summaryrefslogtreecommitdiff
path: root/external/vpc/public
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /external/vpc/public
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'external/vpc/public')
-rw-r--r--external/vpc/public/appframework/iappsystem.h121
-rw-r--r--external/vpc/public/color.h124
-rw-r--r--external/vpc/public/datamap.h521
-rw-r--r--external/vpc/public/filesystem.h958
-rw-r--r--external/vpc/public/filesystem_passthru.h299
-rw-r--r--external/vpc/public/icvar.h211
-rw-r--r--external/vpc/public/ilaunchabledll.h28
-rw-r--r--external/vpc/public/interfaces/interfaces.h287
-rw-r--r--external/vpc/public/mathlib/fltx4.h97
-rw-r--r--external/vpc/public/mathlib/math_pfns.h283
-rw-r--r--external/vpc/public/mathlib/mathlib.h2425
-rw-r--r--external/vpc/public/mathlib/vector.h2633
-rw-r--r--external/vpc/public/mathlib/vector2d.h670
-rw-r--r--external/vpc/public/p4lib/ip4.h191
-rw-r--r--external/vpc/public/tier0/annotations.h116
-rw-r--r--external/vpc/public/tier0/basetypes.h650
-rw-r--r--external/vpc/public/tier0/commonmacros.h149
-rw-r--r--external/vpc/public/tier0/dbg.h716
-rw-r--r--external/vpc/public/tier0/dbgflag.h68
-rw-r--r--external/vpc/public/tier0/etwprof.h155
-rw-r--r--external/vpc/public/tier0/eventmasks.h480
-rw-r--r--external/vpc/public/tier0/eventmodes.h1787
-rw-r--r--external/vpc/public/tier0/fasttimer.h625
-rw-r--r--external/vpc/public/tier0/ia32detect.h383
-rw-r--r--external/vpc/public/tier0/icommandline.h65
-rw-r--r--external/vpc/public/tier0/ioctlcodes.h29
-rw-r--r--external/vpc/public/tier0/k8performancecounters.h2040
-rw-r--r--external/vpc/public/tier0/l2cache.h47
-rw-r--r--external/vpc/public/tier0/logging.h767
-rw-r--r--external/vpc/public/tier0/mem.h50
-rw-r--r--external/vpc/public/tier0/memalloc.h701
-rw-r--r--external/vpc/public/tier0/memdbgoff.h25
-rw-r--r--external/vpc/public/tier0/memdbgon.h281
-rw-r--r--external/vpc/public/tier0/memvirt.h46
-rw-r--r--external/vpc/public/tier0/minidump.h82
-rw-r--r--external/vpc/public/tier0/p4performancecounters.h322
-rw-r--r--external/vpc/public/tier0/p5p6performancecounters.h225
-rw-r--r--external/vpc/public/tier0/platform.h2032
-rw-r--r--external/vpc/public/tier0/pmelib.h212
-rw-r--r--external/vpc/public/tier0/stackstats.h966
-rw-r--r--external/vpc/public/tier0/stacktools.h153
-rw-r--r--external/vpc/public/tier0/threadtools.h2402
-rw-r--r--external/vpc/public/tier0/threadtools.inl629
-rw-r--r--external/vpc/public/tier0/tslist.h858
-rw-r--r--external/vpc/public/tier0/validator.h73
-rw-r--r--external/vpc/public/tier0/valobject.h72
-rw-r--r--external/vpc/public/tier0/valve_off.h33
-rw-r--r--external/vpc/public/tier0/valve_on.h37
-rw-r--r--external/vpc/public/tier0/vprof.h1510
-rw-r--r--external/vpc/public/tier0/vprof_sn.h31
-rw-r--r--external/vpc/public/tier0/wchartypes.h101
-rw-r--r--external/vpc/public/tier0/win32consoleio.h32
-rw-r--r--external/vpc/public/tier0/xbox_codeline_defines.h16
-rw-r--r--external/vpc/public/tier1/byteswap.h268
-rw-r--r--external/vpc/public/tier1/characterset.h43
-rw-r--r--external/vpc/public/tier1/checksum_crc.h31
-rw-r--r--external/vpc/public/tier1/checksum_md5.h33
-rw-r--r--external/vpc/public/tier1/convar.h975
-rw-r--r--external/vpc/public/tier1/convar_serverbounded.h53
-rw-r--r--external/vpc/public/tier1/exprevaluator.h74
-rw-r--r--external/vpc/public/tier1/fmtstr.h179
-rw-r--r--external/vpc/public/tier1/functors.h920
-rw-r--r--external/vpc/public/tier1/generichash.h116
-rw-r--r--external/vpc/public/tier1/iconvar.h121
-rw-r--r--external/vpc/public/tier1/interface.h226
-rw-r--r--external/vpc/public/tier1/keyvalues.h519
-rw-r--r--external/vpc/public/tier1/mempool.h649
-rw-r--r--external/vpc/public/tier1/memstack.h348
-rw-r--r--external/vpc/public/tier1/netadr.h73
-rw-r--r--external/vpc/public/tier1/refcount.h384
-rw-r--r--external/vpc/public/tier1/stringpool.h106
-rw-r--r--external/vpc/public/tier1/strtools.h589
-rw-r--r--external/vpc/public/tier1/tier1.h85
-rw-r--r--external/vpc/public/tier1/utlblockmemory.h349
-rw-r--r--external/vpc/public/tier1/utlbuffer.h1398
-rw-r--r--external/vpc/public/tier1/utldict.h338
-rw-r--r--external/vpc/public/tier1/utlenvelope.h241
-rw-r--r--external/vpc/public/tier1/utlfixedmemory.h354
-rw-r--r--external/vpc/public/tier1/utlgraph.h658
-rw-r--r--external/vpc/public/tier1/utlhash.h1299
-rw-r--r--external/vpc/public/tier1/utllinkedlist.h1087
-rw-r--r--external/vpc/public/tier1/utlmap.h248
-rw-r--r--external/vpc/public/tier1/utlmemory.h1090
-rw-r--r--external/vpc/public/tier1/utlmultilist.h769
-rw-r--r--external/vpc/public/tier1/utlqueue.h176
-rw-r--r--external/vpc/public/tier1/utlrbtree.h1581
-rw-r--r--external/vpc/public/tier1/utlsortvector.h354
-rw-r--r--external/vpc/public/tier1/utlstack.h331
-rw-r--r--external/vpc/public/tier1/utlstring.h373
-rw-r--r--external/vpc/public/tier1/utlsymbol.h345
-rw-r--r--external/vpc/public/tier1/utlvector.h1275
-rw-r--r--external/vpc/public/tier2/tier2.h122
-rw-r--r--external/vpc/public/unitlib/unitlib.h271
-rw-r--r--external/vpc/public/vstdlib/cvar.h25
-rw-r--r--external/vpc/public/vstdlib/ikeyvaluessystem.h56
-rw-r--r--external/vpc/public/vstdlib/pch_vstdlib.h51
-rw-r--r--external/vpc/public/vstdlib/random.h111
-rw-r--r--external/vpc/public/vstdlib/vstdlib.h40
-rw-r--r--external/vpc/public/vstdlib/vstrtools.h275
-rw-r--r--external/vpc/public/winlite.h31
100 files changed, 46854 insertions, 0 deletions
diff --git a/external/vpc/public/appframework/iappsystem.h b/external/vpc/public/appframework/iappsystem.h
new file mode 100644
index 0000000..5375fb0
--- /dev/null
+++ b/external/vpc/public/appframework/iappsystem.h
@@ -0,0 +1,121 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: An application framework
+//
+// $Revision: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef IAPPSYSTEM_H
+#define IAPPSYSTEM_H
+
+#ifdef COMPILER_MSVC
+#pragma once
+#endif
+
+#include "tier1/interface.h"
+#include "interfaces/interfaces.h"
+
+
+//-----------------------------------------------------------------------------
+// Specifies a module + interface name for initialization
+//-----------------------------------------------------------------------------
+struct AppSystemInfo_t
+{
+ const char *m_pModuleName;
+ const char *m_pInterfaceName;
+};
+
+
+//-----------------------------------------------------------------------------
+// Client systems are singleton objects in the client codebase responsible for
+// various tasks
+// The order in which the client systems appear in this list are the
+// order in which they are initialized and updated. They are shut down in
+// reverse order from which they are initialized.
+//-----------------------------------------------------------------------------
+enum InitReturnVal_t
+{
+ INIT_FAILED = 0,
+ INIT_OK,
+
+ INIT_LAST_VAL,
+};
+
+enum AppSystemTier_t
+{
+ APP_SYSTEM_TIER0 = 0,
+ APP_SYSTEM_TIER1,
+ APP_SYSTEM_TIER2,
+ APP_SYSTEM_TIER3,
+
+ APP_SYSTEM_TIER_OTHER,
+};
+
+
+abstract_class IAppSystem
+{
+public:
+ // Here's where the app systems get to learn about each other
+ virtual bool Connect( CreateInterfaceFn factory ) = 0;
+ virtual void Disconnect() = 0;
+
+ // Here's where systems can access other interfaces implemented by this object
+ // Returns NULL if it doesn't implement the requested interface
+ virtual void *QueryInterface( const char *pInterfaceName ) = 0;
+
+ // Init, shutdown
+ virtual InitReturnVal_t Init() = 0;
+ virtual void Shutdown() = 0;
+
+ // Returns all dependent libraries
+ virtual const AppSystemInfo_t* GetDependencies() = 0;
+
+ // Returns the tier
+ virtual AppSystemTier_t GetTier() = 0;
+
+ // Reconnect to a particular interface
+ virtual void Reconnect( CreateInterfaceFn factory, const char *pInterfaceName ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Helper empty implementation of an IAppSystem
+//-----------------------------------------------------------------------------
+template< class IInterface >
+class CBaseAppSystem : public IInterface
+{
+public:
+ // Here's where the app systems get to learn about each other
+ virtual bool Connect( CreateInterfaceFn factory ) { return true; }
+ virtual void Disconnect() {}
+
+ // Here's where systems can access other interfaces implemented by this object
+ // Returns NULL if it doesn't implement the requested interface
+ virtual void *QueryInterface( const char *pInterfaceName ) { return NULL; }
+
+ // Init, shutdown
+ virtual InitReturnVal_t Init() { return INIT_OK; }
+ virtual void Shutdown() {}
+
+ virtual const AppSystemInfo_t* GetDependencies() { return NULL; }
+ virtual AppSystemTier_t GetTier() { return APP_SYSTEM_TIER_OTHER; }
+
+ virtual void Reconnect( CreateInterfaceFn factory, const char *pInterfaceName )
+ {
+ ReconnectInterface( factory, pInterfaceName );
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Helper implementation of an IAppSystem for tier0
+//-----------------------------------------------------------------------------
+template< class IInterface >
+class CTier0AppSystem : public CBaseAppSystem< IInterface >
+{
+};
+
+
+#endif // IAPPSYSTEM_H
+
diff --git a/external/vpc/public/color.h b/external/vpc/public/color.h
new file mode 100644
index 0000000..d84cc11
--- /dev/null
+++ b/external/vpc/public/color.h
@@ -0,0 +1,124 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef COLOR_H
+#define COLOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/basetypes.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Basic handler for an rgb set of colors
+// This class is fully inline
+//-----------------------------------------------------------------------------
+class Color
+{
+public:
+ // constructors
+ Color()
+ {
+ *((int *)this) = 0;
+ }
+ Color(int _r,int _g,int _b)
+ {
+ SetColor(_r, _g, _b, 0);
+ }
+ Color(int _r,int _g,int _b,int _a)
+ {
+ SetColor(_r, _g, _b, _a);
+ }
+
+ // set the color
+ // r - red component (0-255)
+ // g - green component (0-255)
+ // b - blue component (0-255)
+ // a - alpha component, controls transparency (0 - transparent, 255 - opaque);
+ void SetColor(int _r, int _g, int _b, int _a = 0)
+ {
+ _color[0] = (unsigned char)_r;
+ _color[1] = (unsigned char)_g;
+ _color[2] = (unsigned char)_b;
+ _color[3] = (unsigned char)_a;
+ }
+
+ void GetColor(int &_r, int &_g, int &_b, int &_a) const
+ {
+ _r = _color[0];
+ _g = _color[1];
+ _b = _color[2];
+ _a = _color[3];
+ }
+
+ void SetRawColor( int color32 )
+ {
+ *((int *)this) = color32;
+ }
+
+ int GetRawColor() const
+ {
+ return *((int *)this);
+ }
+
+ inline int r() const { return _color[0]; }
+ inline int g() const { return _color[1]; }
+ inline int b() const { return _color[2]; }
+ inline int a() const { return _color[3]; }
+
+ unsigned char &operator[](int index)
+ {
+ return _color[index];
+ }
+
+ const unsigned char &operator[](int index) const
+ {
+ return _color[index];
+ }
+
+ bool operator == (const Color &rhs) const
+ {
+ return ( *((int *)this) == *((int *)&rhs) );
+ }
+
+ bool operator != (const Color &rhs) const
+ {
+ return !(operator==(rhs));
+ }
+
+ Color &operator=( const Color &rhs )
+ {
+ SetRawColor( rhs.GetRawColor() );
+ return *this;
+ }
+
+ Color &operator=( const color32 &rhs )
+ {
+ _color[0] = rhs.r;
+ _color[1] = rhs.g;
+ _color[2] = rhs.b;
+ _color[3] = rhs.a;
+ return *this;
+ }
+
+ color32 ToColor32() const
+ {
+ color32 newColor;
+ newColor.r = _color[0];
+ newColor.g = _color[1];
+ newColor.b = _color[2];
+ newColor.a = _color[3];
+ return newColor;
+ }
+
+private:
+ unsigned char _color[4];
+};
+
+
+#endif // COLOR_H
diff --git a/external/vpc/public/datamap.h b/external/vpc/public/datamap.h
new file mode 100644
index 0000000..941ba51
--- /dev/null
+++ b/external/vpc/public/datamap.h
@@ -0,0 +1,521 @@
+//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef DATAMAP_H
+#define DATAMAP_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#ifndef VECTOR_H
+#include "mathlib/vector.h"
+#endif
+
+#include "tier1/utlvector.h"
+
+#include "tier0/memdbgon.h"
+
+// SINGLE_INHERITANCE restricts the size of CBaseEntity pointers-to-member-functions to 4 bytes
+class SINGLE_INHERITANCE CBaseEntity;
+struct inputdata_t;
+
+#define INVALID_TIME (FLT_MAX * -1.0) // Special value not rebased on save/load
+
+typedef enum _fieldtypes
+{
+ FIELD_VOID = 0, // No type or value
+ FIELD_FLOAT, // Any floating point value
+ FIELD_STRING, // A string ID (return from ALLOC_STRING)
+ FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse
+ FIELD_QUATERNION, // A quaternion
+ FIELD_INTEGER, // Any integer or enum
+ FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression
+ FIELD_SHORT, // 2 byte integer
+ FIELD_CHARACTER, // a byte
+ FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color)
+ FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded class/structure based on an additional typedescription
+ FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse functions
+
+ FIELD_CLASSPTR, // CBaseEntity *
+ FIELD_EHANDLE, // Entity handle
+ FIELD_EDICT, // edict_t *
+
+ FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically)
+ FIELD_TIME, // a floating point time (these are fixed up automatically too!)
+ FIELD_TICK, // an integer tick count( fixed up similarly to time)
+ FIELD_MODELNAME, // Engine string that is a model name (needs precache)
+ FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache)
+
+ FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar)
+ FIELD_FUNCTION, // A class function pointer (Think, Use, etc)
+
+ FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace)
+
+ // NOTE: Use float arrays for local transformations that don't need to be fixed up.
+ FIELD_VMATRIX_WORLDSPACE,// A VMatrix that maps some local space to world space (translation is fixed up on level transitions)
+ FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space (translation is fixed up on level transitions)
+
+ FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 )
+ FIELD_MODELINDEX, // a model index
+ FIELD_MATERIALINDEX, // a material index (using the material precache string table)
+
+ FIELD_VECTOR2D, // 2 floats
+ FIELD_INTEGER64, // 64bit integer
+
+ FIELD_VECTOR4D, // 4 floats
+
+ FIELD_TYPECOUNT, // MUST BE LAST
+} fieldtype_t;
+
+
+//-----------------------------------------------------------------------------
+// Field sizes...
+//-----------------------------------------------------------------------------
+template <int FIELD_TYPE>
+class CDatamapFieldSizeDeducer
+{
+public:
+ enum
+ {
+ SIZE = 0
+ };
+
+ static int FieldSize( )
+ {
+ return 0;
+ }
+};
+
+#define DECLARE_FIELD_SIZE( _fieldType, _fieldSize ) \
+ template< > class CDatamapFieldSizeDeducer<_fieldType> { public: enum { SIZE = _fieldSize }; static int FieldSize() { return _fieldSize; } };
+#define FIELD_SIZE( _fieldType ) CDatamapFieldSizeDeducer<_fieldType>::SIZE
+#define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8)
+
+DECLARE_FIELD_SIZE( FIELD_FLOAT, sizeof(float) )
+DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(int) )
+DECLARE_FIELD_SIZE( FIELD_VECTOR, 3 * sizeof(float) )
+DECLARE_FIELD_SIZE( FIELD_VECTOR2D, 2 * sizeof(float) )
+DECLARE_FIELD_SIZE( FIELD_VECTOR4D, 4 * sizeof( float ) )
+DECLARE_FIELD_SIZE( FIELD_QUATERNION, 4 * sizeof(float))
+DECLARE_FIELD_SIZE( FIELD_INTEGER, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_INTEGER64, sizeof(int64))
+DECLARE_FIELD_SIZE( FIELD_BOOLEAN, sizeof(char))
+DECLARE_FIELD_SIZE( FIELD_SHORT, sizeof(short))
+DECLARE_FIELD_SIZE( FIELD_CHARACTER, sizeof(char))
+DECLARE_FIELD_SIZE( FIELD_COLOR32, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_EDICT, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_POSITION_VECTOR, 3 * sizeof(float))
+DECLARE_FIELD_SIZE( FIELD_TIME, sizeof(float))
+DECLARE_FIELD_SIZE( FIELD_TICK, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(int))
+DECLARE_FIELD_SIZE( FIELD_INPUT, sizeof(int))
+#if defined(_WIN32)
+DECLARE_FIELD_SIZE( FIELD_FUNCTION, sizeof(void *))
+#elif defined(POSIX)
+// pointer to members under gnuc are 8bytes if you have a virtual func
+DECLARE_FIELD_SIZE( FIELD_FUNCTION, 2 * sizeof(void *))
+#else
+#error
+#endif
+DECLARE_FIELD_SIZE( FIELD_VMATRIX, 16 * sizeof(float))
+DECLARE_FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE, 16 * sizeof(float))
+DECLARE_FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE, 12 * sizeof(float))
+DECLARE_FIELD_SIZE( FIELD_INTERVAL, 2 * sizeof( float) ) // NOTE: Must match interval.h definition
+DECLARE_FIELD_SIZE( FIELD_MODELINDEX, sizeof(int) )
+DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX, sizeof(int) )
+
+
+#define ARRAYSIZE2D(p) (sizeof(p)/sizeof(p[0][0]))
+#define SIZE_OF_ARRAY(p) _ARRAYSIZE(p)
+
+#define _FIELD(name,fieldtype,count,flags,mapname,tolerance) { fieldtype, #name, offsetof(classNameTypedef, name), count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance }
+#define DEFINE_FIELD_NULL { FIELD_VOID,0,0,0,0,0,0,0,0}
+#define DEFINE_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_SAVE, NULL, 0 )
+#define DEFINE_FIELD_NOT_SAVED(name,fieldtype) _FIELD(name, fieldtype, 1, 0, NULL, 0 )
+
+#define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
+#define DEFINE_KEYFIELD_NOT_SAVED(name,fieldtype, mapname)_FIELD(name, fieldtype, 1, FTYPEDESC_KEY, mapname, 0 )
+#define DEFINE_AUTO_ARRAY(name,fieldtype) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
+#define DEFINE_AUTO_ARRAY_KEYFIELD(name,fieldtype,mapname) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, mapname, 0 )
+#define DEFINE_ARRAY(name,fieldtype, count) _FIELD(name, fieldtype, count, FTYPEDESC_SAVE, NULL, 0 )
+#define DEFINE_ARRAY_NOT_SAVED(name,fieldtype, count) _FIELD(name, fieldtype, count, 0, NULL, 0 )
+#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, #name, 0 )
+#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 )
+#define DEFINE_GLOBAL_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 )
+#define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
+#define DEFINE_CUSTOM_FIELD(name,datafuncs) { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL }
+#define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname) { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL }
+#define DEFINE_AUTO_ARRAY2D(name,fieldtype) _FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
+// Used by byteswap datadescs
+#define DEFINE_BITFIELD(name,fieldtype,bitcount) DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) )
+#define DEFINE_INDEX(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_INDEX, NULL, 0 )
+
+#define DEFINE_EMBEDDED( name ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
+
+#define DEFINE_EMBEDDED_OVERRIDE( name, overridetype ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
+
+#define DEFINE_EMBEDDEDBYREF( name ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f }
+
+#define DEFINE_EMBEDDED_ARRAY( name, count ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f }
+
+#define DEFINE_EMBEDDED_AUTO_ARRAY( name ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f }
+
+#ifndef NO_ENTITY_PREDICTION
+
+// FTYPEDESC_KEY tells the prediction copy system to report the full nameof the field when reporting errors
+#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, NULL, NULL, NULL, &fieldtype::m_PredMap }
+
+#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) \
+ { FIELD_EMBEDDED, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE | FTYPEDESC_PTR | FTYPEDESC_KEY, NULL, NULL, NULL, &fieldtype::m_PredMap }
+
+#else
+
+#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) DEFINE_FIELD_NULL
+#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) DEFINE_FIELD_NULL
+
+#endif
+
+// Extensions to datamap.h macros for predicted entities only
+#define DEFINE_PRED_FIELD(name,fieldtype, flags) _FIELD(name, fieldtype, 1, flags, NULL, 0.0f )
+#define DEFINE_PRED_ARRAY(name,fieldtype, count,flags) _FIELD(name, fieldtype, count, flags, NULL, 0.0f )
+#define DEFINE_FIELD_NAME(localname,netname,fieldtype) _FIELD(localname, fieldtype, 1, 0, #netname, 0.0f )
+// Predictable macros, which include a tolerance for floating point values...
+#define DEFINE_PRED_FIELD_TOL(name,fieldtype, flags,tolerance) _FIELD(name, fieldtype, 1, flags, NULL, tolerance )
+#define DEFINE_PRED_ARRAY_TOL(name,fieldtype, count,flags,tolerance) _FIELD(name, fieldtype, count, flags, NULL, tolerance)
+#define DEFINE_FIELD_NAME_TOL(localname,netname,fieldtolerance) _FIELD(localname, fieldtype, 1, 0, #netname, tolerance )
+
+//#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1, flags, extname )
+
+// INPUTS
+#define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) }
+#define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, NULL, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast <inputfunc_t> (&classNameTypedef::inputfunc) }
+
+// OUTPUTS
+// the variable 'name' MUST BE derived from CBaseOutput
+// we know the output type from the variable itself, so it doesn't need to be specified here
+class ISaveRestoreOps;
+extern ISaveRestoreOps *eventFuncs;
+#define DEFINE_OUTPUT( name, outputname ) { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs }
+
+// replaces EXPORT table for portability and non-DLL based systems (xbox)
+#define DEFINE_FUNCTION_RAW( function, func_type ) { FIELD_VOID, nameHolder.GenerateName(#function), NULL, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) }
+#define DEFINE_FUNCTION( function ) DEFINE_FUNCTION_RAW( function, inputfunc_t )
+
+
+#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore
+#define FTYPEDESC_SAVE 0x0002 // This field is saved to disk
+#define FTYPEDESC_KEY 0x0004 // This field can be requested and written to by string name at load time
+#define FTYPEDESC_INPUT 0x0008 // This field can be written to by string name at run time, and a function called
+#define FTYPEDESC_OUTPUT 0x0010 // This field propagates its value to all targets whenever it changes
+#define FTYPEDESC_FUNCTIONTABLE 0x0020 // This is a table entry for a member function pointer
+#define FTYPEDESC_PTR 0x0040 // This field is a pointer, not an embedded object
+#define FTYPEDESC_OVERRIDE 0x0080 // The field is an override for one in a base class (only used by prediction system for now)
+
+// Flags used by other systems (e.g., prediction system)
+#define FTYPEDESC_INSENDTABLE 0x0100 // This field is present in a network SendTable
+#define FTYPEDESC_PRIVATE 0x0200 // The field is local to the client or server only (not referenced by prediction code and not replicated by networking)
+#define FTYPEDESC_NOERRORCHECK 0x0400 // The field is part of the prediction typedescription, but doesn't get compared when checking for errors
+
+#define FTYPEDESC_MODELINDEX 0x0800 // The field is a model index (used for debugging output)
+
+#define FTYPEDESC_INDEX 0x1000 // The field is an index into file data, used for byteswapping.
+
+// These flags apply to C_BasePlayer derived objects only
+#define FTYPEDESC_VIEW_OTHER_PLAYER 0x2000 // By default you can only view fields on the local player (yourself),
+ // but if this is set, then we allow you to see fields on other players
+#define FTYPEDESC_VIEW_OWN_TEAM 0x4000 // Only show this data if the player is on the same team as the local player
+#define FTYPEDESC_VIEW_NEVER 0x8000 // Never show this field to anyone, even the local player (unusual)
+
+#define TD_MSECTOLERANCE 0.001f // This is a FIELD_FLOAT and should only be checked to be within 0.001 of the networked info
+
+struct typedescription_t;
+
+
+class ISaveRestoreOps;
+
+//
+// Function prototype for all input handlers.
+//
+typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data);
+
+struct datamap_t;
+struct typedescription_t;
+
+enum
+{
+ PC_NON_NETWORKED_ONLY = 0,
+ PC_NETWORKED_ONLY,
+
+ PC_COPYTYPE_COUNT,
+ PC_EVERYTHING = PC_COPYTYPE_COUNT,
+};
+
+enum
+{
+ TD_OFFSET_NORMAL = 0,
+ TD_OFFSET_PACKED = 1,
+
+ // Must be last
+ TD_OFFSET_COUNT,
+};
+
+struct typedescription_t
+{
+ fieldtype_t fieldType;
+ const char *fieldName;
+ int fieldOffset; // Local offset value
+ unsigned short fieldSize;
+ short flags;
+ // the name of the variable in the map/fgd data, or the name of the action
+ const char *externalName;
+ // pointer to the function set for save/restoring of custom data types
+ ISaveRestoreOps *pSaveRestoreOps;
+ // for associating function with string names
+ inputfunc_t inputFunc;
+ // For embedding additional datatables inside this one
+ datamap_t *td;
+
+ // Stores the actual member variable size in bytes
+ int fieldSizeInBytes;
+
+ // FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred
+ struct typedescription_t *override_field;
+
+ // Used to track exclusion of baseclass fields
+ int override_count;
+
+ // Tolerance for field errors for float fields
+ float fieldTolerance;
+
+ // For raw fields (including children of embedded stuff) this is the flattened offset
+ int flatOffset[ TD_OFFSET_COUNT ];
+ unsigned short flatGroup;
+};
+
+// See predictioncopy.h for implementation and notes
+struct optimized_datamap_t;
+
+//-----------------------------------------------------------------------------
+// Purpose: stores the list of objects in the hierarchy
+// used to iterate through an object's data descriptions
+//-----------------------------------------------------------------------------
+struct datamap_t
+{
+ typedescription_t *dataDesc;
+ int dataNumFields;
+ char const *dataClassName;
+ datamap_t *baseMap;
+
+ int m_nPackedSize;
+ optimized_datamap_t *m_pOptimizedDataMap;
+
+#if defined( _DEBUG )
+ bool bValidityChecked;
+#endif // _DEBUG
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// Macros used to implement datadescs
+//
+#define DECLARE_FRIEND_DATADESC_ACCESS() \
+ template <typename T> friend void DataMapAccess(T *, datamap_t **p); \
+ template <typename T> friend datamap_t *DataMapInit(T *);
+
+#define DECLARE_SIMPLE_DATADESC() \
+ static datamap_t m_DataMap; \
+ static datamap_t *GetBaseMap(); \
+ template <typename T> friend void DataMapAccess(T *, datamap_t **p); \
+ template <typename T> friend datamap_t *DataMapInit(T *);
+
+#if defined(POSIX) && !defined(_PS3)
+
+#define DECLARE_SIMPLE_DATADESC_INSIDE_NAMESPACE() \
+ static datamap_t m_DataMap; \
+ static datamap_t *GetBaseMap(); \
+ template <typename T> friend void ::DataMapAccess(T *, datamap_t **p);
+
+#else
+#define DECLARE_SIMPLE_DATADESC_INSIDE_NAMESPACE() \
+ static datamap_t m_DataMap; \
+ static datamap_t *GetBaseMap(); \
+ template <typename T> friend void ::DataMapAccess(T *, datamap_t **p); \
+ template <typename T> friend datamap_t *::DataMapInit(T *);
+
+#endif
+
+#define DECLARE_DATADESC() \
+ DECLARE_SIMPLE_DATADESC() \
+ virtual datamap_t *GetDataDescMap( void );
+
+#define BEGIN_DATADESC( className ) \
+ datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
+ datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \
+ datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
+ BEGIN_DATADESC_GUTS( className )
+
+#define BEGIN_DATADESC_NO_BASE( className ) \
+ datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
+ datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \
+ datamap_t *className::GetBaseMap() { return NULL; } \
+ BEGIN_DATADESC_GUTS( className )
+
+#define BEGIN_SIMPLE_DATADESC( className ) \
+ datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
+ datamap_t *className::GetBaseMap() { return NULL; } \
+ BEGIN_DATADESC_GUTS( className )
+
+#define BEGIN_SIMPLE_DATADESC_( className, BaseClass ) \
+ datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
+ datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
+ BEGIN_DATADESC_GUTS( className )
+
+#define BEGIN_DATADESC_GUTS( className ) \
+ template <typename T> datamap_t *DataMapInit(T *); \
+ template <> datamap_t *DataMapInit<className>( className * ); \
+ namespace className##_DataDescInit \
+ { \
+ datamap_t *g_DataMapHolder = DataMapInit<className>( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
+ } \
+ \
+ template <> datamap_t *DataMapInit<className>( className * ) \
+ { \
+ typedef className classNameTypedef; \
+ static CDatadescGeneratedNameHolder nameHolder(#className); \
+ className::m_DataMap.baseMap = className::GetBaseMap(); \
+ static typedescription_t dataDesc[] = \
+ { \
+ { FIELD_VOID,0,0,0,0,0,0,0,0}, /* so you can define "empty" tables */
+
+
+#define BEGIN_DATADESC_GUTS_NAMESPACE( className, nameSpace ) \
+ template <typename T> datamap_t *nameSpace::DataMapInit(T *); \
+ template <> datamap_t *nameSpace::DataMapInit<className>( className * ); \
+ namespace className##_DataDescInit \
+ { \
+ datamap_t *g_DataMapHolder = nameSpace::DataMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
+ } \
+ \
+ template <> datamap_t *nameSpace::DataMapInit<className>( className * ) \
+ { \
+ typedef className classNameTypedef; \
+ static CDatadescGeneratedNameHolder nameHolder(#className); \
+ className::m_DataMap.baseMap = className::GetBaseMap(); \
+ static typedescription_t dataDesc[] = \
+ { \
+ { FIELD_VOID,0,0,0,0,0,0,0,0}, /* so you can define "empty" tables */
+
+#define END_DATADESC() \
+ }; \
+ \
+ if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \
+ { \
+ classNameTypedef::m_DataMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \
+ classNameTypedef::m_DataMap.dataDesc = &dataDesc[1]; \
+ } \
+ else \
+ { \
+ classNameTypedef::m_DataMap.dataNumFields = 1; \
+ classNameTypedef::m_DataMap.dataDesc = dataDesc; \
+ } \
+ return &classNameTypedef::m_DataMap; \
+ }
+
+// used for when there is no data description
+#define IMPLEMENT_NULL_SIMPLE_DATADESC( derivedClass ) \
+ BEGIN_SIMPLE_DATADESC( derivedClass ) \
+ END_DATADESC()
+
+#define IMPLEMENT_NULL_SIMPLE_DATADESC_( derivedClass, baseClass ) \
+ BEGIN_SIMPLE_DATADESC_( derivedClass, baseClass ) \
+ END_DATADESC()
+
+#define IMPLEMENT_NULL_DATADESC( derivedClass ) \
+ BEGIN_DATADESC( derivedClass ) \
+ END_DATADESC()
+
+// helps get the offset of a bitfield
+#define BEGIN_BITFIELD( name ) \
+ union \
+ { \
+ char name; \
+ struct \
+ {
+
+#define END_BITFIELD() \
+ }; \
+ };
+
+//-----------------------------------------------------------------------------
+// Forward compatability with potential seperate byteswap datadescs
+
+#define DECLARE_BYTESWAP_DATADESC() DECLARE_SIMPLE_DATADESC()
+#define BEGIN_BYTESWAP_DATADESC(name) BEGIN_SIMPLE_DATADESC(name)
+#define BEGIN_BYTESWAP_DATADESC_(name,base) BEGIN_SIMPLE_DATADESC_(name,base)
+#define END_BYTESWAP_DATADESC() END_DATADESC()
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline void DataMapAccess(T *ignored, datamap_t **p)
+{
+ *p = &T::m_DataMap;
+}
+
+//-----------------------------------------------------------------------------
+
+class CDatadescGeneratedNameHolder
+{
+public:
+ CDatadescGeneratedNameHolder( const char *pszBase )
+ : m_pszBase(pszBase)
+ {
+ m_nLenBase = strlen( m_pszBase );
+ }
+
+ ~CDatadescGeneratedNameHolder()
+ {
+ for ( int i = 0; i < m_Names.Count(); i++ )
+ {
+ delete m_Names[i];
+ }
+ }
+
+ const char *GenerateName( const char *pszIdentifier )
+ {
+ char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1];
+ strcpy( pBuf, m_pszBase );
+ strcat( pBuf, pszIdentifier );
+ m_Names.AddToTail( pBuf );
+ return pBuf;
+ }
+
+private:
+ const char *m_pszBase;
+ size_t m_nLenBase;
+ CUtlVector<char *> m_Names;
+};
+
+//-----------------------------------------------------------------------------
+
+// Compiler can require the global-namespace template friend to be declared
+// before DECLARE_SIMPLE_DATADESC_INSIDE_NAMESPACE() can be used
+template <typename T> datamap_t *DataMapInit(T *);
+
+#include "tier0/memdbgoff.h"
+
+#endif // DATAMAP_H
diff --git a/external/vpc/public/filesystem.h b/external/vpc/public/filesystem.h
new file mode 100644
index 0000000..81d4d98
--- /dev/null
+++ b/external/vpc/public/filesystem.h
@@ -0,0 +1,958 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef FILESYSTEM_H
+#define FILESYSTEM_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <limits.h>
+
+#include "tier0/threadtools.h"
+#include "tier0/memalloc.h"
+#include "tier0/tslist.h"
+#include "tier1/interface.h"
+#include "tier1/utlsymbol.h"
+#include "tier1/utlstring.h"
+#include "tier1/functors.h"
+#include "tier1/checksum_crc.h"
+#include "tier1/utlqueue.h"
+#include "appframework/iappsystem.h"
+#include "tier2/tier2.h"
+#ifdef _PS3
+#include <sysutil/sysutil_syscache.h>
+#include <sysutil/sysutil_gamecontent.h>
+struct HddCacheFileStatus;
+extern char gSrcGameDataPath[];
+class CFileGroupSystem;
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+
+class CUtlBuffer;
+class KeyValues;
+class IFileList;
+
+typedef void * FileHandle_t;
+typedef int FileFindHandle_t;
+typedef void (*FileSystemLoggingFunc_t)( const char *fileName, const char *accessType );
+typedef int WaitForResourcesHandle_t;
+
+#ifdef _X360
+typedef void* HANDLE;
+#endif
+
+//-----------------------------------------------------------------------------
+// Enums used by the interface
+//-----------------------------------------------------------------------------
+
+#define FILESYSTEM_MAX_SEARCH_PATHS 128
+
+enum FileSystemSeek_t
+{
+ FILESYSTEM_SEEK_HEAD = SEEK_SET,
+ FILESYSTEM_SEEK_CURRENT = SEEK_CUR,
+ FILESYSTEM_SEEK_TAIL = SEEK_END,
+};
+
+enum
+{
+ FILESYSTEM_INVALID_FIND_HANDLE = -1
+};
+
+enum FileWarningLevel_t
+{
+ // A problem!
+ FILESYSTEM_WARNING = -1,
+
+ // Don't print anything
+ FILESYSTEM_WARNING_QUIET = 0,
+
+ // On shutdown, report names of files left unclosed
+ FILESYSTEM_WARNING_REPORTUNCLOSED,
+
+ // Report number of times a file was opened, closed
+ FILESYSTEM_WARNING_REPORTUSAGE,
+
+ // Report all open/close events to console ( !slow! )
+ FILESYSTEM_WARNING_REPORTALLACCESSES,
+
+ // Report all open/close/read events to the console ( !slower! )
+ FILESYSTEM_WARNING_REPORTALLACCESSES_READ,
+
+ // Report all open/close/read/write events to the console ( !slower! )
+ FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE,
+
+ // Report all open/close/read/write events and all async I/O file events to the console ( !slower(est)! )
+ FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC,
+
+};
+
+// search path filtering
+enum PathTypeFilter_t
+{
+ FILTER_NONE = 0, // no filtering, all search path types match
+ FILTER_CULLPACK = 1, // pack based search paths are culled (maps and zips)
+ FILTER_CULLNONPACK = 2, // non-pack based search paths are culled
+ FILTER_CULLLOCALIZED = 3, // Ignore localized paths, assumes CULLNONPACK
+ FILTER_CULLLOCALIZED_ANY = 4, // Ignore any localized paths
+};
+
+// search path querying (bit flags)
+enum
+{
+ PATH_IS_NORMAL = 0x00, // normal path, not pack based
+ PATH_IS_PACKFILE = 0x01, // path is a pack file
+ PATH_IS_MAPPACKFILE = 0x02, // path is a map pack file
+ PATH_IS_DVDDEV = 0x04, // path is the dvddev cache
+};
+typedef uint32 PathTypeQuery_t;
+
+#define IS_PACKFILE( n ) ( n & ( PATH_IS_PACKFILE | PATH_IS_MAPPACKFILE ) )
+#define IS_DVDDEV( n ) ( n & PATH_IS_DVDDEV )
+
+enum DVDMode_t
+{
+ DVDMODE_OFF = 0, // not using dvd
+ DVDMODE_STRICT = 1, // dvd device only
+ DVDMODE_DEV = 2, // dev mode, mutiple devices ok
+ DVDMODE_DEV_VISTA = 3, // dev mode from a vista host, mutiple devices ok
+};
+
+#ifdef _PS3
+
+enum FsState_t
+{
+ FS_STATE_INIT = 0,
+ FS_STATE_LEVEL_LOAD = 1,
+ FS_STATE_LEVEL_RUN = 2,
+ FS_STATE_LEVEL_RESTORE = 3,
+ FS_STATE_LEVEL_LOAD_END = 4,
+ FS_STATE_EXITING = 5
+};
+
+enum Ps3FileType_t
+{
+ PS3_FILETYPE_WAV,
+ PS3_FILETYPE_ANI,
+ PS3_FILETYPE_BSP,
+ PS3_FILETYPE_VMT,
+ PS3_FILETYPE_QPRE,
+ PS3_FILETYPE_OTHER,
+ PS3_FILETYPE_DIR,
+ PS3_FILETYPE_UNKNOWN
+};
+
+
+#endif
+
+// In non-retail builds, enable the file blocking access tracking stuff...
+#if defined( TRACK_BLOCKING_IO )
+enum FileBlockingWarning_t
+{
+ // Report how long synchronous i/o took to complete
+ FILESYSTEM_BLOCKING_SYNCHRONOUS = 0,
+ // Report how long async i/o took to complete if AsyncFileFinished caused it to load via "blocking" i/o
+ FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK,
+ // Report how long async i/o took to complete
+ FILESYSTEM_BLOCKING_ASYNCHRONOUS,
+ // Report how long the async "callback" took
+ FILESYSTEM_BLOCKING_CALLBACKTIMING,
+
+ FILESYSTEM_BLOCKING_NUMBINS,
+};
+
+#pragma pack(1)
+class FileBlockingItem
+{
+public:
+ enum
+ {
+ FB_ACCESS_OPEN = 1,
+ FB_ACCESS_CLOSE = 2,
+ FB_ACCESS_READ = 3,
+ FB_ACCESS_WRITE = 4,
+ FB_ACCESS_APPEND = 5,
+ FB_ACCESS_SIZE = 6
+ };
+
+ FileBlockingItem() :
+ m_ItemType( (FileBlockingWarning_t)0 ),
+ m_flElapsed( 0.0f ),
+ m_nAccessType( 0 )
+ {
+ SetFileName( NULL );
+ }
+
+ FileBlockingItem( int type, char const *filename, float elapsed, int accessType ) :
+ m_ItemType( (FileBlockingWarning_t)type ),
+ m_flElapsed( elapsed ),
+ m_nAccessType( accessType )
+ {
+ SetFileName( filename );
+ }
+
+ void SetFileName( char const *filename )
+ {
+ if ( !filename )
+ {
+ m_szFilename[ 0 ] = 0;
+ return;
+ }
+
+ int len = V_strlen( filename );
+ if ( len >= sizeof( m_szFilename ) )
+ {
+ V_strncpy( m_szFilename, &filename[ len - sizeof( m_szFilename ) + 1 ], sizeof( m_szFilename ) );
+ }
+ else
+ {
+ V_strncpy( m_szFilename, filename, sizeof( m_szFilename ) );
+ }
+ }
+
+ char const *GetFileName() const
+ {
+ return m_szFilename;
+ }
+
+ FileBlockingWarning_t m_ItemType;
+ float m_flElapsed;
+ byte m_nAccessType;
+private:
+
+ char m_szFilename[ 32 ];
+};
+#pragma pack()
+
+class IBlockingFileItemList
+{
+public:
+
+ // You can't call any of the below calls without locking first
+ virtual void LockMutex() = 0;
+ virtual void UnlockMutex() = 0;
+
+ virtual int First() const = 0;
+ virtual int Next( int i ) const = 0;
+ virtual int InvalidIndex() const = 0;
+
+ virtual const FileBlockingItem& Get( int index ) const = 0;
+
+ virtual void Reset() = 0;
+};
+
+#endif // TRACK_BLOCKING_IO
+
+enum FilesystemMountRetval_t
+{
+ FILESYSTEM_MOUNT_OK = 0,
+ FILESYSTEM_MOUNT_FAILED,
+};
+
+enum SearchPathAdd_t
+{
+ PATH_ADD_TO_HEAD, // First path searched
+ PATH_ADD_TO_TAIL, // Last path searched
+ PATH_ADD_TO_TAIL_ATINDEX, // First path searched
+};
+
+enum FilesystemOpenExFlags_t
+{
+ FSOPEN_UNBUFFERED = (1 << 0),
+ FSOPEN_FORCE_TRACK_CRC = (1 << 1), // This makes it calculate a CRC for the file (if the file came from disk) regardless
+ // of the IFileList passed to RegisterFileWhitelist.
+ FSOPEN_NEVERINPACK = (1 << 2), // 360 only, hint to FS that file is not allowed to be in pack file
+};
+
+#define FILESYSTEM_INVALID_HANDLE ( FileHandle_t )0
+
+//-----------------------------------------------------------------------------
+// Structures used by the interface
+//-----------------------------------------------------------------------------
+
+struct FileSystemStatistics
+{
+ CInterlockedUInt nReads,
+ nWrites,
+ nBytesRead,
+ nBytesWritten,
+ nSeeks;
+};
+
+//-----------------------------------------------------------------------------
+// File system allocation functions. Client must free on failure
+//-----------------------------------------------------------------------------
+typedef void *(*FSAllocFunc_t)( const char *pszFilename, unsigned nBytes );
+
+
+//-----------------------------------------------------------------------------
+// Used to display dirty disk error functions
+//-----------------------------------------------------------------------------
+typedef void (*FSDirtyDiskReportFunc_t)();
+
+
+//-----------------------------------------------------------------------------
+// Asynchronous support types
+//-----------------------------------------------------------------------------
+DECLARE_POINTER_HANDLE(FSAsyncControl_t);
+DECLARE_POINTER_HANDLE(FSAsyncFile_t);
+const FSAsyncFile_t FS_INVALID_ASYNC_FILE = (FSAsyncFile_t)(0x0000ffff);
+
+
+//---------------------------------------------------------
+// Async file status
+//---------------------------------------------------------
+enum FSAsyncStatus_t
+{
+ FSASYNC_ERR_ALIGNMENT = -6, // read parameters invalid for unbuffered IO
+ FSASYNC_ERR_FAILURE = -5, // hard subsystem failure
+ FSASYNC_ERR_READING = -4, // read error on file
+ FSASYNC_ERR_NOMEMORY = -3, // out of memory for file read
+ FSASYNC_ERR_UNKNOWNID = -2, // caller's provided id is not recognized
+ FSASYNC_ERR_FILEOPEN = -1, // filename could not be opened (bad path, not exist, etc)
+ FSASYNC_OK = 0, // operation is successful
+ FSASYNC_STATUS_PENDING, // file is properly queued, waiting for service
+ FSASYNC_STATUS_INPROGRESS, // file is being accessed
+ FSASYNC_STATUS_ABORTED, // file was aborted by caller
+ FSASYNC_STATUS_UNSERVICED, // file is not yet queued
+};
+
+//---------------------------------------------------------
+// Async request flags
+//---------------------------------------------------------
+enum FSAsyncFlags_t
+{
+ FSASYNC_FLAGS_ALLOCNOFREE = ( 1 << 0 ), // do the allocation for dataPtr, but don't free
+ FSASYNC_FLAGS_FREEDATAPTR = ( 1 << 1 ), // free the memory for the dataPtr post callback
+ FSASYNC_FLAGS_SYNC = ( 1 << 2 ), // Actually perform the operation synchronously. Used to simplify client code paths
+ FSASYNC_FLAGS_NULLTERMINATE = ( 1 << 3 ), // allocate an extra byte and null terminate the buffer read in
+};
+
+//---------------------------------------------------------
+// Return value for CheckFileCRC.
+//---------------------------------------------------------
+enum EFileCRCStatus
+{
+ k_eFileCRCStatus_CantOpenFile, // We don't have this file.
+ k_eFileCRCStatus_GotCRC
+};
+
+// Used in CacheFileCRCs.
+enum ECacheCRCType
+{
+ k_eCacheCRCType_SingleFile,
+ k_eCacheCRCType_Directory,
+ k_eCacheCRCType_Directory_Recursive
+};
+
+//---------------------------------------------------------
+// Optional completion callback for each async file serviced (or failed)
+// call is not reentrant, async i/o guaranteed suspended until return
+// Note: If you change the signature of the callback, you will have to account for it in FileSystemV12 (toml [4/18/2005] )
+//---------------------------------------------------------
+struct FileAsyncRequest_t;
+typedef void (*FSAsyncCallbackFunc_t)(const FileAsyncRequest_t &request, int nBytesRead, FSAsyncStatus_t err);
+
+//-----------------------------------------------------------------------------
+// Used to add results from async directory scans
+//-----------------------------------------------------------------------------
+typedef void (*FSAsyncScanAddFunc_t)( void* pContext, char* pFoundPath, char* pFoundFile );
+typedef void (*FSAsyncScanCompleteFunc_t)( void* pContext, FSAsyncStatus_t err );
+
+//---------------------------------------------------------
+// Description of an async request
+//---------------------------------------------------------
+struct FileAsyncRequest_t
+{
+ FileAsyncRequest_t() { memset( this, 0, sizeof(*this) ); hSpecificAsyncFile = FS_INVALID_ASYNC_FILE; }
+ const char * pszFilename; // file system name
+ void * pData; // optional, system will alloc/free if NULL
+ int nOffset; // optional initial seek_set, 0=beginning
+ int nBytes; // optional read clamp, -1=exist test, 0=full read
+ FSAsyncCallbackFunc_t pfnCallback; // optional completion callback
+ void * pContext; // caller's unique file identifier
+ int priority; // inter list priority, 0=lowest
+ unsigned flags; // behavior modifier
+ const char * pszPathID; // path ID (NOTE: this field is here to remain binary compatible with release HL2 filesystem interface)
+ FSAsyncFile_t hSpecificAsyncFile; // Optional hint obtained using AsyncBeginRead()
+ FSAllocFunc_t pfnAlloc; // custom allocator. can be null. not compatible with FSASYNC_FLAGS_FREEDATAPTR
+};
+
+
+class CUnverifiedCRCFile
+{
+public:
+ char m_PathID[MAX_PATH];
+ char m_Filename[MAX_PATH];
+ CRC32_t m_CRC;
+};
+
+
+// Spew flags for SetWhitelistSpewFlags (set with the fs_whitelist_spew_flags cvar).
+// Update the comment for the fs_whitelist_spew_flags cvar if you change these.
+#define WHITELIST_SPEW_WHILE_LOADING 0x0001 // list files as they are added to the CRC tracker
+#define WHITELIST_SPEW_RELOAD_FILES 0x0002 // show files the filesystem is telling the engine to reload
+#define WHITELIST_SPEW_DONT_RELOAD_FILES 0x0004 // show files the filesystem is NOT telling the engine to reload
+
+
+
+// DLC license mask flags is 32 publisher defined bits
+// MSW 16 bits in 8.8: Type.SubVersion
+// LSW 16 bits: Flags
+
+// return id component
+#define DLC_LICENSE_ID( x ) ( ( ( (unsigned int)( x ) ) >> 24 ) & 0x000000FF )
+// returns minor version component (not generally used, i.e. we dont rev dlc's yet)
+#define DLC_LICENSE_MINORVERSION( x ) ( ( ( (unsigned int)( x ) ) >> 16 ) & 0x000000FF )
+// returns license flags
+#define DLC_LICENSE_FLAGS( x ) ( ( ( (unsigned int)( x ) ) & 0x0000FFFF ) )
+
+#define DLCFLAGS_PRESENCE_ONLY 0x0001 // causes no search path loadout
+
+
+
+//-----------------------------------------------------------------------------
+// Base file system interface
+//-----------------------------------------------------------------------------
+
+// This is the minimal interface that can be implemented to provide access to
+// a named set of files.
+#define BASEFILESYSTEM_INTERFACE_VERSION "VBaseFileSystem011"
+
+abstract_class IBaseFileSystem
+{
+public:
+ virtual int Read( void* pOutput, int size, FileHandle_t file ) = 0;
+ virtual int Write( void const* pInput, int size, FileHandle_t file ) = 0;
+
+ // if pathID is NULL, all paths will be searched for the file
+ virtual FileHandle_t Open( const char *pFileName, const char *pOptions, const char *pathID = 0 ) = 0;
+ virtual void Close( FileHandle_t file ) = 0;
+
+
+ virtual void Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType ) = 0;
+ virtual unsigned int Tell( FileHandle_t file ) = 0;
+ virtual unsigned int Size( FileHandle_t file ) = 0;
+ virtual unsigned int Size( const char *pFileName, const char *pPathID = 0 ) = 0;
+
+ virtual void Flush( FileHandle_t file ) = 0;
+ virtual bool Precache( const char *pFileName, const char *pPathID = 0 ) = 0;
+
+ virtual bool FileExists( const char *pFileName, const char *pPathID = 0 ) = 0;
+ virtual bool IsFileWritable( char const *pFileName, const char *pPathID = 0 ) = 0;
+ virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID = 0 ) = 0;
+
+ virtual long GetFileTime( const char *pFileName, const char *pPathID = 0 ) = 0;
+
+ //--------------------------------------------------------
+ // Reads/writes files to utlbuffers. Use this for optimal read performance when doing open/read/close
+ //--------------------------------------------------------
+ virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
+ virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) = 0;
+ virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) = 0;
+};
+
+abstract_class IIoStats
+{
+public:
+ virtual void OnFileSeek( int nTimeInMs ) = 0;
+ virtual void OnFileRead( int nTimeInMs, int nBytesRead ) = 0;
+ virtual void OnFileOpen( const char * pFileName ) = 0;
+
+ virtual int GetNumberOfFileSeeks() = 0;
+ virtual int GetTimeInFileSeek() = 0;
+
+ virtual int GetNumberOfFileReads() = 0;
+ virtual int GetTimeInFileReads() = 0;
+ virtual int GetFileReadTotalSize() = 0;
+
+ virtual int GetNumberOfFileOpens() = 0;
+
+ virtual void Reset() = 0;
+
+protected:
+ virtual ~IIoStats()
+ {
+ // Do nothing...
+ }
+};
+
+//-----------------------------------------------------------------------------
+// Main file system interface
+//-----------------------------------------------------------------------------
+abstract_class IFileSystem : public IAppSystem, public IBaseFileSystem
+{
+public:
+ //--------------------------------------------------------
+ // Steam operations
+ //--------------------------------------------------------
+
+ virtual bool IsSteam() const = 0;
+
+ // Supplying an extra app id will mount this app in addition
+ // to the one specified in the environment variable "steamappid"
+ //
+ // If nExtraAppId is < -1, then it will mount that app ID only.
+ // (Was needed by the dedicated server b/c the "SteamAppId" env var only gets passed to steam.dll
+ // at load time, so the dedicated couldn't pass it in that way).
+ virtual FilesystemMountRetval_t MountSteamContent( int nExtraAppId = -1 ) = 0;
+
+ //--------------------------------------------------------
+ // Search path manipulation
+ //--------------------------------------------------------
+
+ // Add paths in priority order (mod dir, game dir, ....)
+ // If one or more .pak files are in the specified directory, then they are
+ // added after the file system path
+ // If the path is the relative path to a .bsp file, then any previous .bsp file
+ // override is cleared and the current .bsp is searched for an embedded PAK file
+ // and this file becomes the highest priority search path ( i.e., it's looked at first
+ // even before the mod's file system path ).
+ virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0;
+ virtual bool RemoveSearchPath( const char *pPath, const char *pathID = 0 ) = 0;
+
+ // Remove all search paths (including write path?)
+ virtual void RemoveAllSearchPaths( void ) = 0;
+
+ // Remove search paths associated with a given pathID
+ virtual void RemoveSearchPaths( const char *szPathID ) = 0;
+
+ // This is for optimization. If you mark a path ID as "by request only", then files inside it
+ // will only be accessed if the path ID is specifically requested. Otherwise, it will be ignored.
+ // If there are currently no search paths with the specified path ID, then it will still
+ // remember it in case you add search paths with this path ID.
+ virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) = 0;
+
+ // converts a partial path into a full path
+ virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) = 0;
+#if IsGameConsole()
+ // Given a relative path, gets the PACK file that contained this file and its offset and size. Can be used to prefetch a file to a HDD for caching reason.
+ virtual bool GetPackFileInfoFromRelativePath( const char *pFileName, const char *pPathID, char *pPackPath, int nPackPathBufferSize, int64 &nPosition, int64 &nLength ) = 0;
+#endif
+ // Returns the search path, each path is separated by ;s. Returns the length of the string returned
+ virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) = 0;
+
+ // interface for custom pack files > 4Gb
+ virtual bool AddPackFile( const char *fullpath, const char *pathID ) = 0;
+
+ //--------------------------------------------------------
+ // File manipulation operations
+ //--------------------------------------------------------
+
+ // Deletes a file (on the WritePath)
+ virtual void RemoveFile( char const* pRelativePath, const char *pathID = 0 ) = 0;
+
+ // Renames a file (on the WritePath)
+ virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID = 0 ) = 0;
+
+ // create a local directory structure
+ virtual void CreateDirHierarchy( const char *path, const char *pathID = 0 ) = 0;
+
+ // File I/O and info
+ virtual bool IsDirectory( const char *pFileName, const char *pathID = 0 ) = 0;
+
+ virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) = 0;
+
+ //--------------------------------------------------------
+ // Open file operations
+ //--------------------------------------------------------
+
+ virtual void SetBufferSize( FileHandle_t file, unsigned nBytes ) = 0;
+
+ virtual bool IsOk( FileHandle_t file ) = 0;
+
+ virtual bool EndOfFile( FileHandle_t file ) = 0;
+
+ virtual char *ReadLine( char *pOutput, int maxChars, FileHandle_t file ) = 0;
+ virtual int FPrintf( FileHandle_t file, const char *pFormat, ... ) FMTFUNCTION( 3, 4 ) = 0;
+
+ //--------------------------------------------------------
+ // Dynamic library operations
+ //--------------------------------------------------------
+
+ // load/unload modules
+ virtual CSysModule *LoadModule( const char *pFileName, const char *pPathID = 0, bool bValidatedDllOnly = true ) = 0;
+ virtual void UnloadModule( CSysModule *pModule ) = 0;
+
+ //--------------------------------------------------------
+ // File searching operations
+ //--------------------------------------------------------
+
+ // FindFirst/FindNext. Also see FindFirstEx.
+ virtual const char *FindFirst( const char *pWildCard, FileFindHandle_t *pHandle ) = 0;
+ virtual const char *FindNext( FileFindHandle_t handle ) = 0;
+ virtual bool FindIsDirectory( FileFindHandle_t handle ) = 0;
+ virtual void FindClose( FileFindHandle_t handle ) = 0;
+
+ // Same as FindFirst, but you can filter by path ID, which can make it faster.
+ virtual const char *FindFirstEx(
+ const char *pWildCard,
+ const char *pPathID,
+ FileFindHandle_t *pHandle
+ ) = 0;
+
+ // Searches for a file in all paths and results absolute path names for the file, works in pack files (zip and vpk) too
+ // Lets you search for something like sound/sound.cache and get a list of every sound cache
+ virtual void FindFileAbsoluteList( CUtlVector< CUtlString > &outAbsolutePathNames, const char *pWildCard, const char *pPathID ) = 0;
+
+ //--------------------------------------------------------
+ // File name and directory operations
+ //--------------------------------------------------------
+
+ // FIXME: This method is obsolete! Use RelativePathToFullPath instead!
+ // converts a partial path into a full path
+ virtual const char *GetLocalPath( const char *pFileName, char *pLocalPath, int localPathBufferSize ) = 0;
+
+ // Returns true on success ( based on current list of search paths, otherwise false if
+ // it can't be resolved )
+ virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) = 0;
+
+ // Gets the current working directory
+ virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) = 0;
+
+ //--------------------------------------------------------
+ // Filename dictionary operations
+ //--------------------------------------------------------
+
+ virtual FileNameHandle_t FindOrAddFileName( char const *pFileName ) = 0;
+ virtual bool String( const FileNameHandle_t& handle, char *buf, int buflen ) = 0;
+
+ //--------------------------------------------------------
+ // Asynchronous file operations
+ //--------------------------------------------------------
+
+ //------------------------------------
+ // Global operations
+ //------------------------------------
+ FSAsyncStatus_t AsyncRead( const FileAsyncRequest_t &request, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultiple( &request, 1, phControl ); }
+ virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *phControls = NULL ) = 0;
+ virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl = NULL ) = 0;
+ virtual FSAsyncStatus_t AsyncAppendFile(const char *pAppendToFileName, const char *pAppendFromFileName, FSAsyncControl_t *pControl = NULL ) = 0;
+ virtual void AsyncFinishAll( int iToPriority = 0 ) = 0;
+ virtual void AsyncFinishAllWrites() = 0;
+ virtual FSAsyncStatus_t AsyncFlush() = 0;
+ virtual bool AsyncSuspend() = 0;
+ virtual bool AsyncResume() = 0;
+
+ //------------------------------------
+ // Functions to hold a file open if planning on doing mutiple reads. Use is optional,
+ // and is taken only as a hint
+ //------------------------------------
+ virtual FSAsyncStatus_t AsyncBeginRead( const char *pszFile, FSAsyncFile_t *phFile ) = 0;
+ virtual FSAsyncStatus_t AsyncEndRead( FSAsyncFile_t hFile ) = 0;
+
+ //------------------------------------
+ // Request management
+ //------------------------------------
+ virtual FSAsyncStatus_t AsyncFinish( FSAsyncControl_t hControl, bool wait = true ) = 0;
+ virtual FSAsyncStatus_t AsyncGetResult( FSAsyncControl_t hControl, void **ppData, int *pSize ) = 0;
+ virtual FSAsyncStatus_t AsyncAbort( FSAsyncControl_t hControl ) = 0;
+ virtual FSAsyncStatus_t AsyncStatus( FSAsyncControl_t hControl ) = 0;
+ // set a new priority for a file already in the queue
+ virtual FSAsyncStatus_t AsyncSetPriority(FSAsyncControl_t hControl, int newPriority) = 0;
+ virtual void AsyncAddRef( FSAsyncControl_t hControl ) = 0;
+ virtual void AsyncRelease( FSAsyncControl_t hControl ) = 0;
+
+ //--------------------------------------------------------
+ // Remote resource management
+ //--------------------------------------------------------
+
+ // starts waiting for resources to be available
+ // returns FILESYSTEM_INVALID_HANDLE if there is nothing to wait on
+ virtual WaitForResourcesHandle_t WaitForResources( const char *resourcelist ) = 0;
+ // get progress on waiting for resources; progress is a float [0, 1], complete is true on the waiting being done
+ // returns false if no progress is available
+ // any calls after complete is true or on an invalid handle will return false, 0.0f, true
+ virtual bool GetWaitForResourcesProgress( WaitForResourcesHandle_t handle, float *progress /* out */ , bool *complete /* out */ ) = 0;
+ // cancels a progress call
+ virtual void CancelWaitForResources( WaitForResourcesHandle_t handle ) = 0;
+
+ // hints that a set of files will be loaded in near future
+ // HintResourceNeed() is not to be confused with resource precaching.
+ virtual int HintResourceNeed( const char *hintlist, int forgetEverything ) = 0;
+ // returns true if a file is on disk
+ virtual bool IsFileImmediatelyAvailable(const char *pFileName) = 0;
+
+ // copies file out of pak/bsp/steam cache onto disk (to be accessible by third-party code)
+ virtual void GetLocalCopy( const char *pFileName ) = 0;
+
+ //--------------------------------------------------------
+ // Debugging operations
+ //--------------------------------------------------------
+
+ // Dump to printf/OutputDebugString the list of files that have not been closed
+ virtual void PrintOpenedFiles( void ) = 0;
+ virtual void PrintSearchPaths( void ) = 0;
+
+ // output
+ virtual void SetWarningFunc( void (*pfnWarning)( const char *fmt, ... ) ) = 0;
+ virtual void SetWarningLevel( FileWarningLevel_t level ) = 0;
+ virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ) = 0;
+ virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) = 0;
+
+ // Returns the file system statistics retreived by the implementation. Returns NULL if not supported.
+ virtual const FileSystemStatistics *GetFilesystemStatistics() = 0;
+
+#if defined( _PS3 )
+ // EA cruft not used: virtual Ps3FileType_t GetPs3FileType(const char* path) = 0;
+ virtual void LogFileAccess( const char *pFullFileName ) = 0;
+
+ // Prefetches a full file in the HDD cache.
+ virtual bool PrefetchFile( const char *pFileName, int nPriority, bool bPersist ) = 0;
+ // Prefetches a file portion in the HDD cache.
+ virtual bool PrefetchFile( const char *pFileName, int nPriority, bool bPersist, int64 nOffset, int64 nSize ) = 0;
+ // Flushes the HDD cache.
+ virtual void FlushCache() = 0;
+ // Suspends all prefetches (like when the game is doing a file intensive operation not controlled by the HDD cache, like Bink movies).
+ virtual void SuspendPrefetches( const char *pWhy ) = 0;
+ // Resumes prefetches. This function has to to be called as many time as SuspendPrefetches() to effectively resumes prefetches.
+ virtual void ResumePrefetches( const char * pWhy ) = 0;
+
+ // Gets called when we are starting / ending a save (it allows the file system to reduce its HDD usage and use BluRay instead).
+ virtual void OnSaveStateChanged( bool bSaving ) = 0;
+
+ // Returns the prefetching state. If true, everything has been prefetched on the HDD.
+ virtual bool IsPrefetchingDone() = 0;
+
+#endif //_PS3
+ //--------------------------------------------------------
+ // Start of new functions after Lost Coast release (7/05)
+ //--------------------------------------------------------
+
+ virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) = 0;
+
+ // Extended version of read provides more context to allow for more optimal reading
+ virtual int ReadEx( void* pOutput, int sizeDest, int size, FileHandle_t file ) = 0;
+ virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate = false, bool bOptimalAlloc = false, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
+
+ virtual FileNameHandle_t FindFileName( char const *pFileName ) = 0;
+
+#if defined( TRACK_BLOCKING_IO )
+ virtual void EnableBlockingFileAccessTracking( bool state ) = 0;
+ virtual bool IsBlockingFileAccessEnabled() const = 0;
+
+ virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() = 0;
+#endif
+
+ virtual void SetupPreloadData() = 0;
+ virtual void DiscardPreloadData() = 0;
+
+ // Fixme, we could do these via a string embedded into the compiled data, etc...
+ enum KeyValuesPreloadType_t
+ {
+ TYPE_VMT,
+ TYPE_SOUNDEMITTER,
+ TYPE_SOUNDSCAPE,
+ TYPE_SOUNDOPERATORS,
+ NUM_PRELOAD_TYPES
+ };
+
+ // If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup.
+ // Otherwise, it'll just fall through to the regular KeyValues loading routines
+ virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0;
+ virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0;
+
+ virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0;
+ virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0;
+ // Async read functions with memory blame
+ FSAsyncStatus_t AsyncReadCreditAlloc( const FileAsyncRequest_t &request, const char *pszFile, int line, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultipleCreditAlloc( &request, 1, pszFile, line, phControl ); }
+ virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *phControls = NULL ) = 0;
+
+ virtual FSAsyncStatus_t AsyncDirectoryScan( const char* pSearchSpec, bool recurseFolders, void* pContext, FSAsyncScanAddFunc_t pfnAdd, FSAsyncScanCompleteFunc_t pfnDone, FSAsyncControl_t *pControl = NULL ) = 0;
+
+ virtual bool GetFileTypeForFullPath( char const *pFullPath, wchar_t *buf, size_t bufSizeInBytes ) = 0;
+
+ //--------------------------------------------------------
+ //--------------------------------------------------------
+ virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0;
+
+ //--------------------------------------------------------
+ // Optimal IO operations
+ //--------------------------------------------------------
+ virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) = 0;
+ inline unsigned GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize );
+ virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize = 0, unsigned nOffset = 0 ) = 0;
+ virtual void FreeOptimalReadBuffer( void * ) = 0;
+
+ //--------------------------------------------------------
+ //
+ //--------------------------------------------------------
+ virtual void BeginMapAccess() = 0;
+ virtual void EndMapAccess() = 0;
+
+ // Returns true on success, otherwise false if it can't be resolved
+ virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, char *pRelative, int maxlen ) = 0;
+
+ virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0;
+ virtual long GetPathTime( const char *pPath, const char *pPathID ) = 0;
+
+ virtual DVDMode_t GetDVDMode() = 0;
+
+ //--------------------------------------------------------
+ // Whitelisting for pure servers.
+ //--------------------------------------------------------
+
+ // This should be called ONCE at startup. Multiplayer games (gameinfo.txt does not contain singleplayer_only)
+ // want to enable this so sv_pure works.
+ virtual void EnableWhitelistFileTracking( bool bEnable ) = 0;
+
+ // This is called when the client connects to a server using a pure_server_whitelist.txt file.
+ //
+ // Files listed in pWantCRCList will have CRCs calculated for them IF they come off disk
+ // (and those CRCs will come out of GetUnverifiedCRCFiles).
+ //
+ // Files listed in pAllowFromDiskList will be allowed to load from disk. All other files will
+ // be forced to come from Steam.
+ //
+ // The filesystem hangs onto the whitelists you pass in here, and it will Release() them when it closes down
+ // or when you call this function again.
+ //
+ // NOTE: The whitelists you pass in here will be accessed from multiple threads, so make sure the
+ // IsFileInList function is thread safe.
+ //
+ // If pFilesToReload is non-null, the filesystem will hand back a list of files that should be reloaded because they
+ // are now "dirty". For example, if you were on a non-pure server and you loaded a certain model, and then you connected
+ // to a pure server that said that model had to come from Steam, then pFilesToReload would specify that model
+ // and the engine should reload it so it can come from Steam.
+ //
+ // Be sure to call Release() on pFilesToReload.
+ virtual void RegisterFileWhitelist( IFileList *pWantCRCList, IFileList *pAllowFromDiskList, IFileList **pFilesToReload ) = 0;
+
+ // Called when the client logs onto a server. Any files that came off disk should be marked as
+ // unverified because this server may have a different set of files it wants to guarantee.
+ virtual void MarkAllCRCsUnverified() = 0;
+
+ // As the server loads whitelists when it transitions maps, it calls this to calculate CRCs for any files marked
+ // with check_crc. Then it calls CheckCachedFileCRC later when it gets client requests to verify CRCs.
+ virtual void CacheFileCRCs( const char *pPathname, ECacheCRCType eType, IFileList *pFilter ) = 0;
+ virtual EFileCRCStatus CheckCachedFileCRC( const char *pPathID, const char *pRelativeFilename, CRC32_t *pCRC ) = 0;
+
+ // Fills in the list of files that have been loaded off disk and have not been verified.
+ // Returns the number of files filled in (between 0 and nMaxFiles).
+ //
+ // This also removes any files it's returning from the unverified CRC list, so they won't be
+ // returned from here again.
+ // The client sends batches of these to the server to verify.
+ virtual int GetUnverifiedCRCFiles( CUnverifiedCRCFile *pFiles, int nMaxFiles ) = 0;
+
+ // Control debug message output.
+ // Pass a combination of WHITELIST_SPEW_ flags.
+ virtual int GetWhitelistSpewFlags() = 0;
+ virtual void SetWhitelistSpewFlags( int flags ) = 0;
+
+ // Installs a callback used to display a dirty disk dialog
+ virtual void InstallDirtyDiskReportFunc( FSDirtyDiskReportFunc_t func ) = 0;
+
+ virtual bool IsLaunchedFromXboxHDD() = 0;
+ virtual bool IsInstalledToXboxHDDCache() = 0;
+ virtual bool IsDVDHosted() = 0;
+ virtual bool IsInstallAllowed() = 0;
+
+ virtual int GetSearchPathID( char *pPath, int nMaxLen ) = 0;
+ virtual bool FixupSearchPathsAfterInstall() = 0;
+
+ virtual FSDirtyDiskReportFunc_t GetDirtyDiskReportFunc() = 0;
+
+ virtual void AddVPKFile( char const *pszName, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0;
+ virtual void RemoveVPKFile( char const *pszName ) = 0;
+ virtual void GetVPKFileNames( CUtlVector<CUtlString> &destVector ) = 0;
+ virtual void RemoveAllMapSearchPaths() = 0;
+ virtual void SyncDvdDevCache() = 0;
+
+ virtual bool GetStringFromKVPool( CRC32_t poolKey, unsigned int key, char *pOutBuff, int buflen ) = 0;
+
+ virtual bool DiscoverDLC( int iController ) = 0;
+ virtual int IsAnyDLCPresent( bool *pbDLCSearchPathMounted = NULL ) = 0;
+ virtual bool GetAnyDLCInfo( int iDLC, unsigned int *pLicenseMask, wchar_t *pTitleBuff, int nOutTitleSize ) = 0;
+ virtual int IsAnyCorruptDLC() = 0;
+ virtual bool GetAnyCorruptDLCInfo( int iCorruptDLC, wchar_t *pTitleBuff, int nOutTitleSize ) = 0;
+ virtual bool AddDLCSearchPaths() = 0;
+ virtual bool IsSpecificDLCPresent( unsigned int nDLCPackage ) = 0;
+
+ // call this to look for CPU-hogs during loading processes. When you set this, a breakpoint
+ // will be issued whenever the indicated # of seconds go by without an i/o request. Passing
+ // 0.0 will turn off the functionality.
+ virtual void SetIODelayAlarm( float flThreshhold ) = 0;
+
+ virtual bool AddXLSPUpdateSearchPath( const void *pData, int nSize ) = 0;
+
+ virtual IIoStats *GetIoStats() = 0;
+
+};
+
+//-----------------------------------------------------------------------------
+
+#if defined( _X360 ) && !defined( _CERT )
+extern char g_szXboxProfileLastFileOpened[MAX_PATH];
+#define SetLastProfileFileRead( s ) V_strncpy( g_szXboxProfileLastFileOpened, sizeof( g_szXboxProfileLastFileOpened), pFileName )
+#define GetLastProfileFileRead() (&g_szXboxProfileLastFileOpened[0])
+#else
+#define SetLastProfileFileRead( s ) ((void)0)
+#define GetLastProfileFileRead() NULL
+#endif
+
+#if defined( _X360 ) && defined( _BASETSD_H_ )
+class CXboxDiskCacheSetter
+{
+public:
+ CXboxDiskCacheSetter( SIZE_T newSize )
+ {
+ m_oldSize = XGetFileCacheSize();
+ XSetFileCacheSize( newSize );
+ }
+
+ ~CXboxDiskCacheSetter()
+ {
+ XSetFileCacheSize( m_oldSize );
+ }
+private:
+ SIZE_T m_oldSize;
+};
+#define DISK_INTENSIVE() CXboxDiskCacheSetter cacheSetter( 1024*1024 )
+#else
+#define DISK_INTENSIVE() ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+
+inline unsigned IFileSystem::GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize )
+{
+ unsigned align;
+ if ( GetOptimalIOConstraints( hFile, &align, NULL, NULL ) )
+ return AlignValue( nLogicalSize, align );
+ else
+ return nLogicalSize;
+}
+
+//-----------------------------------------------------------------------------
+
+// We include this here so it'll catch compile errors in VMPI early.
+#include "filesystem_passthru.h"
+
+//-----------------------------------------------------------------------------
+// Async memory tracking
+//-----------------------------------------------------------------------------
+
+#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
+#define AsyncRead( a, b ) AsyncReadCreditAlloc( a, __FILE__, __LINE__, b )
+#define AsyncReadMutiple( a, b, c ) AsyncReadMultipleCreditAlloc( a, b, __FILE__, __LINE__, c )
+#endif
+
+//-----------------------------------------------------------------------------
+// Globals Exposed
+//-----------------------------------------------------------------------------
+DECLARE_TIER2_INTERFACE( IFileSystem, g_pFullFileSystem );
+
+
+
+
+#endif // FILESYSTEM_H
diff --git a/external/vpc/public/filesystem_passthru.h b/external/vpc/public/filesystem_passthru.h
new file mode 100644
index 0000000..ed1372d
--- /dev/null
+++ b/external/vpc/public/filesystem_passthru.h
@@ -0,0 +1,299 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef FILESYSTEM_PASSTHRU_H
+#define FILESYSTEM_PASSTHRU_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "filesystem.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef AsyncRead
+#undef AsyncRead
+#undef AsyncReadMutiple
+#endif
+
+//
+// These classes pass all filesystem interface calls through to another filesystem
+// interface. They can be used anytime you want to override a couple things in
+// a filesystem. VMPI uses this to override the base filesystem calls while
+// allowing the rest of the filesystem functionality to work on the master.
+//
+
+template<class Base>
+class CInternalFileSystemPassThru : public Base
+{
+public:
+ CInternalFileSystemPassThru()
+ {
+ m_pBaseFileSystemPassThru = NULL;
+ }
+ virtual void InitPassThru( IBaseFileSystem *pBaseFileSystemPassThru )
+ {
+ m_pBaseFileSystemPassThru = pBaseFileSystemPassThru;
+ }
+ virtual int Read( void* pOutput, int size, FileHandle_t file ) { return m_pBaseFileSystemPassThru->Read( pOutput, size, file ); }
+ virtual int Write( void const* pInput, int size, FileHandle_t file ) { return m_pBaseFileSystemPassThru->Write( pInput, size, file ); }
+ virtual FileHandle_t Open( const char *pFileName, const char *pOptions, const char *pathID ) { return m_pBaseFileSystemPassThru->Open( pFileName, pOptions, pathID ); }
+ virtual void Close( FileHandle_t file ) { m_pBaseFileSystemPassThru->Close( file ); }
+ virtual void Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType ) { m_pBaseFileSystemPassThru->Seek( file, pos, seekType ); }
+ virtual unsigned int Tell( FileHandle_t file ) { return m_pBaseFileSystemPassThru->Tell( file ); }
+ virtual unsigned int Size( FileHandle_t file ) { return m_pBaseFileSystemPassThru->Size( file ); }
+ virtual unsigned int Size( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->Size( pFileName, pPathID ); }
+ virtual void Flush( FileHandle_t file ) { m_pBaseFileSystemPassThru->Flush( file ); }
+ virtual bool Precache( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->Precache( pFileName, pPathID ); }
+ virtual bool FileExists( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->FileExists( pFileName, pPathID ); }
+ virtual bool IsFileWritable( char const *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->IsFileWritable( pFileName, pPathID ); }
+ virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID ) { return m_pBaseFileSystemPassThru->SetFileWritable( pFileName, writable, pPathID ); }
+ virtual long GetFileTime( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->GetFileTime( pFileName, pPathID ); }
+ virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pBaseFileSystemPassThru->ReadFile( pFileName, pPath, buf, nMaxBytes, nStartingByte, pfnAlloc ); }
+ virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) { return m_pBaseFileSystemPassThru->WriteFile( pFileName, pPath, buf ); }
+ virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) { return m_pBaseFileSystemPassThru->UnzipFile( pFileName, pPath, pDestination ); }
+
+protected:
+ IBaseFileSystem *m_pBaseFileSystemPassThru;
+};
+
+
+class CBaseFileSystemPassThru : public CInternalFileSystemPassThru<IBaseFileSystem>
+{
+public:
+};
+
+
+class CFileSystemPassThru : public CInternalFileSystemPassThru<IFileSystem>
+{
+public:
+ typedef CInternalFileSystemPassThru<IFileSystem> BaseClass;
+
+ CFileSystemPassThru()
+ {
+ m_pFileSystemPassThru = NULL;
+ }
+ virtual void InitPassThru( IFileSystem *pFileSystemPassThru, bool bBaseOnly )
+ {
+ if ( !bBaseOnly )
+ m_pFileSystemPassThru = pFileSystemPassThru;
+
+ BaseClass::InitPassThru( pFileSystemPassThru );
+ }
+
+ // IAppSystem stuff.
+ // Here's where the app systems get to learn about each other
+ virtual bool Connect( CreateInterfaceFn factory ) { return m_pFileSystemPassThru->Connect( factory ); }
+ virtual void Disconnect() { m_pFileSystemPassThru->Disconnect(); }
+ virtual void *QueryInterface( const char *pInterfaceName ) { return m_pFileSystemPassThru->QueryInterface( pInterfaceName ); }
+ virtual InitReturnVal_t Init() { return m_pFileSystemPassThru->Init(); }
+ virtual void Shutdown() { m_pFileSystemPassThru->Shutdown(); }
+ virtual const AppSystemInfo_t* GetDependencies() { return m_pFileSystemPassThru->GetDependencies(); }
+ virtual AppSystemTier_t GetTier() { return m_pFileSystemPassThru->GetTier(); }
+ virtual void Reconnect( CreateInterfaceFn factory, const char *pInterfaceName ) { m_pFileSystemPassThru->Reconnect( factory, pInterfaceName ); }
+
+ virtual void RemoveAllSearchPaths( void ) { m_pFileSystemPassThru->RemoveAllSearchPaths(); }
+ virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType ) { m_pFileSystemPassThru->AddSearchPath( pPath, pathID, addType ); }
+ virtual bool RemoveSearchPath( const char *pPath, const char *pathID ) { return m_pFileSystemPassThru->RemoveSearchPath( pPath, pathID ); }
+ virtual void RemoveFile( char const* pRelativePath, const char *pathID ) { m_pFileSystemPassThru->RemoveFile( pRelativePath, pathID ); }
+ virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID ) { return m_pFileSystemPassThru->RenameFile( pOldPath, pNewPath, pathID ); }
+ virtual void CreateDirHierarchy( const char *path, const char *pathID ) { m_pFileSystemPassThru->CreateDirHierarchy( path, pathID ); }
+ virtual bool IsDirectory( const char *pFileName, const char *pathID ) { return m_pFileSystemPassThru->IsDirectory( pFileName, pathID ); }
+ virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) { m_pFileSystemPassThru->FileTimeToString( pStrip, maxCharsIncludingTerminator, fileTime ); }
+ virtual void SetBufferSize( FileHandle_t file, unsigned nBytes ) { m_pFileSystemPassThru->SetBufferSize( file, nBytes ); }
+ virtual bool IsOk( FileHandle_t file ) { return m_pFileSystemPassThru->IsOk( file ); }
+ virtual bool EndOfFile( FileHandle_t file ) { return m_pFileSystemPassThru->EndOfFile( file ); }
+ virtual char *ReadLine( char *pOutput, int maxChars, FileHandle_t file ) { return m_pFileSystemPassThru->ReadLine( pOutput, maxChars, file ); }
+ virtual int FPrintf( FileHandle_t file, const char *pFormat, ... )
+ {
+ char str[8192];
+ va_list marker;
+ va_start( marker, pFormat );
+ _vsnprintf( str, sizeof( str ), pFormat, marker );
+ va_end( marker );
+ return m_pFileSystemPassThru->FPrintf( file, "%s", str );
+ }
+ virtual CSysModule *LoadModule( const char *pFileName, const char *pPathID, bool bValidatedDllOnly ) { return m_pFileSystemPassThru->LoadModule( pFileName, pPathID, bValidatedDllOnly ); }
+ virtual void UnloadModule( CSysModule *pModule ) { m_pFileSystemPassThru->UnloadModule( pModule ); }
+ virtual const char *FindFirst( const char *pWildCard, FileFindHandle_t *pHandle ) { return m_pFileSystemPassThru->FindFirst( pWildCard, pHandle ); }
+ virtual const char *FindNext( FileFindHandle_t handle ) { return m_pFileSystemPassThru->FindNext( handle ); }
+ virtual bool FindIsDirectory( FileFindHandle_t handle ) { return m_pFileSystemPassThru->FindIsDirectory( handle ); }
+ virtual void FindClose( FileFindHandle_t handle ) { m_pFileSystemPassThru->FindClose( handle ); }
+ virtual void FindFileAbsoluteList( CUtlVector< CUtlString > &outAbsolutePathNames, const char *pWildCard, const char *pPathID ) { m_pFileSystemPassThru->FindFileAbsoluteList( outAbsolutePathNames, pWildCard, pPathID ); }
+ virtual const char *GetLocalPath( const char *pFileName, char *pLocalPath, int localPathBufferSize ) { return m_pFileSystemPassThru->GetLocalPath( pFileName, pLocalPath, localPathBufferSize ); }
+ virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) { return m_pFileSystemPassThru->FullPathToRelativePath( pFullpath, pRelative, maxlen ); }
+ virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) { return m_pFileSystemPassThru->GetCurrentDirectory( pDirectory, maxlen ); }
+ virtual void PrintOpenedFiles( void ) { m_pFileSystemPassThru->PrintOpenedFiles(); }
+ virtual void PrintSearchPaths( void ) { m_pFileSystemPassThru->PrintSearchPaths(); }
+ virtual void SetWarningFunc( void (*pfnWarning)( const char *fmt, ... ) ) { m_pFileSystemPassThru->SetWarningFunc( pfnWarning ); }
+ virtual void SetWarningLevel( FileWarningLevel_t level ) { m_pFileSystemPassThru->SetWarningLevel( level ); }
+ virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ){ m_pFileSystemPassThru->AddLoggingFunc( pfnLogFunc ); }
+ virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) { m_pFileSystemPassThru->RemoveLoggingFunc( logFunc ); }
+ virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultiple( pRequests, nRequests, pControls ); }
+ virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultipleCreditAlloc( pRequests, nRequests, pszFile, line, pControls ); }
+ virtual FSAsyncStatus_t AsyncDirectoryScan( const char* pSearchSpec, bool recurseFolders, void* pContext, FSAsyncScanAddFunc_t pfnAdd, FSAsyncScanCompleteFunc_t pfnDone, FSAsyncControl_t *pControl = NULL ) { return m_pFileSystemPassThru->AsyncDirectoryScan( pSearchSpec, recurseFolders, pContext, pfnAdd, pfnDone, pControl ); }
+ virtual FSAsyncStatus_t AsyncFinish(FSAsyncControl_t hControl, bool wait) { return m_pFileSystemPassThru->AsyncFinish( hControl, wait ); }
+ virtual FSAsyncStatus_t AsyncGetResult( FSAsyncControl_t hControl, void **ppData, int *pSize ) { return m_pFileSystemPassThru->AsyncGetResult( hControl, ppData, pSize ); }
+ virtual FSAsyncStatus_t AsyncAbort(FSAsyncControl_t hControl) { return m_pFileSystemPassThru->AsyncAbort( hControl ); }
+ virtual FSAsyncStatus_t AsyncStatus(FSAsyncControl_t hControl) { return m_pFileSystemPassThru->AsyncStatus( hControl ); }
+ virtual FSAsyncStatus_t AsyncFlush() { return m_pFileSystemPassThru->AsyncFlush(); }
+ virtual void AsyncAddRef( FSAsyncControl_t hControl ) { m_pFileSystemPassThru->AsyncAddRef( hControl ); }
+ virtual void AsyncRelease( FSAsyncControl_t hControl ) { m_pFileSystemPassThru->AsyncRelease( hControl ); }
+ virtual FSAsyncStatus_t AsyncBeginRead( const char *pszFile, FSAsyncFile_t *phFile ) { return m_pFileSystemPassThru->AsyncBeginRead( pszFile, phFile ); }
+ virtual FSAsyncStatus_t AsyncEndRead( FSAsyncFile_t hFile ) { return m_pFileSystemPassThru->AsyncEndRead( hFile ); }
+ virtual const FileSystemStatistics *GetFilesystemStatistics() { return m_pFileSystemPassThru->GetFilesystemStatistics(); }
+
+
+#if defined( _PS3 )
+ // These should never be called on PS3!
+ virtual Ps3FileType_t GetPs3FileType(const char* path) { return PS3_FILETYPE_UNKNOWN; }
+ virtual void LogFileAccess( const char *pFullFileName ) { }
+
+ virtual bool PrefetchFile( const char *pFileName, int nPriority, bool bPersist ) { return m_pFileSystemPassThru->PrefetchFile( pFileName, nPriority, bPersist ); }
+ virtual bool PrefetchFile( const char *pFileName, int nPriority, bool bPersist, int64 nOffset, int64 nSize ) { return m_pFileSystemPassThru->PrefetchFile( pFileName, nPriority, bPersist, nOffset, nSize ); }
+ virtual void FlushCache() { m_pFileSystemPassThru->FlushCache(); }
+ virtual void SuspendPrefetches( const char * pWhy ) { m_pFileSystemPassThru->SuspendPrefetches( pWhy ); }
+ virtual void ResumePrefetches( const char * pWhy ) { m_pFileSystemPassThru->ResumePrefetches( pWhy ); }
+ virtual void OnSaveStateChanged( bool bSaving ) { m_pFileSystemPassThru->OnSaveStateChanged( bSaving ); }
+ virtual bool IsPrefetchingDone( ) { return m_pFileSystemPassThru->IsPrefetchingDone(); }
+#endif //_PS3
+
+ virtual WaitForResourcesHandle_t WaitForResources( const char *resourcelist ) { return m_pFileSystemPassThru->WaitForResources( resourcelist ); }
+ virtual bool GetWaitForResourcesProgress( WaitForResourcesHandle_t handle,
+ float *progress, bool *complete ) { return m_pFileSystemPassThru->GetWaitForResourcesProgress( handle, progress, complete ); }
+ virtual void CancelWaitForResources( WaitForResourcesHandle_t handle ) { m_pFileSystemPassThru->CancelWaitForResources( handle ); }
+ virtual int HintResourceNeed( const char *hintlist, int forgetEverything ) { return m_pFileSystemPassThru->HintResourceNeed( hintlist, forgetEverything ); }
+ virtual bool IsFileImmediatelyAvailable(const char *pFileName) { return m_pFileSystemPassThru->IsFileImmediatelyAvailable( pFileName ); }
+ virtual void GetLocalCopy( const char *pFileName ) { m_pFileSystemPassThru->GetLocalCopy( pFileName ); }
+ virtual FileNameHandle_t FindOrAddFileName( char const *pFileName ) { return m_pFileSystemPassThru->FindOrAddFileName( pFileName ); }
+ virtual FileNameHandle_t FindFileName( char const *pFileName ) { return m_pFileSystemPassThru->FindFileName( pFileName ); }
+ virtual bool String( const FileNameHandle_t& handle, char *buf, int buflen ) { return m_pFileSystemPassThru->String( handle, buf, buflen ); }
+ virtual bool IsOk2( FileHandle_t file ) { return IsOk(file); }
+ virtual void RemoveSearchPaths( const char *szPathID ) { m_pFileSystemPassThru->RemoveSearchPaths( szPathID ); }
+ virtual bool IsSteam() const { return m_pFileSystemPassThru->IsSteam(); }
+ virtual FilesystemMountRetval_t MountSteamContent( int nExtraAppId = -1 ) { return m_pFileSystemPassThru->MountSteamContent( nExtraAppId ); }
+
+ virtual const char *FindFirstEx(
+ const char *pWildCard,
+ const char *pPathID,
+ FileFindHandle_t *pHandle
+ ) { return m_pFileSystemPassThru->FindFirstEx( pWildCard, pPathID, pHandle ); }
+ virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) { m_pFileSystemPassThru->MarkPathIDByRequestOnly( pPathID, bRequestOnly ); }
+ virtual bool AddPackFile( const char *fullpath, const char *pathID ) { return m_pFileSystemPassThru->AddPackFile( fullpath, pathID ); }
+ virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppend( pFileName, pSrc, nSrcBytes, bFreeMemory, pControl); }
+ virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWrite( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); }
+ virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWriteFile( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); }
+ virtual FSAsyncStatus_t AsyncAppendFile(const char *pDestFileName, const char *pSrcFileName, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppendFile(pDestFileName, pSrcFileName, pControl); }
+ virtual void AsyncFinishAll( int iToPriority ) { m_pFileSystemPassThru->AsyncFinishAll(iToPriority); }
+ virtual void AsyncFinishAllWrites() { m_pFileSystemPassThru->AsyncFinishAllWrites(); }
+ virtual FSAsyncStatus_t AsyncSetPriority(FSAsyncControl_t hControl, int newPriority) { return m_pFileSystemPassThru->AsyncSetPriority(hControl, newPriority); }
+ virtual bool AsyncSuspend() { return m_pFileSystemPassThru->AsyncSuspend(); }
+ virtual bool AsyncResume() { return m_pFileSystemPassThru->AsyncResume(); }
+ virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) { return m_pFileSystemPassThru->RelativePathToFullPath( pFileName, pPathID, pLocalPath, localPathBufferSize, pathFilter, pPathType ); }
+#if IsGameConsole()
+ // Given a relative path, gets the PACK file that contained this file and its offset and size. Can be used to prefetch a file to a HDD for caching reason.
+ virtual bool GetPackFileInfoFromRelativePath( const char *pFileName, const char * pPathID, char *pPackPath, int nPackPathBufferSize, int64 &nPosition, int64 &nLength ) { return m_pFileSystemPassThru->GetPackFileInfoFromRelativePath( pFileName, pPathID, pPackPath, nPackPathBufferSize, nPosition, nLength ); }
+#endif
+
+ virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) { return m_pFileSystemPassThru->GetSearchPath( pathID, bGetPackFiles, pPath, nMaxLen ); }
+
+ virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) { return m_pFileSystemPassThru->OpenEx( pFileName, pOptions, flags, pathID, ppszResolvedFilename );}
+ virtual int ReadEx( void* pOutput, int destSize, int size, FileHandle_t file ) { return m_pFileSystemPassThru->ReadEx( pOutput, destSize, size, file ); }
+ virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate, bool bOptimalAlloc, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadFileEx( pFileName, pPath, ppBuf, bNullTerminate, bOptimalAlloc, nMaxBytes, nStartingByte, pfnAlloc ); }
+
+#if defined( TRACK_BLOCKING_IO )
+ virtual void EnableBlockingFileAccessTracking( bool state ) { m_pFileSystemPassThru->EnableBlockingFileAccessTracking( state ); }
+ virtual bool IsBlockingFileAccessEnabled() const { return m_pFileSystemPassThru->IsBlockingFileAccessEnabled(); }
+
+ virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() { return m_pFileSystemPassThru->RetrieveBlockingFileAccessInfo(); }
+#endif
+ virtual void SetupPreloadData() {}
+ virtual void DiscardPreloadData() {}
+
+ // If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup.
+ // Otherwise, it'll just fall through to the regular KeyValues loading routines
+ virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->LoadKeyValues( type, filename, pPathID ); }
+ virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->LoadKeyValues( head, type, filename, pPathID ); }
+
+ virtual bool GetFileTypeForFullPath( char const *pFullPath, wchar_t *buf, size_t bufSizeInBytes ) { return m_pFileSystemPassThru->GetFileTypeForFullPath( pFullPath, buf, bufSizeInBytes ); }
+
+ virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) { return m_pFileSystemPassThru->GetOptimalIOConstraints( hFile, pOffsetAlign, pSizeAlign, pBufferAlign ); }
+ virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize, unsigned nOffset ) { return m_pFileSystemPassThru->AllocOptimalReadBuffer( hFile, nOffset, nSize ); }
+ virtual void FreeOptimalReadBuffer( void *p ) { m_pFileSystemPassThru->FreeOptimalReadBuffer( p ); }
+
+ virtual void BeginMapAccess() { m_pFileSystemPassThru->BeginMapAccess(); }
+ virtual void EndMapAccess() { m_pFileSystemPassThru->EndMapAccess(); }
+
+ virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadToBuffer( hFile, buf, nMaxBytes, pfnAlloc ); }
+ virtual bool FullPathToRelativePathEx( const char *pFullPath, const char *pPathId, char *pRelative, int nMaxLen ) { return m_pFileSystemPassThru->FullPathToRelativePathEx( pFullPath, pPathId, pRelative, nMaxLen ); }
+ virtual int GetPathIndex( const FileNameHandle_t &handle ) { return m_pFileSystemPassThru->GetPathIndex( handle ); }
+ virtual long GetPathTime( const char *pPath, const char *pPathID ) { return m_pFileSystemPassThru->GetPathTime( pPath, pPathID ); }
+
+ virtual DVDMode_t GetDVDMode() { return m_pFileSystemPassThru->GetDVDMode(); }
+
+ virtual void EnableWhitelistFileTracking( bool bEnable )
+ { m_pFileSystemPassThru->EnableWhitelistFileTracking( bEnable ); }
+ virtual void RegisterFileWhitelist( IFileList *pForceMatchList, IFileList *pAllowFromDiskList, IFileList **pFilesToReload )
+ { m_pFileSystemPassThru->RegisterFileWhitelist( pForceMatchList, pAllowFromDiskList, pFilesToReload ); }
+ virtual void MarkAllCRCsUnverified()
+ { m_pFileSystemPassThru->MarkAllCRCsUnverified(); }
+ virtual void CacheFileCRCs( const char *pPathname, ECacheCRCType eType, IFileList *pFilter )
+ { return m_pFileSystemPassThru->CacheFileCRCs( pPathname, eType, pFilter ); }
+ virtual EFileCRCStatus CheckCachedFileCRC( const char *pPathID, const char *pRelativeFilename, CRC32_t *pCRC )
+ { return m_pFileSystemPassThru->CheckCachedFileCRC( pPathID, pRelativeFilename, pCRC ); }
+ virtual int GetUnverifiedCRCFiles( CUnverifiedCRCFile *pFiles, int nMaxFiles )
+ { return m_pFileSystemPassThru->GetUnverifiedCRCFiles( pFiles, nMaxFiles ); }
+ virtual int GetWhitelistSpewFlags()
+ { return m_pFileSystemPassThru->GetWhitelistSpewFlags(); }
+ virtual void SetWhitelistSpewFlags( int spewFlags )
+ { m_pFileSystemPassThru->SetWhitelistSpewFlags( spewFlags ); }
+ virtual void InstallDirtyDiskReportFunc( FSDirtyDiskReportFunc_t func ) { m_pFileSystemPassThru->InstallDirtyDiskReportFunc( func ); }
+
+ virtual bool IsLaunchedFromXboxHDD() { return m_pFileSystemPassThru->IsLaunchedFromXboxHDD(); }
+ virtual bool IsInstalledToXboxHDDCache() { return m_pFileSystemPassThru->IsInstalledToXboxHDDCache(); }
+ virtual bool IsDVDHosted() { return m_pFileSystemPassThru->IsDVDHosted(); }
+ virtual bool IsInstallAllowed() { return m_pFileSystemPassThru->IsInstallAllowed(); }
+ virtual int GetSearchPathID( char *pPath, int nMaxLen ) { return m_pFileSystemPassThru->GetSearchPathID( pPath, nMaxLen ); }
+ virtual bool FixupSearchPathsAfterInstall() { return m_pFileSystemPassThru->FixupSearchPathsAfterInstall(); }
+
+ virtual FSDirtyDiskReportFunc_t GetDirtyDiskReportFunc() { return m_pFileSystemPassThru->GetDirtyDiskReportFunc(); }
+
+ virtual void AddVPKFile( char const *pPkName, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) { m_pFileSystemPassThru->AddVPKFile( pPkName, addType ); }
+ virtual void RemoveVPKFile( char const *pPkName ) { m_pFileSystemPassThru->RemoveVPKFile( pPkName ); }
+ virtual void GetVPKFileNames( CUtlVector<CUtlString> &destVector ) { m_pFileSystemPassThru->GetVPKFileNames( destVector ); }
+
+ virtual void RemoveAllMapSearchPaths( void ) { m_pFileSystemPassThru->RemoveAllMapSearchPaths(); }
+
+ virtual void SyncDvdDevCache( void ) { m_pFileSystemPassThru->SyncDvdDevCache(); }
+
+ virtual bool GetStringFromKVPool( CRC32_t poolKey, unsigned int key, char *pOutBuff, int buflen ) { return m_pFileSystemPassThru->GetStringFromKVPool( poolKey, key, pOutBuff, buflen ); }
+
+ virtual bool DiscoverDLC( int iController ) { return m_pFileSystemPassThru->DiscoverDLC( iController ); }
+ virtual int IsAnyDLCPresent( bool *pbDLCSearchPathMounted = NULL ) { return m_pFileSystemPassThru->IsAnyDLCPresent( pbDLCSearchPathMounted ); }
+ virtual bool GetAnyDLCInfo( int iDLC, unsigned int *pLicenseMask, wchar_t *pTitleBuff, int nOutTitleSize ) { return m_pFileSystemPassThru->GetAnyDLCInfo( iDLC, pLicenseMask, pTitleBuff, nOutTitleSize ); }
+ virtual int IsAnyCorruptDLC() { return m_pFileSystemPassThru->IsAnyCorruptDLC(); }
+ virtual bool GetAnyCorruptDLCInfo( int iCorruptDLC, wchar_t *pTitleBuff, int nOutTitleSize ) { return m_pFileSystemPassThru->GetAnyCorruptDLCInfo( iCorruptDLC, pTitleBuff, nOutTitleSize ); }
+ virtual bool AddDLCSearchPaths() { return m_pFileSystemPassThru->AddDLCSearchPaths(); }
+ virtual bool IsSpecificDLCPresent( unsigned int nDLCPackage ) { return m_pFileSystemPassThru->IsSpecificDLCPresent( nDLCPackage ); }
+ virtual void SetIODelayAlarm( float flThreshhold ) { m_pFileSystemPassThru->SetIODelayAlarm( flThreshhold ); }
+ virtual bool AddXLSPUpdateSearchPath( const void *pData, int nSize ) { return m_pFileSystemPassThru->AddXLSPUpdateSearchPath( pData, nSize ); }
+ virtual IIoStats *GetIoStats() { return m_pFileSystemPassThru->GetIoStats(); }
+
+protected:
+ IFileSystem *m_pFileSystemPassThru;
+};
+
+
+// This is so people who change the filesystem interface are forced to add the passthru wrapper into CFileSystemPassThru,
+// so they don't break VMPI.
+inline void GiveMeACompileError()
+{
+ CFileSystemPassThru asdf;
+}
+
+
+#endif // FILESYSTEM_PASSTHRU_H
diff --git a/external/vpc/public/icvar.h b/external/vpc/public/icvar.h
new file mode 100644
index 0000000..b471a3b
--- /dev/null
+++ b/external/vpc/public/icvar.h
@@ -0,0 +1,211 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef ICVAR_H
+#define ICVAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "appframework/iappsystem.h"
+#include "tier1/iconvar.h"
+#include "tier1/utlvector.h"
+
+
+class ConCommandBase;
+class ConCommand;
+class ConVar;
+class Color;
+
+
+//-----------------------------------------------------------------------------
+// ConVars/ComCommands are marked as having a particular DLL identifier
+//-----------------------------------------------------------------------------
+typedef int CVarDLLIdentifier_t;
+
+
+//-----------------------------------------------------------------------------
+// Used to display console messages
+//-----------------------------------------------------------------------------
+abstract_class IConsoleDisplayFunc
+{
+public:
+ virtual void ColorPrint( const Color& clr, const char *pMessage ) = 0;
+ virtual void Print( const char *pMessage ) = 0;
+ virtual void DPrint( const char *pMessage ) = 0;
+
+ virtual void GetConsoleText( char *pchText, size_t bufSize ) const = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Applications can implement this to modify behavior in ICvar
+//-----------------------------------------------------------------------------
+#define CVAR_QUERY_INTERFACE_VERSION "VCvarQuery001"
+abstract_class ICvarQuery : public IAppSystem
+{
+public:
+ // Can these two convars be aliased?
+ virtual bool AreConVarsLinkable( const ConVar *child, const ConVar *parent ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: DLL interface to ConVars/ConCommands
+//-----------------------------------------------------------------------------
+abstract_class ICvar : public IAppSystem
+{
+public:
+ // Allocate a unique DLL identifier
+ virtual CVarDLLIdentifier_t AllocateDLLIdentifier() = 0;
+
+ // Register, unregister commands
+ virtual void RegisterConCommand( ConCommandBase *pCommandBase ) = 0;
+ virtual void UnregisterConCommand( ConCommandBase *pCommandBase ) = 0;
+ virtual void UnregisterConCommands( CVarDLLIdentifier_t id ) = 0;
+
+ // If there is a +<varname> <value> on the command line, this returns the value.
+ // Otherwise, it returns NULL.
+ virtual const char* GetCommandLineValue( const char *pVariableName ) = 0;
+
+ // Try to find the cvar pointer by name
+ virtual ConCommandBase *FindCommandBase( const char *name ) = 0;
+ virtual const ConCommandBase *FindCommandBase( const char *name ) const = 0;
+ virtual ConVar *FindVar ( const char *var_name ) = 0;
+ virtual const ConVar *FindVar ( const char *var_name ) const = 0;
+ virtual ConCommand *FindCommand( const char *name ) = 0;
+ virtual const ConCommand *FindCommand( const char *name ) const = 0;
+
+
+
+ // Install a global change callback (to be called when any convar changes)
+ virtual void InstallGlobalChangeCallback( FnChangeCallback_t callback ) = 0;
+ virtual void RemoveGlobalChangeCallback( FnChangeCallback_t callback ) = 0;
+ virtual void CallGlobalChangeCallbacks( ConVar *var, const char *pOldString, float flOldValue ) = 0;
+
+ // Install a console printer
+ virtual void InstallConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc ) = 0;
+ virtual void RemoveConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc ) = 0;
+ virtual void ConsoleColorPrintf( const Color& clr, const char *pFormat, ... ) const = 0;
+ virtual void ConsolePrintf( const char *pFormat, ... ) const = 0;
+ virtual void ConsoleDPrintf( const char *pFormat, ... ) const = 0;
+
+ // Reverts cvars which contain a specific flag
+ virtual void RevertFlaggedConVars( int nFlag ) = 0;
+
+ // Method allowing the engine ICvarQuery interface to take over
+ // A little hacky, owing to the fact the engine is loaded
+ // well after ICVar, so we can't use the standard connect pattern
+ virtual void InstallCVarQuery( ICvarQuery *pQuery ) = 0;
+
+#if defined( USE_VXCONSOLE )
+ virtual void PublishToVXConsole( ) = 0;
+#endif
+
+ virtual void SetMaxSplitScreenSlots( int nSlots ) = 0;
+ virtual int GetMaxSplitScreenSlots() const = 0;
+
+ virtual void AddSplitScreenConVars() = 0;
+ virtual void RemoveSplitScreenConVars( CVarDLLIdentifier_t id ) = 0;
+
+ virtual int GetConsoleDisplayFuncCount() const = 0;
+ virtual void GetConsoleText( int nDisplayFuncIndex, char *pchText, size_t bufSize ) const = 0;
+
+ // Utilities for convars accessed by the material system thread
+ virtual bool IsMaterialThreadSetAllowed( ) const = 0;
+ virtual void QueueMaterialThreadSetValue( ConVar *pConVar, const char *pValue ) = 0;
+ virtual void QueueMaterialThreadSetValue( ConVar *pConVar, int nValue ) = 0;
+ virtual void QueueMaterialThreadSetValue( ConVar *pConVar, float flValue ) = 0;
+ virtual bool HasQueuedMaterialThreadConVarSets() const = 0;
+ virtual int ProcessQueuedMaterialThreadConVarSets() = 0;
+
+protected: class ICVarIteratorInternal;
+public:
+ /// Iteration over all cvars.
+ /// (THIS IS A SLOW OPERATION AND YOU SHOULD AVOID IT.)
+ /// usage:
+ /// { ICVar::Iterator iter(g_pCVar);
+ /// for ( iter.SetFirst() ; iter.IsValid() ; iter.Next() )
+ /// {
+ /// ConCommandBase *cmd = iter.Get();
+ /// }
+ /// }
+ /// The Iterator class actually wraps the internal factory methods
+ /// so you don't need to worry about new/delete -- scope takes care
+ // of it.
+ /// We need an iterator like this because we can't simply return a
+ /// pointer to the internal data type that contains the cvars --
+ /// it's a custom, protected class with unusual semantics and is
+ /// prone to change.
+ class Iterator
+ {
+ public:
+ inline Iterator(ICvar *icvar);
+ inline ~Iterator(void);
+ inline void SetFirst( void );
+ inline void Next( void );
+ inline bool IsValid( void );
+ inline ConCommandBase *Get( void );
+ private:
+ ICVarIteratorInternal *m_pIter;
+ };
+
+protected:
+ // internals for ICVarIterator
+ class ICVarIteratorInternal
+ {
+ public:
+ virtual void SetFirst( void ) = 0;
+ virtual void Next( void ) = 0;
+ virtual bool IsValid( void ) = 0;
+ virtual ConCommandBase *Get( void ) = 0;
+ };
+
+ virtual ICVarIteratorInternal *FactoryInternalIterator( void ) = 0;
+ friend class Iterator;
+};
+
+inline ICvar::Iterator::Iterator(ICvar *icvar)
+{
+ m_pIter = icvar->FactoryInternalIterator();
+}
+
+inline ICvar::Iterator::~Iterator( void )
+{
+ delete m_pIter;
+}
+
+inline void ICvar::Iterator::SetFirst( void )
+{
+ m_pIter->SetFirst();
+}
+
+inline void ICvar::Iterator::Next( void )
+{
+ m_pIter->Next();
+}
+
+inline bool ICvar::Iterator::IsValid( void )
+{
+ return m_pIter->IsValid();
+}
+
+inline ConCommandBase * ICvar::Iterator::Get( void )
+{
+ return m_pIter->Get();
+}
+
+
+//-----------------------------------------------------------------------------
+// These global names are defined by tier1.h, duplicated here so you
+// don't have to include tier1.h
+//-----------------------------------------------------------------------------
+
+// These are marked DLL_EXPORT for Linux.
+DECLARE_TIER1_INTERFACE( ICvar, cvar );
+DECLARE_TIER1_INTERFACE( ICvar, g_pCVar );
+
+
+#endif // ICVAR_H
diff --git a/external/vpc/public/ilaunchabledll.h b/external/vpc/public/ilaunchabledll.h
new file mode 100644
index 0000000..4062588
--- /dev/null
+++ b/external/vpc/public/ilaunchabledll.h
@@ -0,0 +1,28 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef ILAUNCHABLEDLL_H
+#define ILAUNCHABLEDLL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#define LAUNCHABLE_DLL_INTERFACE_VERSION "launchable_dll_1"
+
+
+// vmpi_service can use this to debug worker apps in-process,
+// and some of the launchers (like texturecompile) use this.
+class ILaunchableDLL
+{
+public:
+ // All vrad.exe does is load the VRAD DLL and run this.
+ virtual int main( int argc, char **argv ) = 0;
+};
+
+
+
+#endif // ILAUNCHABLEDLL_H
diff --git a/external/vpc/public/interfaces/interfaces.h b/external/vpc/public/interfaces/interfaces.h
new file mode 100644
index 0000000..6e3166f
--- /dev/null
+++ b/external/vpc/public/interfaces/interfaces.h
@@ -0,0 +1,287 @@
+//===== Copyright � 2005-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: A higher level link library for general use in the game and tools.
+//
+//===========================================================================//
+
+
+#ifndef INTERFACES_H
+#define INTERFACES_H
+
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Interface creation function
+//-----------------------------------------------------------------------------
+typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode);
+
+
+//-----------------------------------------------------------------------------
+// Macros to declare interfaces appropriate for various tiers
+//-----------------------------------------------------------------------------
+#if 1 || defined( TIER1_LIBRARY ) || defined( TIER2_LIBRARY ) || defined( TIER3_LIBRARY ) || defined( TIER4_LIBRARY ) || defined( APPLICATION )
+#define DECLARE_TIER1_INTERFACE( _Interface, _Global ) extern _Interface * _Global;
+#else
+#define DECLARE_TIER1_INTERFACE( _Interface, _Global )
+#endif
+
+#if 1 || defined( TIER2_LIBRARY ) || defined( TIER3_LIBRARY ) || defined( TIER4_LIBRARY ) || defined( APPLICATION )
+#define DECLARE_TIER2_INTERFACE( _Interface, _Global ) extern _Interface * _Global;
+#else
+#define DECLARE_TIER2_INTERFACE( _Interface, _Global )
+#endif
+
+#if 1 || defined( TIER3_LIBRARY ) || defined( TIER4_LIBRARY ) || defined( APPLICATION )
+#define DECLARE_TIER3_INTERFACE( _Interface, _Global ) extern _Interface * _Global;
+#else
+#define DECLARE_TIER3_INTERFACE( _Interface, _Global )
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class ICvar;
+class IProcessUtils;
+class ILocalize;
+class IPhysics2;
+class IPhysics2ActorManager;
+class IPhysics2ResourceManager;
+class IEventSystem;
+
+class IAsyncFileSystem;
+class IColorCorrectionSystem;
+class IDebugTextureInfo;
+class IFileSystem;
+class IRenderHardwareConfig;
+class IInputSystem;
+class IInputStackSystem;
+class IMaterialSystem;
+class IMaterialSystem2;
+class IMaterialSystemHardwareConfig;
+class IMdlLib;
+class INetworkSystem;
+class IP4;
+class IQueuedLoader;
+class IResourceAccessControl;
+class IPrecacheSystem;
+class IRenderDevice;
+class IRenderDeviceMgr;
+class IResourceSystem;
+class IVBAllocTracker;
+class IXboxInstaller;
+class IMatchFramework;
+class ISoundSystem;
+class IStudioRender;
+class IMatSystemSurface;
+class IGameUISystemMgr;
+class IDataCache;
+class IMDLCache;
+class IAvi;
+class IBik;
+class IDmeMakefileUtils;
+class IPhysicsCollision;
+class ISoundEmitterSystemBase;
+class IMeshSystem;
+class IWorldRendererMgr;
+class ISceneSystem;
+class IVGuiRenderSurface;
+
+namespace vgui
+{
+ class ISurface;
+ class IVGui;
+ class IInput;
+ class IPanel;
+ class IVGUILocalize;
+ class ISchemeManager;
+ class ISystem;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Fills out global DLL exported interface pointers
+//-----------------------------------------------------------------------------
+#define CVAR_INTERFACE_VERSION "VEngineCvar007"
+DECLARE_TIER1_INTERFACE( ICvar, cvar );
+DECLARE_TIER1_INTERFACE( ICvar, g_pCVar )
+
+#define PROCESS_UTILS_INTERFACE_VERSION "VProcessUtils002"
+DECLARE_TIER1_INTERFACE( IProcessUtils, g_pProcessUtils );
+
+#define VPHYSICS2_INTERFACE_VERSION "Physics2 Interface v0.3"
+DECLARE_TIER1_INTERFACE( IPhysics2, g_pPhysics2 );
+
+#define VPHYSICS2_ACTOR_MGR_INTERFACE_VERSION "Physics2 Interface ActorMgr v0.1"
+DECLARE_TIER1_INTERFACE( IPhysics2ActorManager, g_pPhysics2ActorManager );
+
+#define VPHYSICS2_RESOURCE_MGR_INTERFACE_VERSION "Physics2 Interface ResourceMgr v0.1"
+DECLARE_TIER1_INTERFACE( IPhysics2ResourceManager, g_pPhysics2ResourceManager );
+
+#define EVENTSYSTEM_INTERFACE_VERSION "EventSystem001"
+DECLARE_TIER1_INTERFACE( IEventSystem, g_pEventSystem );
+
+#define LOCALIZE_INTERFACE_VERSION "Localize_001"
+DECLARE_TIER2_INTERFACE( ILocalize, g_pLocalize );
+DECLARE_TIER3_INTERFACE( vgui::IVGUILocalize, g_pVGuiLocalize );
+
+#define RENDER_DEVICE_MGR_INTERFACE_VERSION "RenderDeviceMgr001"
+DECLARE_TIER2_INTERFACE( IRenderDeviceMgr, g_pRenderDeviceMgr );
+
+#define FILESYSTEM_INTERFACE_VERSION "VFileSystem017"
+DECLARE_TIER2_INTERFACE( IFileSystem, g_pFullFileSystem );
+
+#define ASYNCFILESYSTEM_INTERFACE_VERSION "VNewAsyncFileSystem001"
+DECLARE_TIER2_INTERFACE( IAsyncFileSystem, g_pAsyncFileSystem );
+
+#define RESOURCESYSTEM_INTERFACE_VERSION "ResourceSystem004"
+DECLARE_TIER2_INTERFACE( IResourceSystem, g_pResourceSystem );
+
+#define MATERIAL_SYSTEM_INTERFACE_VERSION "VMaterialSystem080"
+DECLARE_TIER2_INTERFACE( IMaterialSystem, materials );
+DECLARE_TIER2_INTERFACE( IMaterialSystem, g_pMaterialSystem );
+
+#define MATERIAL_SYSTEM2_INTERFACE_VERSION "VMaterialSystem2_001"
+DECLARE_TIER2_INTERFACE( IMaterialSystem2, g_pMaterialSystem2 );
+
+#define INPUTSYSTEM_INTERFACE_VERSION "InputSystemVersion001"
+DECLARE_TIER2_INTERFACE( IInputSystem, g_pInputSystem );
+
+#define INPUTSTACKSYSTEM_INTERFACE_VERSION "InputStackSystemVersion001"
+DECLARE_TIER2_INTERFACE( IInputStackSystem, g_pInputStackSystem );
+
+#define NETWORKSYSTEM_INTERFACE_VERSION "NetworkSystemVersion001"
+DECLARE_TIER2_INTERFACE( INetworkSystem, g_pNetworkSystem );
+
+#define MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION "MaterialSystemHardwareConfig013"
+DECLARE_TIER2_INTERFACE( IMaterialSystemHardwareConfig, g_pMaterialSystemHardwareConfig );
+
+#define DEBUG_TEXTURE_INFO_VERSION "DebugTextureInfo001"
+DECLARE_TIER2_INTERFACE( IDebugTextureInfo, g_pMaterialSystemDebugTextureInfo );
+
+#define VB_ALLOC_TRACKER_INTERFACE_VERSION "VBAllocTracker001"
+DECLARE_TIER2_INTERFACE( IVBAllocTracker, g_VBAllocTracker );
+
+#define COLORCORRECTION_INTERFACE_VERSION "COLORCORRECTION_VERSION_1"
+DECLARE_TIER2_INTERFACE( IColorCorrectionSystem, colorcorrection );
+
+#define P4_INTERFACE_VERSION "VP4002"
+DECLARE_TIER2_INTERFACE( IP4, p4 );
+
+#define MDLLIB_INTERFACE_VERSION "VMDLLIB001"
+DECLARE_TIER2_INTERFACE( IMdlLib, mdllib );
+
+#define QUEUEDLOADER_INTERFACE_VERSION "QueuedLoaderVersion001"
+DECLARE_TIER2_INTERFACE( IQueuedLoader, g_pQueuedLoader );
+
+#define RESOURCE_ACCESS_CONTROL_INTERFACE_VERSION "VResourceAccessControl001"
+DECLARE_TIER2_INTERFACE( IResourceAccessControl, g_pResourceAccessControl );
+
+#define PRECACHE_SYSTEM_INTERFACE_VERSION "VPrecacheSystem001"
+DECLARE_TIER2_INTERFACE( IPrecacheSystem, g_pPrecacheSystem );
+
+#if defined( _X360 )
+#define XBOXINSTALLER_INTERFACE_VERSION "XboxInstallerVersion001"
+DECLARE_TIER2_INTERFACE( IXboxInstaller, g_pXboxInstaller );
+#endif
+
+#define MATCHFRAMEWORK_INTERFACE_VERSION "MATCHFRAMEWORK_001"
+DECLARE_TIER2_INTERFACE( IMatchFramework, g_pMatchFramework );
+
+#define GAMEUISYSTEMMGR_INTERFACE_VERSION "GameUISystemMgr001"
+DECLARE_TIER3_INTERFACE( IGameUISystemMgr, g_pGameUISystemMgr );
+
+
+//-----------------------------------------------------------------------------
+// Not exactly a global, but we're going to keep track of these here anyways
+// NOTE: Appframework deals with connecting these bad boys. See materialsystem2app.cpp
+//-----------------------------------------------------------------------------
+#define RENDER_DEVICE_INTERFACE_VERSION "RenderDevice001"
+DECLARE_TIER2_INTERFACE( IRenderDevice, g_pRenderDevice );
+
+#define RENDER_HARDWARECONFIG_INTERFACE_VERSION "RenderHardwareConfig001"
+DECLARE_TIER2_INTERFACE( IRenderHardwareConfig, g_pRenderHardwareConfig );
+
+#define SOUNDSYSTEM_INTERFACE_VERSION "SoundSystem001"
+DECLARE_TIER2_INTERFACE( ISoundSystem, g_pSoundSystem );
+
+#define MESHSYSTEM_INTERFACE_VERSION "MeshSystem001"
+DECLARE_TIER3_INTERFACE( IMeshSystem, g_pMeshSystem );
+
+#define STUDIO_RENDER_INTERFACE_VERSION "VStudioRender026"
+DECLARE_TIER3_INTERFACE( IStudioRender, g_pStudioRender );
+DECLARE_TIER3_INTERFACE( IStudioRender, studiorender );
+
+#define MAT_SYSTEM_SURFACE_INTERFACE_VERSION "MatSystemSurface006"
+DECLARE_TIER3_INTERFACE( IMatSystemSurface, g_pMatSystemSurface );
+
+#define RENDER_SYSTEM_SURFACE_INTERFACE_VERSION "RenderSystemSurface001"
+DECLARE_TIER3_INTERFACE( IVGuiRenderSurface, g_pVGuiRenderSurface );
+
+#define SCENESYSTEM_INTERFACE_VERSION "SceneSystem_001"
+DECLARE_TIER3_INTERFACE( ISceneSystem, g_pSceneSystem );
+
+#define VGUI_SURFACE_INTERFACE_VERSION "VGUI_Surface031"
+DECLARE_TIER3_INTERFACE( vgui::ISurface, g_pVGuiSurface );
+
+#define SCHEME_SURFACE_INTERFACE_VERSION "SchemeSurface001"
+
+#define VGUI_INPUT_INTERFACE_VERSION "VGUI_Input005"
+DECLARE_TIER3_INTERFACE( vgui::IInput, g_pVGuiInput );
+
+#define VGUI_IVGUI_INTERFACE_VERSION "VGUI_ivgui008"
+DECLARE_TIER3_INTERFACE( vgui::IVGui, g_pVGui );
+
+#define VGUI_PANEL_INTERFACE_VERSION "VGUI_Panel009"
+DECLARE_TIER3_INTERFACE( vgui::IPanel, g_pVGuiPanel );
+
+#define VGUI_SCHEME_INTERFACE_VERSION "VGUI_Scheme010"
+DECLARE_TIER3_INTERFACE( vgui::ISchemeManager, g_pVGuiSchemeManager );
+
+#define VGUI_SYSTEM_INTERFACE_VERSION "VGUI_System010"
+DECLARE_TIER3_INTERFACE( vgui::ISystem, g_pVGuiSystem );
+
+#define DATACACHE_INTERFACE_VERSION "VDataCache003"
+DECLARE_TIER3_INTERFACE( IDataCache, g_pDataCache ); // FIXME: Should IDataCache be in tier2?
+
+#define MDLCACHE_INTERFACE_VERSION "MDLCache004"
+DECLARE_TIER3_INTERFACE( IMDLCache, g_pMDLCache );
+DECLARE_TIER3_INTERFACE( IMDLCache, mdlcache );
+
+#define AVI_INTERFACE_VERSION "VAvi001"
+DECLARE_TIER3_INTERFACE( IAvi, g_pAVI );
+
+#define BIK_INTERFACE_VERSION "VBik001"
+DECLARE_TIER3_INTERFACE( IBik, g_pBIK );
+
+#define DMEMAKEFILE_UTILS_INTERFACE_VERSION "VDmeMakeFileUtils001"
+DECLARE_TIER3_INTERFACE( IDmeMakefileUtils, g_pDmeMakefileUtils );
+
+#define VPHYSICS_COLLISION_INTERFACE_VERSION "VPhysicsCollision007"
+DECLARE_TIER3_INTERFACE( IPhysicsCollision, g_pPhysicsCollision );
+
+#define SOUNDEMITTERSYSTEM_INTERFACE_VERSION "VSoundEmitter003"
+DECLARE_TIER3_INTERFACE( ISoundEmitterSystemBase, g_pSoundEmitterSystem );
+
+#define WORLD_RENDERER_MGR_INTERFACE_VERSION "WorldRendererMgr001"
+DECLARE_TIER3_INTERFACE( IWorldRendererMgr, g_pWorldRendererMgr );
+
+//-----------------------------------------------------------------------------
+// Fills out global DLL exported interface pointers
+//-----------------------------------------------------------------------------
+void ConnectInterfaces( CreateInterfaceFn *pFactoryList, int nFactoryCount );
+void DisconnectInterfaces();
+
+
+//-----------------------------------------------------------------------------
+// Reconnects an interface
+//-----------------------------------------------------------------------------
+void ReconnectInterface( CreateInterfaceFn factory, const char *pInterfaceName );
+
+
+#endif // INTERFACES_H
+
diff --git a/external/vpc/public/mathlib/fltx4.h b/external/vpc/public/mathlib/fltx4.h
new file mode 100644
index 0000000..a32877b
--- /dev/null
+++ b/external/vpc/public/mathlib/fltx4.h
@@ -0,0 +1,97 @@
+//===== Copyright 1996-2010, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: - defines the type fltx4 - Avoid cyclic includion.
+//
+//===========================================================================//
+
+#ifndef FLTX4_H
+#define FLTX4_H
+
+#if defined(GNUC)
+#define USE_STDC_FOR_SIMD 0
+#else
+#define USE_STDC_FOR_SIMD 0
+#endif
+
+#if (!defined(PLATFORM_PPC) && (USE_STDC_FOR_SIMD == 0))
+#define _SSE1 1
+#endif
+
+// I thought about defining a class/union for the SIMD packed floats instead of using fltx4,
+// but decided against it because (a) the nature of SIMD code which includes comparisons is to blur
+// the relationship between packed floats and packed integer types and (b) not sure that the
+// compiler would handle generating good code for the intrinsics.
+
+#if USE_STDC_FOR_SIMD
+
+#error "hello"
+typedef union
+{
+ float m128_f32[4];
+ uint32 m128_u32[4];
+} fltx4;
+
+typedef fltx4 i32x4;
+typedef fltx4 u32x4;
+
+#ifdef _PS3
+typedef fltx4 u32x4;
+typedef fltx4 i32x4;
+#endif
+typedef fltx4 bi32x4;
+
+#elif ( defined( _PS3 ) )
+
+typedef union
+{
+ // This union allows float/int access (which generally shouldn't be done in inner loops)
+
+ vec_float4 vmxf;
+ vec_int4 vmxi;
+ vec_uint4 vmxui;
+ __vector bool vmxbi;
+
+ struct
+ {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ float m128_f32[4];
+ uint32 m128_u32[4];
+ int32 m128_i32[4];
+
+} fltx4_union;
+
+typedef vec_float4 fltx4;
+typedef vec_uint4 u32x4;
+typedef vec_int4 i32x4;
+typedef __vector bool bi32x4;
+#define DIFFERENT_NATIVE_VECTOR_TYPES // true if the compiler has different types for float4, uint4, int4, etc
+
+#elif ( defined( _X360 ) )
+
+typedef union
+{
+ // This union allows float/int access (which generally shouldn't be done in inner loops)
+ __vector4 vmx;
+ float m128_f32[4];
+ uint32 m128_u32[4];
+} fltx4_union;
+
+typedef __vector4 fltx4;
+typedef __vector4 i32x4; // a VMX register; just a way of making it explicit that we're doing integer ops.
+typedef __vector4 u32x4; // a VMX register; just a way of making it explicit that we're doing unsigned integer ops.
+typedef fltx4 bi32x4;
+#else
+
+typedef __m128 fltx4;
+typedef __m128 i32x4;
+typedef __m128 u32x4;
+typedef fltx4 bi32x4;
+
+#endif
+
+#endif
diff --git a/external/vpc/public/mathlib/math_pfns.h b/external/vpc/public/mathlib/math_pfns.h
new file mode 100644
index 0000000..23a4f6b
--- /dev/null
+++ b/external/vpc/public/mathlib/math_pfns.h
@@ -0,0 +1,283 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=====================================================================================//
+
+#ifndef _MATH_PFNS_H_
+#define _MATH_PFNS_H_
+
+#include <limits>
+
+#if defined( _X360 )
+#include <xboxmath.h>
+#elif defined(_PS3)
+
+#ifndef SPU
+#include <ppu_asm_intrinsics.h>
+#endif
+
+// Note that similar defines exist in ssemath.h
+// Maybe we should consolidate in one place for all platforms.
+
+#define _VEC_0x7ff (vec_int4){0x7ff,0x7ff,0x7ff,0x7ff}
+#define _VEC_0x3ff (vec_int4){0x3ff,0x3ff,0x3ff,0x3ff}
+#define _VEC_22L (vector unsigned int){22,22,22,22}
+#define _VEC_11L (vector unsigned int){11,11,11,11}
+#define _VEC_0L (vector unsigned int){0,0,0,0}
+#define _VEC_255F (vector float){255.0f,255.0f,255.0f,255.0f}
+#define _VEC_NEGONEF (vector float){-1.0f,-1.0f,-1.0f,-1.0f}
+#define _VEC_ONEF (vector float){1.0f,1.0f,1.0f,1.0f}
+#define _VEC_ZEROF (vector float){0.0f,0.0f,0.0f,0.0f}
+#define _VEC_ZEROxyzONEwF (vector float){0.0f,0.0f,0.0f,1.0f}
+#define _VEC_HALFF (vector float){0.5f,0.5f,0.5f,0.5f}
+#define _VEC_HALFxyzZEROwF (vector float){0.5f,0.5f,0.5f,0.0f}
+#define _VEC_PERMUTE_XYZ0W1 (vector unsigned char){0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x1c,0x1d,0x1e,0x1f}
+
+#define _VEC_IEEEHACK (vector float){(float)(1 << 23),(float)(1 << 23),(float)(1 << 23),(float)(1 << 23)}
+#define _VEC_PERMUTE_FASTFTOC (vector unsigned char){0,0,0,0,0,0,0,0,0,0,0,0,0x03,0x07,0x0b,0x0f}
+
+// AngleQuaternion
+#define _VEC_PERMUTE_AQsxsxcxcx (vector unsigned char) {0x00,0x01,0x02,0x03,0x00,0x01,0x02,0x03,0x10,0x11,0x12,0x13,0x10,0x11,0x12,0x13}
+#define _VEC_PERMUTE_AQczszszcz (vector unsigned char) {0x18,0x19,0x1a,0x1b,0x08,0x09,0x0a,0x0b,0x08,0x09,0x0a,0x0b,0x18,0x19,0x1a,0x1b}
+#define _VEC_PERMUTE_AQcxcxsxsx (vector unsigned char) {0x10,0x11,0x12,0x13,0x10,0x11,0x12,0x13,0x00,0x01,0x02,0x03,0x00,0x01,0x02,0x03}
+#define _VEC_PERMUTE_AQszczczsz (vector unsigned char) {0x08,0x09,0x0a,0x0b,0x18,0x19,0x1a,0x1b,0x18,0x19,0x1a,0x1b,0x08,0x09,0x0a,0x0b}
+#define _VEC_PERMUTE_ANGLEQUAT (vector unsigned char) {0x10,0x11,0x12,0x13,0x04,0x05,0x06,0x07,0x18,0x19,0x1a,0x1b,0x0c,0x0d,0x0e,0x0f}
+
+#define _VEC_EPSILONF (__vector float) {FLT_EPSILON,FLT_EPSILON,FLT_EPSILON,FLT_EPSILON}
+
+#endif
+
+#if !(defined( PLATFORM_PPC ) || defined(SPU))
+// If we are not PPC based or SPU based, then assumes it is SSE2. We should make this code cleaner.
+
+#include <xmmintrin.h>
+
+// These globals are initialized by mathlib and redirected based on available fpu features
+
+// The following are not declared as macros because they are often used in limiting situations,
+// and sometimes the compiler simply refuses to inline them for some reason
+FORCEINLINE float FastSqrt( float x )
+{
+ __m128 root = _mm_sqrt_ss( _mm_load_ss( &x ) );
+ return *( reinterpret_cast<float *>( &root ) );
+}
+
+FORCEINLINE float FastRSqrtFast( float x )
+{
+ // use intrinsics
+ __m128 rroot = _mm_rsqrt_ss( _mm_load_ss( &x ) );
+ return *( reinterpret_cast<float *>( &rroot ) );
+}
+// Single iteration NewtonRaphson reciprocal square root:
+// 0.5 * rsqrtps * (3 - x * rsqrtps(x) * rsqrtps(x))
+// Very low error, and fine to use in place of 1.f / sqrtf(x).
+FORCEINLINE float FastRSqrt( float x )
+{
+ float rroot = FastRSqrtFast( x );
+ return (0.5f * rroot) * (3.f - (x * rroot) * rroot);
+}
+
+void FastSinCos( float x, float* s, float* c ); // any x
+float FastCos( float x );
+
+
+
+inline float FastRecip(float x) {return 1.0f / x;}
+// Simple SSE rsqrt. Usually accurate to around 6 (relative) decimal places
+// or so, so ok for closed transforms. (ie, computing lighting normals)
+inline float FastSqrtEst(float x) { return FastRSqrtFast(x) * x; }
+
+
+#else // !defined( PLATFORM_PPC ) && !defined(_SPU)
+
+#ifndef SPU
+// We may not need this for SPU, so let's not bother for now
+
+FORCEINLINE float _VMX_Sqrt( float x )
+{
+ return __fsqrts( x );
+}
+
+FORCEINLINE double _VMX_RSqrt( double x )
+{
+ double rroot = __frsqrte( x );
+
+ // Single iteration NewtonRaphson on reciprocal square root estimate
+ return (0.5f * rroot) * (3.0f - (x * rroot) * rroot);
+}
+
+FORCEINLINE double _VMX_RSqrtFast( double x )
+{
+ return __frsqrte( x );
+}
+
+#ifdef _X360
+FORCEINLINE void _VMX_SinCos( float a, float *pS, float *pC )
+{
+ XMScalarSinCos( pS, pC, a );
+}
+
+FORCEINLINE float _VMX_Cos( float a )
+{
+ return XMScalarCos( a );
+}
+#endif
+
+// the 360 has fixed hw and calls directly
+#define FastSqrt(x) _VMX_Sqrt(x)
+#define FastRSqrt(x) _VMX_RSqrt(x)
+#define FastRSqrtFast(x) _VMX_RSqrtFast(x)
+#define FastSinCos(x,s,c) _VMX_SinCos(x,s,c)
+#define FastCos(x) _VMX_Cos(x)
+
+inline double FastRecip(double x) {return __fres(x);}
+inline double FastSqrtEst(double x) { return __frsqrte(x) * x; }
+
+#endif // !defined( PLATFORM_PPC ) && !defined(_SPU)
+
+// if x is infinite, return FLT_MAX
+inline float FastClampInfinity( float x )
+{
+#ifdef PLATFORM_PPC
+ return fsel( std::numeric_limits<float>::infinity() - x, x, FLT_MAX );
+#else
+ return ( x > FLT_MAX ? FLT_MAX : x );
+#endif
+}
+
+#if defined (_PS3) && !defined(SPU)
+
+// extern float cosvf(float); /* single precision cosine */
+// extern float sinvf(float); /* single precision sine */
+// TODO: need a faster single precision equivalent
+#define cosvf cosf
+#define sinvf sinf
+
+inline int _rotl( int x, int c )
+{
+ return __rlwimi(x,x,c,0,31);
+}
+
+inline int64 _rotl64( int64 x, int c )
+{
+ return __rldicl( x, c, 0 );
+}
+
+//-----------------------------------------------------------------
+// Vector Unions
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Floats
+//-----------------------------------------------------------------
+typedef union
+{
+ vector float vf;
+ float f[4];
+} vector_float_union;
+
+//-----------------------------------------------------------------
+// Ints
+//-----------------------------------------------------------------
+typedef union
+{
+ vector int vi;
+ int i[4];
+} vector_int4_union;
+
+typedef union
+{
+ vector unsigned int vui;
+ unsigned int ui[4];
+} vector_uint4_union;
+
+//-----------------------------------------------------------------
+// Shorts
+//-----------------------------------------------------------------
+typedef union
+{
+ vector signed short vs;
+ signed short s[8];
+} vector_short8_union;
+
+typedef union
+{
+ vector unsigned short vus;
+ unsigned short us[8];
+} vector_ushort8_union;
+
+//-----------------------------------------------------------------
+// Chars
+//-----------------------------------------------------------------
+typedef union
+{
+ vector signed char vc;
+ signed char c[16];
+} vector_char16_union;
+
+typedef union
+{
+ vector unsigned char vuc;
+ unsigned char uc[16];
+} vector_uchar16_union;
+
+/*
+FORCEINLINE float _VMX_Sqrt( float x )
+{
+ vector_float_union vIn, vOut;
+
+ vIn.f[0] = x;
+
+ vOut.vf = sqrtf4(vIn.vf);
+
+ return vOut.f[0];
+}
+
+FORCEINLINE float _VMX_RSqrt( float x )
+{
+ vector_float_union vIn, vOut;
+
+ vIn.f[0] = x;
+
+ vOut.vf = rsqrtf4(vIn.vf);
+
+ return vOut.f[0];
+}
+
+FORCEINLINE float _VMX_RSqrtFast( float x )
+{
+ vector_float_union vIn, vOut;
+
+ vIn.f[0] = x;
+
+ vOut.vf = rsqrtf4fast(vIn.vf);
+
+ return vOut.f[0];
+}
+*/
+
+FORCEINLINE void _VMX_SinCos( float a, float *pS, float *pC )
+{
+ *pS=sinvf(a);
+ *pC=cosvf(a);
+}
+
+FORCEINLINE float _VMX_Cos( float a )
+{
+ return cosvf(a);
+}
+
+
+// the 360 has fixed hw and calls directly
+/*
+#define FastSqrt(x) _VMX_Sqrt(x)
+#define FastRSqrt(x) _VMX_RSqrt(x)
+#define FastRSqrtFast(x) _VMX_RSqrtFast(x)
+#define FastSinCos(x,s,c) _VMX_SinCos(x,s,c)
+#define FastCos(x) _VMX_Cos(x)
+*/
+#endif // _PS3
+#endif // #ifndef SPU
+
+#endif // _MATH_PFNS_H_
diff --git a/external/vpc/public/mathlib/mathlib.h b/external/vpc/public/mathlib/mathlib.h
new file mode 100644
index 0000000..db1848f
--- /dev/null
+++ b/external/vpc/public/mathlib/mathlib.h
@@ -0,0 +1,2425 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef MATH_LIB_H
+#define MATH_LIB_H
+
+#include <math.h>
+#include "tier0/basetypes.h"
+#include "mathlib/vector.h"
+#include "mathlib/vector2d.h"
+#include "tier0/dbg.h"
+
+#include "mathlib/math_pfns.h"
+#include "mathlib/fltx4.h"
+
+#ifndef ALIGN8_POST
+#define ALIGN8_POST
+#endif
+
+#if defined(_PS3)
+
+#include <ppu_intrinsics.h>
+#include <altivec.h>
+#include <vectormath/c/vectormath_soa.h>
+
+#endif
+
+// plane_t structure
+// !!! if this is changed, it must be changed in asm code too !!!
+// FIXME: does the asm code even exist anymore?
+// FIXME: this should move to a different file
+struct cplane_t
+{
+ Vector normal;
+ float dist;
+ byte type; // for fast side tests
+ byte signbits; // signx + (signy<<1) + (signz<<1)
+ byte pad[2];
+
+#ifdef VECTOR_NO_SLOW_OPERATIONS
+ cplane_t() {}
+
+private:
+ // No copy constructors allowed if we're in optimal mode
+ cplane_t(const cplane_t& vOther);
+#endif
+};
+
+// structure offset for asm code
+#define CPLANE_NORMAL_X 0
+#define CPLANE_NORMAL_Y 4
+#define CPLANE_NORMAL_Z 8
+#define CPLANE_DIST 12
+#define CPLANE_TYPE 16
+#define CPLANE_SIGNBITS 17
+#define CPLANE_PAD0 18
+#define CPLANE_PAD1 19
+
+// 0-2 are axial planes
+#define PLANE_X 0
+#define PLANE_Y 1
+#define PLANE_Z 2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define PLANE_ANYX 3
+#define PLANE_ANYY 4
+#define PLANE_ANYZ 5
+
+
+//-----------------------------------------------------------------------------
+// Frustum plane indices.
+// WARNING: there is code that depends on these values
+//-----------------------------------------------------------------------------
+
+enum
+{
+ FRUSTUM_RIGHT = 0,
+ FRUSTUM_LEFT = 1,
+ FRUSTUM_TOP = 2,
+ FRUSTUM_BOTTOM = 3,
+ FRUSTUM_NEARZ = 4,
+ FRUSTUM_FARZ = 5,
+ FRUSTUM_NUMPLANES = 6
+};
+
+extern int SignbitsForPlane( cplane_t *out );
+class Frustum_t;
+
+// Computes Y fov from an X fov and a screen aspect ratio + X from Y
+float CalcFovY( float flFovX, float flScreenAspect );
+float CalcFovX( float flFovY, float flScreenAspect );
+
+// Generate a frustum based on perspective view parameters
+// NOTE: FOV is specified in degrees, as the *full* view angle (not half-angle)
+class VPlane;
+void GeneratePerspectiveFrustum( const Vector& origin, const QAngle &angles, float flZNear, float flZFar, float flFovX, float flAspectRatio, Frustum_t &frustum );
+void GeneratePerspectiveFrustum( const Vector& origin, const Vector &forward, const Vector &right, const Vector &up, float flZNear, float flZFar, float flFovX, float flFovY, VPlane *pPlanesOut );
+// Cull the world-space bounding box to the specified frustum.
+// bool R_CullBox( const Vector& mins, const Vector& maxs, const Frustum_t &frustum );
+// bool R_CullBoxSkipNear( const Vector& mins, const Vector& maxs, const Frustum_t &frustum );
+void GenerateOrthoFrustum( const Vector &origin, const Vector &forward, const Vector &right, const Vector &up, float flLeft, float flRight, float flBottom, float flTop, float flZNear, float flZFar, VPlane *pPlanesOut );
+
+class matrix3x4a_t;
+
+struct matrix3x4_t
+{
+ matrix3x4_t() {}
+ matrix3x4_t(
+ float m00, float m01, float m02, float m03,
+ float m10, float m11, float m12, float m13,
+ float m20, float m21, float m22, float m23 )
+ {
+ m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03;
+ m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13;
+ m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23;
+ }
+
+ //-----------------------------------------------------------------------------
+ // Creates a matrix where the X axis = forward
+ // the Y axis = left, and the Z axis = up
+ //-----------------------------------------------------------------------------
+ void Init( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector &vecOrigin )
+ {
+ m_flMatVal[0][0] = xAxis.x; m_flMatVal[0][1] = yAxis.x; m_flMatVal[0][2] = zAxis.x; m_flMatVal[0][3] = vecOrigin.x;
+ m_flMatVal[1][0] = xAxis.y; m_flMatVal[1][1] = yAxis.y; m_flMatVal[1][2] = zAxis.y; m_flMatVal[1][3] = vecOrigin.y;
+ m_flMatVal[2][0] = xAxis.z; m_flMatVal[2][1] = yAxis.z; m_flMatVal[2][2] = zAxis.z; m_flMatVal[2][3] = vecOrigin.z;
+ }
+
+ //-----------------------------------------------------------------------------
+ // Creates a matrix where the X axis = forward
+ // the Y axis = left, and the Z axis = up
+ //-----------------------------------------------------------------------------
+ matrix3x4_t( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector &vecOrigin )
+ {
+ Init( xAxis, yAxis, zAxis, vecOrigin );
+ }
+
+ inline void SetOrigin( Vector const & p )
+ {
+ m_flMatVal[0][3] = p.x;
+ m_flMatVal[1][3] = p.y;
+ m_flMatVal[2][3] = p.z;
+ }
+
+ inline void Invalidate( void )
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ m_flMatVal[i][j] = VEC_T_NAN;
+ }
+ }
+ }
+
+ float *operator[]( int i ) { Assert(( i >= 0 ) && ( i < 3 )); return m_flMatVal[i]; }
+ const float *operator[]( int i ) const { Assert(( i >= 0 ) && ( i < 3 )); return m_flMatVal[i]; }
+ float *Base() { return &m_flMatVal[0][0]; }
+ const float *Base() const { return &m_flMatVal[0][0]; }
+
+ float m_flMatVal[3][4];
+};
+
+class ALIGN16 matrix3x4a_t : public matrix3x4_t
+{
+public:
+ /*
+ matrix3x4a_t() { if (((size_t)Base()) % 16 != 0) { Error( "matrix3x4a_t missaligned" ); } }
+ */
+ matrix3x4a_t& operator=( const matrix3x4_t& src ) { memcpy( Base(), src.Base(), sizeof( float ) * 3 * 4 ); return *this; };
+} ALIGN16_POST;
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+#endif
+
+#define M_PI_F ((float)(M_PI)) // Shouldn't collide with anything.
+
+// NJS: Inlined to prevent floats from being autopromoted to doubles, as with the old system.
+#ifndef RAD2DEG
+ #define RAD2DEG( x ) ( (float)(x) * (float)(180.f / M_PI_F) )
+#endif
+
+#ifndef DEG2RAD
+ #define DEG2RAD( x ) ( (float)(x) * (float)(M_PI_F / 180.f) )
+#endif
+
+// Used to represent sides of things like planes.
+#define SIDE_FRONT 0
+#define SIDE_BACK 1
+#define SIDE_ON 2
+#define SIDE_CROSS -2 // necessary for polylib.c
+
+// Use different side values (1, 2, 4) instead of (0, 1, 2) so we can '|' and '&' them, and quickly determine overall clipping
+// without having to maintain counters and read / write memory.
+enum Sides
+{
+ OR_SIDE_FRONT = 1,
+ OR_SIDE_BACK = 2,
+ OR_SIDE_ON = 4,
+};
+
+#define ON_VIS_EPSILON 0.01 // necessary for vvis (flow.c) -- again look into moving later!
+#define EQUAL_EPSILON 0.001 // necessary for vbsp (faces.c) -- should look into moving it there?
+
+extern bool s_bMathlibInitialized;
+
+extern const Vector vec3_origin;
+extern const QAngle vec3_angle;
+extern const Quaternion quat_identity;
+extern const Vector vec3_invalid;
+extern const int nanmask;
+
+#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
+
+FORCEINLINE vec_t DotProduct(const vec_t *v1, const vec_t *v2)
+{
+ return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+FORCEINLINE void VectorSubtract(const vec_t *a, const vec_t *b, vec_t *c)
+{
+ c[0]=a[0]-b[0];
+ c[1]=a[1]-b[1];
+ c[2]=a[2]-b[2];
+}
+FORCEINLINE void VectorAdd(const vec_t *a, const vec_t *b, vec_t *c)
+{
+ c[0]=a[0]+b[0];
+ c[1]=a[1]+b[1];
+ c[2]=a[2]+b[2];
+}
+FORCEINLINE void VectorCopy(const vec_t *a, vec_t *b)
+{
+ b[0]=a[0];
+ b[1]=a[1];
+ b[2]=a[2];
+}
+FORCEINLINE void VectorClear(vec_t *a)
+{
+ a[0]=a[1]=a[2]=0;
+}
+
+FORCEINLINE float VectorMaximum(const vec_t *v)
+{
+ return MAX( v[0], MAX( v[1], v[2] ) );
+}
+
+FORCEINLINE float VectorMaximum(const Vector& v)
+{
+ return MAX( v.x, MAX( v.y, v.z ) );
+}
+
+FORCEINLINE void VectorScale (const float* in, vec_t scale, float* out)
+{
+ out[0] = in[0]*scale;
+ out[1] = in[1]*scale;
+ out[2] = in[2]*scale;
+}
+
+
+// Cannot be forceinline as they have overloads:
+inline void VectorFill(vec_t *a, float b)
+{
+ a[0]=a[1]=a[2]=b;
+}
+
+inline void VectorNegate(vec_t *a)
+{
+ a[0]=-a[0];
+ a[1]=-a[1];
+ a[2]=-a[2];
+}
+
+
+//#define VectorMaximum(a) ( max( (a)[0], max( (a)[1], (a)[2] ) ) )
+#define Vector2Clear(x) {(x)[0]=(x)[1]=0;}
+#define Vector2Negate(x) {(x)[0]=-((x)[0]);(x)[1]=-((x)[1]);}
+#define Vector2Copy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];}
+#define Vector2Subtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];}
+#define Vector2Add(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];}
+#define Vector2Scale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];}
+
+// NJS: Some functions in VBSP still need to use these for dealing with mixing vec4's and shorts with vec_t's.
+// remove when no longer needed.
+#define VECTOR_COPY( A, B ) do { (B)[0] = (A)[0]; (B)[1] = (A)[1]; (B)[2]=(A)[2]; } while(0)
+#define DOT_PRODUCT( A, B ) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] + (A)[2]*(B)[2] )
+
+FORCEINLINE void VectorMAInline( const float* start, float scale, const float* direction, float* dest )
+{
+ dest[0]=start[0]+direction[0]*scale;
+ dest[1]=start[1]+direction[1]*scale;
+ dest[2]=start[2]+direction[2]*scale;
+}
+
+FORCEINLINE void VectorMAInline( const Vector& start, float scale, const Vector& direction, Vector& dest )
+{
+ dest.x=start.x+direction.x*scale;
+ dest.y=start.y+direction.y*scale;
+ dest.z=start.z+direction.z*scale;
+}
+
+FORCEINLINE void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest )
+{
+ VectorMAInline(start, scale, direction, dest);
+}
+
+FORCEINLINE void VectorMA( const float * start, float scale, const float *direction, float *dest )
+{
+ VectorMAInline(start, scale, direction, dest);
+}
+
+
+int VectorCompare (const float *v1, const float *v2);
+
+inline float VectorLength(const float *v)
+{
+ return FastSqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + FLT_EPSILON );
+}
+
+void CrossProduct (const float *v1, const float *v2, float *cross);
+
+qboolean VectorsEqual( const float *v1, const float *v2 );
+
+inline vec_t RoundInt (vec_t in)
+{
+ return floor(in + 0.5f);
+}
+
+size_t Q_log2( unsigned int val );
+
+// Math routines done in optimized assembly math package routines
+void inline SinCos( float radians, float * RESTRICT sine, float * RESTRICT cosine )
+{
+#if defined( _X360 )
+ XMScalarSinCos( sine, cosine, radians );
+#elif defined( _PS3 )
+#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 1 ) && ( __GNUC_PATCHLEVEL__ == 1 )
+ vector_float_union s;
+ vector_float_union c;
+
+ vec_float4 rad = vec_splats( radians );
+ vec_float4 sin;
+ vec_float4 cos;
+
+ sincosf4( rad, &sin, &cos );
+
+ vec_st( sin, 0, s.f );
+ vec_st( cos, 0, c.f );
+
+ *sine = s.f[0];
+ *cosine = c.f[0];
+#else //__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 1
+ vector_float_union r;
+ vector_float_union s;
+ vector_float_union c;
+
+ vec_float4 rad;
+ vec_float4 sin;
+ vec_float4 cos;
+
+ r.f[0] = radians;
+ rad = vec_ld( 0, r.f );
+
+ sincosf4( rad, &sin, &cos );
+
+ vec_st( sin, 0, s.f );
+ vec_st( cos, 0, c.f );
+
+ *sine = s.f[0];
+ *cosine = c.f[0];
+#endif //__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ == 1
+#elif defined( COMPILER_MSVC32 )
+ _asm
+ {
+ fld DWORD PTR [radians]
+ fsincos
+
+ mov edx, DWORD PTR [cosine]
+ mov eax, DWORD PTR [sine]
+
+ fstp DWORD PTR [edx]
+ fstp DWORD PTR [eax]
+ }
+#elif defined( GNUC )
+ register double __cosr, __sinr;
+ __asm __volatile__ ("fsincos" : "=t" (__cosr), "=u" (__sinr) : "0" (radians));
+
+ *sine = __sinr;
+ *cosine = __cosr;
+#else
+ *sine = sinf(radians);
+ *cosine = cosf(radians);
+#endif
+}
+
+#define SIN_TABLE_SIZE 256
+#define FTOIBIAS 12582912.f
+extern float SinCosTable[SIN_TABLE_SIZE];
+
+inline float TableCos( float theta )
+{
+ union
+ {
+ int i;
+ float f;
+ } ftmp;
+
+ // ideally, the following should compile down to: theta * constant + constant, changing any of these constants from defines sometimes fubars this.
+ ftmp.f = theta * ( float )( SIN_TABLE_SIZE / ( 2.0f * M_PI ) ) + ( FTOIBIAS + ( SIN_TABLE_SIZE / 4 ) );
+ return SinCosTable[ ftmp.i & ( SIN_TABLE_SIZE - 1 ) ];
+}
+
+inline float TableSin( float theta )
+{
+ union
+ {
+ int i;
+ float f;
+ } ftmp;
+
+ // ideally, the following should compile down to: theta * constant + constant
+ ftmp.f = theta * ( float )( SIN_TABLE_SIZE / ( 2.0f * M_PI ) ) + FTOIBIAS;
+ return SinCosTable[ ftmp.i & ( SIN_TABLE_SIZE - 1 ) ];
+}
+
+template<class T>
+FORCEINLINE T Square( T const &a )
+{
+ return a * a;
+}
+
+FORCEINLINE bool IsPowerOfTwo( uint x )
+{
+ return ( x & ( x - 1 ) ) == 0;
+}
+
+// return the smallest power of two >= x.
+// returns 0 if x == 0 or x > 0x80000000 (ie numbers that would be negative if x was signed)
+// NOTE: the old code took an int, and if you pass in an int of 0x80000000 casted to a uint,
+// you'll get 0x80000000, which is correct for uints, instead of 0, which was correct for ints
+FORCEINLINE uint SmallestPowerOfTwoGreaterOrEqual( uint x )
+{
+ x -= 1;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return x + 1;
+}
+
+// return the largest power of two <= x. Will return 0 if passed 0
+FORCEINLINE uint LargestPowerOfTwoLessThanOrEqual( uint x )
+{
+ if ( x >= 0x80000000 )
+ return 0x80000000;
+
+ return SmallestPowerOfTwoGreaterOrEqual( x + 1 ) >> 1;
+}
+
+
+// Math routines for optimizing division
+void FloorDivMod (double numer, double denom, int *quotient, int *rem);
+int GreatestCommonDivisor (int i1, int i2);
+
+// Test for FPU denormal mode
+bool IsDenormal( const float &val );
+
+// MOVEMENT INFO
+enum
+{
+ PITCH = 0, // up / down
+ YAW, // left / right
+ ROLL // fall over
+};
+
+void MatrixAngles( const matrix3x4_t & matrix, float *angles ); // !!!!
+void MatrixVectors( const matrix3x4_t &matrix, Vector* pForward, Vector *pRight, Vector *pUp );
+void VectorTransform (const float *in1, const matrix3x4_t & in2, float *out);
+void VectorITransform (const float *in1, const matrix3x4_t & in2, float *out);
+void VectorRotate( const float *in1, const matrix3x4_t & in2, float *out);
+void VectorRotate( const Vector &in1, const QAngle &in2, Vector &out );
+void VectorRotate( const Vector &in1, const Quaternion &in2, Vector &out );
+void VectorIRotate( const float *in1, const matrix3x4_t & in2, float *out);
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+QAngle TransformAnglesToLocalSpace( const QAngle &angles, const matrix3x4_t &parentMatrix );
+QAngle TransformAnglesToWorldSpace( const QAngle &angles, const matrix3x4_t &parentMatrix );
+
+#endif
+
+void MatrixInitialize( matrix3x4_t &mat, const Vector &vecOrigin, const Vector &vecXAxis, const Vector &vecYAxis, const Vector &vecZAxis );
+void MatrixCopy( const matrix3x4_t &in, matrix3x4_t &out );
+void MatrixInvert( const matrix3x4_t &in, matrix3x4_t &out );
+
+// Matrix equality test
+bool MatricesAreEqual( const matrix3x4_t &src1, const matrix3x4_t &src2, float flTolerance = 1e-5 );
+
+void MatrixGetColumn( const matrix3x4_t &in, int column, Vector &out );
+void MatrixSetColumn( const Vector &in, int column, matrix3x4_t &out );
+
+//void DecomposeRotation( const matrix3x4_t &mat, float *out );
+void ConcatRotations (const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out);
+void ConcatTransforms (const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out);
+// faster version assumes m0, m1, out are 16-byte aligned addresses
+void ConcatTransforms_Aligned( const matrix3x4a_t &m0, const matrix3x4a_t &m1, matrix3x4a_t &out );
+
+// For identical interface w/ VMatrix
+inline void MatrixMultiply ( const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out )
+{
+ ConcatTransforms( in1, in2, out );
+}
+
+void QuaternionExp( const Quaternion &p, Quaternion &q );
+void QuaternionLn( const Quaternion &p, Quaternion &q );
+void QuaternionAverageExponential( Quaternion &q, int nCount, const Quaternion *pQuaternions, const float *pflWeights = NULL );
+void QuaternionLookAt( const Vector &vecForward, const Vector &referenceUp, Quaternion &q );
+void QuaternionSlerp( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
+void QuaternionSlerpNoAlign( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
+void QuaternionBlend( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
+void QuaternionBlendNoAlign( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt );
+void QuaternionIdentityBlend( const Quaternion &p, float t, Quaternion &qt );
+float QuaternionAngleDiff( const Quaternion &p, const Quaternion &q );
+void QuaternionScale( const Quaternion &p, float t, Quaternion &q );
+void QuaternionAlign( const Quaternion &p, const Quaternion &q, Quaternion &qt );
+float QuaternionDotProduct( const Quaternion &p, const Quaternion &q );
+void QuaternionConjugate( const Quaternion &p, Quaternion &q );
+void QuaternionInvert( const Quaternion &p, Quaternion &q );
+float QuaternionNormalize( Quaternion &q );
+void QuaternionAdd( const Quaternion &p, const Quaternion &q, Quaternion &qt );
+void QuaternionMult( const Quaternion &p, const Quaternion &q, Quaternion &qt );
+void QuaternionMatrix( const Quaternion &q, matrix3x4_t &matrix );
+void QuaternionMatrix( const Quaternion &q, const Vector &pos, matrix3x4_t &matrix );
+void QuaternionAngles( const Quaternion &q, QAngle &angles );
+void AngleQuaternion( const QAngle& angles, Quaternion &qt );
+void QuaternionAngles( const Quaternion &q, RadianEuler &angles );
+void AngleQuaternion( RadianEuler const &angles, Quaternion &qt );
+void QuaternionAxisAngle( const Quaternion &q, Vector &axis, float &angle );
+void AxisAngleQuaternion( const Vector &axis, float angle, Quaternion &q );
+void BasisToQuaternion( const Vector &vecForward, const Vector &vecRight, const Vector &vecUp, Quaternion &q );
+void MatrixQuaternion( const matrix3x4_t &mat, Quaternion &q );
+
+// A couple methods to find the dot product of a vector with a matrix row or column...
+inline float MatrixRowDotProduct( const matrix3x4_t &in1, int row, const Vector& in2 )
+{
+ Assert( (row >= 0) && (row < 3) );
+ return DotProduct( in1[row], in2.Base() );
+}
+
+inline float MatrixColumnDotProduct( const matrix3x4_t &in1, int col, const Vector& in2 )
+{
+ Assert( (col >= 0) && (col < 4) );
+ return in1[0][col] * in2[0] + in1[1][col] * in2[1] + in1[2][col] * in2[2];
+}
+
+int __cdecl BoxOnPlaneSide (const float *emins, const float *emaxs, const cplane_t *plane);
+
+inline float anglemod(float a)
+{
+ a = (360.f/65536) * ((int)(a*(65536.f/360.0f)) & 65535);
+ return a;
+}
+
+//// CLAMP
+#if defined(__cplusplus) && defined(PLATFORM_PPC)
+
+#ifdef _X360
+#define __fsels __fsel
+#endif
+
+template< >
+inline double clamp( double const &val, double const &minVal, double const &maxVal )
+{
+ float diffmin = val - minVal;
+ float diffmax = maxVal - val;
+ float r;
+ r = __fsel(diffmin, val, minVal);
+ r = __fsel(diffmax, r, maxVal);
+ return r;
+}
+
+template< >
+inline double clamp( double const &val, float const &minVal, float const &maxVal )
+{
+ // these typecasts are actually free since all FPU regs are 64 bit on PPC anyway
+ return clamp ( val, (double) minVal, (double) maxVal );
+}
+template< >
+inline double clamp( double const &val, float const &minVal, double const &maxVal )
+{
+ return clamp ( val, (double) minVal, (double) maxVal );
+}
+template< >
+inline double clamp( double const &val, double const &minVal, float const &maxVal )
+{
+ return clamp ( val, (double) minVal, (double) maxVal );
+}
+
+template< >
+inline float clamp( float const &val, float const &minVal, float const &maxVal )
+{
+ float diffmin = val - minVal;
+ float diffmax = maxVal - val;
+ float r;
+ r = __fsels(diffmin, val, minVal);
+ r = __fsels(diffmax, r, maxVal);
+ return r;
+}
+
+template< >
+inline float clamp( float const &val, double const &minVal, double const &maxVal )
+{
+ float diffmin = val - minVal;
+ float diffmax = maxVal - val;
+ float r;
+ r = __fsels(diffmin, val, minVal);
+ r = __fsels(diffmax, r, maxVal);
+ return r;
+}
+template< >
+inline float clamp( float const &val, double const &minVal, float const &maxVal )
+{
+ return clamp ( val, (float) minVal, maxVal );
+}
+template< >
+inline float clamp( float const &val, float const &minVal, double const &maxVal )
+{
+ return clamp ( val, minVal, (float) maxVal );
+}
+
+#endif
+
+// Remap a value in the range [A,B] to [C,D].
+inline float RemapVal( float val, float A, float B, float C, float D)
+{
+ if ( A == B )
+ return fsel( val - B , D , C );
+ return C + (D - C) * (val - A) / (B - A);
+}
+
+inline float RemapValClamped( float val, float A, float B, float C, float D)
+{
+ if ( A == B )
+ return fsel( val - B , D , C );
+ float cVal = (val - A) / (B - A);
+ cVal = clamp<float>( cVal, 0.0f, 1.0f );
+
+ return C + (D - C) * cVal;
+}
+
+// Returns A + (B-A)*flPercent.
+// float Lerp( float flPercent, float A, float B );
+template <class T>
+FORCEINLINE T Lerp( float flPercent, T const &A, T const &B )
+{
+ return A + (B - A) * flPercent;
+}
+
+FORCEINLINE float Sqr( float f )
+{
+ return f*f;
+}
+
+// 5-argument floating point linear interpolation.
+// FLerp(f1,f2,i1,i2,x)=
+// f1 at x=i1
+// f2 at x=i2
+// smooth lerp between f1 and f2 at x>i1 and x<i2
+// extrapolation for x<i1 or x>i2
+//
+// If you know a function f(x)'s value (f1) at position i1, and its value (f2) at position i2,
+// the function can be linearly interpolated with FLerp(f1,f2,i1,i2,x)
+// i2=i1 will cause a divide by zero.
+static inline float FLerp(float f1, float f2, float i1, float i2, float x)
+{
+ return f1+(f2-f1)*(x-i1)/(i2-i1);
+}
+
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+// YWB: Specialization for interpolating euler angles via quaternions...
+template<> FORCEINLINE QAngle Lerp<QAngle>( float flPercent, const QAngle& q1, const QAngle& q2 )
+{
+ // Avoid precision errors
+ if ( q1 == q2 )
+ return q1;
+
+ Quaternion src, dest;
+
+ // Convert to quaternions
+ AngleQuaternion( q1, src );
+ AngleQuaternion( q2, dest );
+
+ Quaternion result;
+
+ // Slerp
+ QuaternionSlerp( src, dest, flPercent, result );
+
+ // Convert to euler
+ QAngle output;
+ QuaternionAngles( result, output );
+ return output;
+}
+
+#else
+
+#pragma error
+
+// NOTE NOTE: I haven't tested this!! It may not work! Check out interpolatedvar.cpp in the client dll to try it
+template<> FORCEINLINE QAngleByValue Lerp<QAngleByValue>( float flPercent, const QAngleByValue& q1, const QAngleByValue& q2 )
+{
+ // Avoid precision errors
+ if ( q1 == q2 )
+ return q1;
+
+ Quaternion src, dest;
+
+ // Convert to quaternions
+ AngleQuaternion( q1, src );
+ AngleQuaternion( q2, dest );
+
+ Quaternion result;
+
+ // Slerp
+ QuaternionSlerp( src, dest, flPercent, result );
+
+ // Convert to euler
+ QAngleByValue output;
+ QuaternionAngles( result, output );
+ return output;
+}
+
+#endif // VECTOR_NO_SLOW_OPERATIONS
+
+
+// Swap two of anything.
+template <class T>
+FORCEINLINE void V_swap( T& x, T& y )
+{
+ T temp = x;
+ x = y;
+ y = temp;
+}
+
+template <class T> FORCEINLINE T AVG(T a, T b)
+{
+ return (a+b)/2;
+}
+
+// number of elements in an array of static size
+#define NELEMS(x) ((sizeof(x))/sizeof(x[0]))
+
+// XYZ macro, for printf type functions - ex printf("%f %f %f",XYZ(myvector));
+#define XYZ(v) (v).x,(v).y,(v).z
+
+
+
+
+inline float Sign( float x )
+{
+ return fsel( x, 1.0f, -1.0f ); // x >= 0 ? 1.0f : -1.0f
+ //return (x <0.0f) ? -1.0f : 1.0f;
+}
+
+//
+// Clamps the input integer to the given array bounds.
+// Equivalent to the following, but without using any branches:
+//
+// if( n < 0 ) return 0;
+// else if ( n > maxindex ) return maxindex;
+// else return n;
+//
+// This is not always a clear performance win, but when you have situations where a clamped
+// value is thrashing against a boundary this is a big win. (ie, valid, invalid, valid, invalid, ...)
+//
+// Note: This code has been run against all possible integers.
+//
+inline int ClampArrayBounds( int n, unsigned maxindex )
+{
+ // mask is 0 if less than 4096, 0xFFFFFFFF if greater than
+ unsigned int inrangemask = 0xFFFFFFFF + (((unsigned) n) > maxindex );
+ unsigned int lessthan0mask = 0xFFFFFFFF + ( n >= 0 );
+
+ // If the result was valid, set the result, (otherwise sets zero)
+ int result = (inrangemask & n);
+
+ // if the result was out of range or zero.
+ result |= ((~inrangemask) & (~lessthan0mask)) & maxindex;
+
+ return result;
+}
+
+
+
+// Turn a number "inside out".
+// See Recording Animation in Binary Order for Progressive Temporal Refinement
+// by Paul Heckbert from "Graphics Gems".
+//
+// If you want to iterate something from 0 to n, you can use this to iterate non-sequentially, in
+// such a way that you will start with widely separated values and then refine the gaps between
+// them, as you would for progressive refinement. This works with non-power of two ranges.
+int InsideOut( int nTotal, int nCounter );
+
+#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
+ (((p)->type < 3)? \
+ ( \
+ ((p)->dist <= (emins)[(p)->type])? \
+ 1 \
+ : \
+ ( \
+ ((p)->dist >= (emaxs)[(p)->type])?\
+ 2 \
+ : \
+ 3 \
+ ) \
+ ) \
+ : \
+ BoxOnPlaneSide( (emins), (emaxs), (p)))
+
+//-----------------------------------------------------------------------------
+// FIXME: Vector versions.... the float versions will go away hopefully soon!
+//-----------------------------------------------------------------------------
+
+void AngleVectors (const QAngle& angles, Vector *forward);
+void AngleVectors (const QAngle& angles, Vector *forward, Vector *right, Vector *up);
+void AngleVectorsTranspose (const QAngle& angles, Vector *forward, Vector *right, Vector *up);
+void AngleMatrix (const QAngle &angles, matrix3x4_t &mat );
+void AngleMatrix( const QAngle &angles, const Vector &position, matrix3x4_t &mat );
+void AngleMatrix (const RadianEuler &angles, matrix3x4_t &mat );
+void AngleMatrix( RadianEuler const &angles, const Vector &position, matrix3x4_t &mat );
+void AngleIMatrix (const QAngle &angles, matrix3x4_t &mat );
+void AngleIMatrix (const QAngle &angles, const Vector &position, matrix3x4_t &mat );
+void AngleIMatrix (const RadianEuler &angles, matrix3x4_t &mat );
+void VectorAngles( const Vector &forward, QAngle &angles );
+void VectorAngles( const Vector &forward, const Vector &pseudoup, QAngle &angles );
+void VectorMatrix( const Vector &forward, matrix3x4_t &mat );
+void VectorVectors( const Vector &forward, Vector &right, Vector &up );
+void SetIdentityMatrix( matrix3x4_t &mat );
+void SetScaleMatrix( float x, float y, float z, matrix3x4_t &dst );
+void MatrixBuildRotationAboutAxis( const Vector &vAxisOfRot, float angleDegrees, matrix3x4_t &dst );
+
+inline bool MatrixIsIdentity( const matrix3x4_t &m )
+{
+ return
+ m.m_flMatVal[0][0] == 1.0f && m.m_flMatVal[0][1] == 0.0f && m.m_flMatVal[0][2] == 0.0f && m.m_flMatVal[0][3] == 0.0f &&
+ m.m_flMatVal[1][0] == 0.0f && m.m_flMatVal[1][1] == 1.0f && m.m_flMatVal[1][2] == 0.0f && m.m_flMatVal[1][3] == 0.0f &&
+ m.m_flMatVal[2][0] == 0.0f && m.m_flMatVal[2][1] == 0.0f && m.m_flMatVal[2][2] == 1.0f && m.m_flMatVal[2][3] == 0.0f;
+}
+
+
+inline void SetScaleMatrix( float flScale, matrix3x4_t &dst )
+{
+ SetScaleMatrix( flScale, flScale, flScale, dst );
+}
+
+inline void SetScaleMatrix( const Vector& scale, matrix3x4_t &dst )
+{
+ SetScaleMatrix( scale.x, scale.y, scale.z, dst );
+}
+
+// Computes the inverse transpose
+void MatrixTranspose( matrix3x4_t& mat );
+void MatrixTranspose( const matrix3x4_t& src, matrix3x4_t& dst );
+void MatrixInverseTranspose( const matrix3x4_t& src, matrix3x4_t& dst );
+
+inline void PositionMatrix( const Vector &position, matrix3x4_t &mat )
+{
+ MatrixSetColumn( position, 3, mat );
+}
+
+inline void MatrixPosition( const matrix3x4_t &matrix, Vector &position )
+{
+ position[0] = matrix[0][3];
+ position[1] = matrix[1][3];
+ position[2] = matrix[2][3];
+}
+
+inline void VectorRotate( const Vector& in1, const matrix3x4_t &in2, Vector &out)
+{
+ VectorRotate( &in1.x, in2, &out.x );
+}
+
+inline void VectorIRotate( const Vector& in1, const matrix3x4_t &in2, Vector &out)
+{
+ VectorIRotate( &in1.x, in2, &out.x );
+}
+
+inline void MatrixAngles( const matrix3x4_t &matrix, QAngle &angles )
+{
+ MatrixAngles( matrix, &angles.x );
+}
+
+inline void MatrixAngles( const matrix3x4_t &matrix, QAngle &angles, Vector &position )
+{
+ MatrixAngles( matrix, angles );
+ MatrixPosition( matrix, position );
+}
+
+inline void MatrixAngles( const matrix3x4_t &matrix, RadianEuler &angles )
+{
+ MatrixAngles( matrix, &angles.x );
+
+ angles.Init( DEG2RAD( angles.z ), DEG2RAD( angles.x ), DEG2RAD( angles.y ) );
+}
+
+void MatrixAngles( const matrix3x4_t &mat, RadianEuler &angles, Vector &position );
+
+void MatrixAngles( const matrix3x4_t &mat, Quaternion &q, Vector &position );
+
+inline int VectorCompare (const Vector& v1, const Vector& v2)
+{
+ return v1 == v2;
+}
+
+inline void VectorTransform (const Vector& in1, const matrix3x4_t &in2, Vector &out)
+{
+ VectorTransform( &in1.x, in2, &out.x );
+}
+
+inline void VectorITransform (const Vector& in1, const matrix3x4_t &in2, Vector &out)
+{
+ VectorITransform( &in1.x, in2, &out.x );
+}
+
+/*
+inline void DecomposeRotation( const matrix3x4_t &mat, Vector &out )
+{
+ DecomposeRotation( mat, &out.x );
+}
+*/
+
+inline int BoxOnPlaneSide (const Vector& emins, const Vector& emaxs, const cplane_t *plane )
+{
+ return BoxOnPlaneSide( &emins.x, &emaxs.x, plane );
+}
+
+inline void VectorFill(Vector& a, float b)
+{
+ a[0]=a[1]=a[2]=b;
+}
+
+inline void VectorNegate(Vector& a)
+{
+ a[0] = -a[0];
+ a[1] = -a[1];
+ a[2] = -a[2];
+}
+
+inline vec_t VectorAvg(Vector& a)
+{
+ return ( a[0] + a[1] + a[2] ) / 3;
+}
+
+//-----------------------------------------------------------------------------
+// Box/plane test (slow version)
+//-----------------------------------------------------------------------------
+inline int FASTCALL BoxOnPlaneSide2 (const Vector& emins, const Vector& emaxs, const cplane_t *p, float tolerance = 0.f )
+{
+ Vector corners[2];
+
+ if (p->normal[0] < 0)
+ {
+ corners[0][0] = emins[0];
+ corners[1][0] = emaxs[0];
+ }
+ else
+ {
+ corners[1][0] = emins[0];
+ corners[0][0] = emaxs[0];
+ }
+
+ if (p->normal[1] < 0)
+ {
+ corners[0][1] = emins[1];
+ corners[1][1] = emaxs[1];
+ }
+ else
+ {
+ corners[1][1] = emins[1];
+ corners[0][1] = emaxs[1];
+ }
+
+ if (p->normal[2] < 0)
+ {
+ corners[0][2] = emins[2];
+ corners[1][2] = emaxs[2];
+ }
+ else
+ {
+ corners[1][2] = emins[2];
+ corners[0][2] = emaxs[2];
+ }
+
+ int sides = 0;
+
+ float dist1 = DotProduct (p->normal, corners[0]) - p->dist;
+ if (dist1 >= tolerance)
+ sides = 1;
+
+ float dist2 = DotProduct (p->normal, corners[1]) - p->dist;
+ if (dist2 < -tolerance)
+ sides |= 2;
+
+ return sides;
+}
+
+//-----------------------------------------------------------------------------
+// Helpers for bounding box construction
+//-----------------------------------------------------------------------------
+
+void ClearBounds (Vector& mins, Vector& maxs);
+void AddPointToBounds (const Vector& v, Vector& mins, Vector& maxs);
+
+//-----------------------------------------------------------------------------
+// Ensures that the min and max bounds values are valid.
+// (ClearBounds() sets min > max, which is clearly invalid.)
+//-----------------------------------------------------------------------------
+bool AreBoundsValid( const Vector &vMin, const Vector &vMax );
+
+//-----------------------------------------------------------------------------
+// Returns true if the provided point is in the AABB defined by vMin
+// at the lower corner and vMax at the upper corner.
+//-----------------------------------------------------------------------------
+bool IsPointInBounds( const Vector &vPoint, const Vector &vMin, const Vector &vMax );
+
+//
+// COLORSPACE/GAMMA CONVERSION STUFF
+//
+void BuildGammaTable( float gamma, float texGamma, float brightness, int overbright );
+
+// convert texture to linear 0..1 value
+inline float TexLightToLinear( int c, int exponent )
+{
+ extern float power2_n[256];
+ Assert( exponent >= -128 && exponent <= 127 );
+ return ( float )c * power2_n[exponent+128];
+}
+
+
+// convert texture to linear 0..1 value
+int LinearToTexture( float f );
+// converts 0..1 linear value to screen gamma (0..255)
+int LinearToScreenGamma( float f );
+float TextureToLinear( int c );
+
+// compressed color format
+struct ColorRGBExp32
+{
+ byte r, g, b;
+ signed char exponent;
+};
+
+void ColorRGBExp32ToVector( const ColorRGBExp32& in, Vector& out );
+void VectorToColorRGBExp32( const Vector& v, ColorRGBExp32 &c );
+
+// solve for "x" where "a x^2 + b x + c = 0", return true if solution exists
+bool SolveQuadratic( float a, float b, float c, float &root1, float &root2 );
+
+// solves for "a, b, c" where "a x^2 + b x + c = y", return true if solution exists
+bool SolveInverseQuadratic( float x1, float y1, float x2, float y2, float x3, float y3, float &a, float &b, float &c );
+
+// solves for a,b,c specified as above, except that it always creates a monotonically increasing or
+// decreasing curve if the data is monotonically increasing or decreasing. In order to enforce the
+// monoticity condition, it is possible that the resulting quadratic will only approximate the data
+// instead of interpolating it. This code is not especially fast.
+bool SolveInverseQuadraticMonotonic( float x1, float y1, float x2, float y2,
+ float x3, float y3, float &a, float &b, float &c );
+
+
+
+
+// solves for "a, b, c" where "1/(a x^2 + b x + c ) = y", return true if solution exists
+bool SolveInverseReciprocalQuadratic( float x1, float y1, float x2, float y2, float x3, float y3, float &a, float &b, float &c );
+
+// rotate a vector around the Z axis (YAW)
+void VectorYawRotate( const Vector& in, float flYaw, Vector &out);
+
+
+// Bias takes an X value between 0 and 1 and returns another value between 0 and 1
+// The curve is biased towards 0 or 1 based on biasAmt, which is between 0 and 1.
+// Lower values of biasAmt bias the curve towards 0 and higher values bias it towards 1.
+//
+// For example, with biasAmt = 0.2, the curve looks like this:
+//
+// 1
+// | *
+// | *
+// | *
+// | **
+// | **
+// | ****
+// |*********
+// |___________________
+// 0 1
+//
+//
+// With biasAmt = 0.8, the curve looks like this:
+//
+// 1
+// | **************
+// | **
+// | *
+// | *
+// |*
+// |*
+// |*
+// |___________________
+// 0 1
+//
+// With a biasAmt of 0.5, Bias returns X.
+float Bias( float x, float biasAmt );
+
+
+// Gain is similar to Bias, but biasAmt biases towards or away from 0.5.
+// Lower bias values bias towards 0.5 and higher bias values bias away from it.
+//
+// For example, with biasAmt = 0.2, the curve looks like this:
+//
+// 1
+// | *
+// | *
+// | **
+// | ***************
+// | **
+// | *
+// |*
+// |___________________
+// 0 1
+//
+//
+// With biasAmt = 0.8, the curve looks like this:
+//
+// 1
+// | *****
+// | ***
+// | *
+// | *
+// | *
+// | ***
+// |*****
+// |___________________
+// 0 1
+float Gain( float x, float biasAmt );
+
+
+// SmoothCurve maps a 0-1 value into another 0-1 value based on a cosine wave
+// where the derivatives of the function at 0 and 1 (and 0.5) are 0. This is useful for
+// any fadein/fadeout effect where it should start and end smoothly.
+//
+// The curve looks like this:
+//
+// 1
+// | **
+// | * *
+// | * *
+// | * *
+// | * *
+// | ** **
+// |*** ***
+// |___________________
+// 0 1
+//
+float SmoothCurve( float x );
+
+
+// This works like SmoothCurve, with two changes:
+//
+// 1. Instead of the curve peaking at 0.5, it will peak at flPeakPos.
+// (So if you specify flPeakPos=0.2, then the peak will slide to the left).
+//
+// 2. flPeakSharpness is a 0-1 value controlling the sharpness of the peak.
+// Low values blunt the peak and high values sharpen the peak.
+float SmoothCurve_Tweak( float x, float flPeakPos=0.5, float flPeakSharpness=0.5 );
+
+
+//float ExponentialDecay( float halflife, float dt );
+//float ExponentialDecay( float decayTo, float decayTime, float dt );
+
+// halflife is time for value to reach 50%
+inline float ExponentialDecay( float halflife, float dt )
+{
+ // log(0.5) == -0.69314718055994530941723212145818
+ return expf( -0.69314718f / halflife * dt);
+}
+
+// decayTo is factor the value should decay to in decayTime
+inline float ExponentialDecay( float decayTo, float decayTime, float dt )
+{
+ return expf( logf( decayTo ) / decayTime * dt);
+}
+
+// Get the integrated distanced traveled
+// decayTo is factor the value should decay to in decayTime
+// dt is the time relative to the last velocity update
+inline float ExponentialDecayIntegral( float decayTo, float decayTime, float dt )
+{
+ return (powf( decayTo, dt / decayTime) * decayTime - decayTime) / logf( decayTo );
+}
+
+// hermite basis function for smooth interpolation
+// Similar to Gain() above, but very cheap to call
+// value should be between 0 & 1 inclusive
+inline float SimpleSpline( float value )
+{
+ float valueSquared = value * value;
+
+ // Nice little ease-in, ease-out spline-like curve
+ return (3 * valueSquared - 2 * valueSquared * value);
+}
+
+// remaps a value in [startInterval, startInterval+rangeInterval] from linear to
+// spline using SimpleSpline
+inline float SimpleSplineRemapVal( float val, float A, float B, float C, float D)
+{
+ if ( A == B )
+ return val >= B ? D : C;
+ float cVal = (val - A) / (B - A);
+ return C + (D - C) * SimpleSpline( cVal );
+}
+
+// remaps a value in [startInterval, startInterval+rangeInterval] from linear to
+// spline using SimpleSpline
+inline float SimpleSplineRemapValClamped( float val, float A, float B, float C, float D )
+{
+ if ( A == B )
+ return val >= B ? D : C;
+ float cVal = (val - A) / (B - A);
+ cVal = clamp( cVal, 0.0f, 1.0f );
+ return C + (D - C) * SimpleSpline( cVal );
+}
+
+FORCEINLINE int RoundFloatToInt(float f)
+{
+#if defined( _X360 )
+#ifdef Assert
+ Assert( IsFPUControlWordSet() );
+#endif
+ union
+ {
+ double flResult;
+ int pResult[2];
+ };
+ flResult = __fctiw( f );
+ return pResult[1];
+#elif defined ( _PS3 )
+ return __fctiw( f );
+#else // !X360
+ int nResult;
+#if defined( COMPILER_MSVC32 )
+ __asm
+ {
+ fld f
+ fistp nResult
+ }
+#elif GNUC
+ __asm __volatile__ (
+ "fistpl %0;": "=m" (nResult): "t" (f) : "st"
+ );
+#else
+ nResult = static_cast<int>(f);
+#endif
+ return nResult;
+#endif
+}
+
+FORCEINLINE unsigned char RoundFloatToByte(float f)
+{
+#if defined( _X360 )
+#ifdef Assert
+ Assert( IsFPUControlWordSet() );
+#endif
+ union
+ {
+ double flResult;
+ int pIntResult[2];
+ unsigned char pResult[8];
+ };
+ flResult = __fctiw( f );
+#ifdef Assert
+ Assert( pIntResult[1] >= 0 && pIntResult[1] <= 255 );
+#endif
+ return pResult[7];
+
+#elif defined ( _PS3 )
+ return __fctiw( f );
+#else // !X360
+
+ int nResult;
+
+#if defined( COMPILER_MSVC32 )
+ __asm
+ {
+ fld f
+ fistp nResult
+ }
+#elif GNUC
+ __asm __volatile__ (
+ "fistpl %0;": "=m" (nResult): "t" (f) : "st"
+ );
+#else
+ nResult = static_cast<unsigned int> (f) & 0xff;
+#endif
+
+#ifdef Assert
+ Assert( nResult >= 0 && nResult <= 255 );
+#endif
+ return nResult;
+
+#endif
+}
+
+FORCEINLINE unsigned long RoundFloatToUnsignedLong(float f)
+{
+#if defined( _X360 )
+#ifdef Assert
+ Assert( IsFPUControlWordSet() );
+#endif
+ union
+ {
+ double flResult;
+ int pIntResult[2];
+ unsigned long pResult[2];
+ };
+ flResult = __fctiw( f );
+ Assert( pIntResult[1] >= 0 );
+ return pResult[1];
+#elif defined ( _PS3 )
+ return __fctiw( f );
+#else // !X360
+
+#if defined( COMPILER_MSVC32 )
+ unsigned char nResult[8];
+ __asm
+ {
+ fld f
+ fistp qword ptr nResult
+ }
+ return *((unsigned long*)nResult);
+#elif defined( COMPILER_GCC )
+ unsigned char nResult[8];
+ __asm __volatile__ (
+ "fistpl %0;": "=m" (nResult): "t" (f) : "st"
+ );
+ return *((unsigned long*)nResult);
+#else
+ return static_cast<unsigned long>(f);
+#endif
+
+#endif
+}
+
+FORCEINLINE bool IsIntegralValue( float flValue, float flTolerance = 0.001f )
+{
+ return fabs( RoundFloatToInt( flValue ) - flValue ) < flTolerance;
+}
+
+// Fast, accurate ftol:
+FORCEINLINE int Float2Int( float a )
+{
+#if defined( _X360 )
+ union
+ {
+ double flResult;
+ int pResult[2];
+ };
+ flResult = __fctiwz( a );
+ return pResult[1];
+#elif defined ( _PS3 )
+ return __fctiwz( a );
+#else // !X360
+
+ int RetVal;
+
+#if defined( COMPILER_MSVC32 )
+ int CtrlwdHolder;
+ int CtrlwdSetter;
+ __asm
+ {
+ fld a // push 'a' onto the FP stack
+ fnstcw CtrlwdHolder // store FPU control word
+ movzx eax, CtrlwdHolder // move and zero extend word into eax
+ and eax, 0xFFFFF3FF // set all bits except rounding bits to 1
+ or eax, 0x00000C00 // set rounding mode bits to round towards zero
+ mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid!
+ fldcw CtrlwdSetter // Entering plaid!
+ fistp RetVal // Store and converted (to int) result
+ fldcw CtrlwdHolder // Restore control word
+ }
+#else
+ RetVal = static_cast<int>( a );
+#endif
+
+ return RetVal;
+#endif
+}
+
+// Over 15x faster than: (int)floor(value)
+inline int Floor2Int( float a )
+{
+ int RetVal;
+
+#if defined( PLATFORM_PPC )
+ RetVal = (int)floor( a );
+#elif defined( COMPILER_MSVC32 )
+ int CtrlwdHolder;
+ int CtrlwdSetter;
+ __asm
+ {
+ fld a // push 'a' onto the FP stack
+ fnstcw CtrlwdHolder // store FPU control word
+ movzx eax, CtrlwdHolder // move and zero extend word into eax
+ and eax, 0xFFFFF3FF // set all bits except rounding bits to 1
+ or eax, 0x00000400 // set rounding mode bits to round down
+ mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid!
+ fldcw CtrlwdSetter // Entering plaid!
+ fistp RetVal // Store floored and converted (to int) result
+ fldcw CtrlwdHolder // Restore control word
+ }
+#else
+ RetVal = static_cast<int>( floor(a) );
+#endif
+
+ return RetVal;
+}
+
+//-----------------------------------------------------------------------------
+// Fast color conversion from float to unsigned char
+//-----------------------------------------------------------------------------
+FORCEINLINE unsigned char FastFToC( float c )
+{
+ volatile float dc;
+
+ // ieee trick
+ dc = c * 255.0f + (float)(1 << 23);
+
+ // return the lsb
+#if defined( _X360 ) || defined( _PS3 )
+ return ((unsigned char*)&dc)[3];
+#else
+ return *(unsigned char*)&dc;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Bound input float to .001 (millisecond) boundary
+// Input : in -
+// Output : inline float
+//-----------------------------------------------------------------------------
+inline float ClampToMsec( float in )
+{
+ int msec = Floor2Int( in * 1000.0f + 0.5f );
+ return msec / 1000.0f;
+}
+
+// Over 15x faster than: (int)ceil(value)
+inline int Ceil2Int( float a )
+{
+ int RetVal;
+
+#if defined( PLATFORM_PPC )
+ RetVal = (int)ceil( a );
+#elif defined( COMPILER_MSVC32 )
+ int CtrlwdHolder;
+ int CtrlwdSetter;
+ __asm
+ {
+ fld a // push 'a' onto the FP stack
+ fnstcw CtrlwdHolder // store FPU control word
+ movzx eax, CtrlwdHolder // move and zero extend word into eax
+ and eax, 0xFFFFF3FF // set all bits except rounding bits to 1
+ or eax, 0x00000800 // set rounding mode bits to round down
+ mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid!
+ fldcw CtrlwdSetter // Entering plaid!
+ fistp RetVal // Store floored and converted (to int) result
+ fldcw CtrlwdHolder // Restore control word
+ }
+#else
+ RetVal = static_cast<int>( ceil(a) );
+#endif
+
+ return RetVal;
+}
+
+
+// Regular signed area of triangle
+#define TriArea2D( A, B, C ) \
+ ( 0.5f * ( ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ) ) )
+
+// This version doesn't premultiply by 0.5f, so it's the area of the rectangle instead
+#define TriArea2DTimesTwo( A, B, C ) \
+ ( ( ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ) ) )
+
+
+// Get the barycentric coordinates of "pt" in triangle [A,B,C].
+inline void GetBarycentricCoords2D(
+ Vector2D const &A,
+ Vector2D const &B,
+ Vector2D const &C,
+ Vector2D const &pt,
+ float bcCoords[3] )
+{
+ // Note, because to top and bottom are both x2, the issue washes out in the composite
+ float invTriArea = 1.0f / TriArea2DTimesTwo( A, B, C );
+
+ // NOTE: We assume here that the lightmap coordinate vertices go counterclockwise.
+ // If not, TriArea2D() is negated so this works out right.
+ bcCoords[0] = TriArea2DTimesTwo( B, C, pt ) * invTriArea;
+ bcCoords[1] = TriArea2DTimesTwo( C, A, pt ) * invTriArea;
+ bcCoords[2] = TriArea2DTimesTwo( A, B, pt ) * invTriArea;
+}
+
+
+// Return true of the sphere might touch the box (the sphere is actually treated
+// like a box itself, so this may return true if the sphere's bounding box touches
+// a corner of the box but the sphere itself doesn't).
+inline bool QuickBoxSphereTest(
+ const Vector& vOrigin,
+ float flRadius,
+ const Vector& bbMin,
+ const Vector& bbMax )
+{
+ return vOrigin.x - flRadius < bbMax.x && vOrigin.x + flRadius > bbMin.x &&
+ vOrigin.y - flRadius < bbMax.y && vOrigin.y + flRadius > bbMin.y &&
+ vOrigin.z - flRadius < bbMax.z && vOrigin.z + flRadius > bbMin.z;
+}
+
+
+// Return true of the boxes intersect (but not if they just touch).
+inline bool QuickBoxIntersectTest(
+ const Vector& vBox1Min,
+ const Vector& vBox1Max,
+ const Vector& vBox2Min,
+ const Vector& vBox2Max )
+{
+ return
+ vBox1Min.x < vBox2Max.x && vBox1Max.x > vBox2Min.x &&
+ vBox1Min.y < vBox2Max.y && vBox1Max.y > vBox2Min.y &&
+ vBox1Min.z < vBox2Max.z && vBox1Max.z > vBox2Min.z;
+}
+
+
+extern float GammaToLinearFullRange( float gamma );
+extern float LinearToGammaFullRange( float linear );
+extern float GammaToLinear( float gamma );
+extern float LinearToGamma( float linear );
+
+extern float SrgbGammaToLinear( float flSrgbGammaValue );
+extern float SrgbLinearToGamma( float flLinearValue );
+extern float X360GammaToLinear( float fl360GammaValue );
+extern float X360LinearToGamma( float flLinearValue );
+extern float SrgbGammaTo360Gamma( float flSrgbGammaValue );
+
+// linear (0..4) to screen corrected vertex space (0..1?)
+FORCEINLINE float LinearToVertexLight( float f )
+{
+ extern float lineartovertex[4096];
+
+ // Gotta clamp before the multiply; could overflow...
+ // assume 0..4 range
+ int i = RoundFloatToInt( f * 1024.f );
+
+ // Presumably the comman case will be not to clamp, so check that first:
+ if( (unsigned)i > 4095 )
+ {
+ if ( i < 0 )
+ i = 0; // Compare to zero instead of 4095 to save 4 bytes in the instruction stream
+ else
+ i = 4095;
+ }
+
+ return lineartovertex[i];
+}
+
+
+FORCEINLINE unsigned char LinearToLightmap( float f )
+{
+ extern unsigned char lineartolightmap[4096];
+
+ // Gotta clamp before the multiply; could overflow...
+ int i = RoundFloatToInt( f * 1024.f ); // assume 0..4 range
+
+ // Presumably the comman case will be not to clamp, so check that first:
+ if ( (unsigned)i > 4095 )
+ {
+ if ( i < 0 )
+ i = 0; // Compare to zero instead of 4095 to save 4 bytes in the instruction stream
+ else
+ i = 4095;
+ }
+
+ return lineartolightmap[i];
+}
+
+FORCEINLINE void ColorClamp( Vector& color )
+{
+ float maxc = MAX( color.x, MAX( color.y, color.z ) );
+ if ( maxc > 1.0f )
+ {
+ float ooMax = 1.0f / maxc;
+ color.x *= ooMax;
+ color.y *= ooMax;
+ color.z *= ooMax;
+ }
+
+ if ( color[0] < 0.f ) color[0] = 0.f;
+ if ( color[1] < 0.f ) color[1] = 0.f;
+ if ( color[2] < 0.f ) color[2] = 0.f;
+}
+
+inline void ColorClampTruncate( Vector& color )
+{
+ if (color[0] > 1.0f) color[0] = 1.0f; else if (color[0] < 0.0f) color[0] = 0.0f;
+ if (color[1] > 1.0f) color[1] = 1.0f; else if (color[1] < 0.0f) color[1] = 0.0f;
+ if (color[2] > 1.0f) color[2] = 1.0f; else if (color[2] < 0.0f) color[2] = 0.0f;
+}
+
+// Interpolate a Catmull-Rom spline.
+// t is a [0,1] value and interpolates a curve between p2 and p3.
+void Catmull_Rom_Spline(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector &output );
+
+// Interpolate a Catmull-Rom spline.
+// Returns the tangent of the point at t of the spline
+void Catmull_Rom_Spline_Tangent(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector &output );
+
+// area under the curve [0..t]
+void Catmull_Rom_Spline_Integral(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// area under the curve [0..1]
+void Catmull_Rom_Spline_Integral(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ Vector& output );
+
+// Interpolate a Catmull-Rom spline.
+// Normalize p2->p1 and p3->p4 to be the same length as p2->p3
+void Catmull_Rom_Spline_Normalize(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector &output );
+
+// area under the curve [0..t]
+// Normalize p2->p1 and p3->p4 to be the same length as p2->p3
+void Catmull_Rom_Spline_Integral_Normalize(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// Interpolate a Catmull-Rom spline.
+// Normalize p2.x->p1.x and p3.x->p4.x to be the same length as p2.x->p3.x
+void Catmull_Rom_Spline_NormalizeX(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector &output );
+
+// area under the curve [0..t]
+void Catmull_Rom_Spline_NormalizeX(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// Interpolate a Hermite spline.
+// t is a [0,1] value and interpolates a curve between p1 and p2 with the deltas d1 and d2.
+void Hermite_Spline(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &d1,
+ const Vector &d2,
+ float t,
+ Vector& output );
+
+float Hermite_Spline(
+ float p1,
+ float p2,
+ float d1,
+ float d2,
+ float t );
+
+// t is a [0,1] value and interpolates a curve between p1 and p2 with the slopes p0->p1 and p1->p2
+void Hermite_Spline(
+ const Vector &p0,
+ const Vector &p1,
+ const Vector &p2,
+ float t,
+ Vector& output );
+
+float Hermite_Spline(
+ float p0,
+ float p1,
+ float p2,
+ float t );
+
+
+void Hermite_SplineBasis( float t, float basis[] );
+
+void Hermite_Spline(
+ const Quaternion &q0,
+ const Quaternion &q1,
+ const Quaternion &q2,
+ float t,
+ Quaternion &output );
+
+
+// See http://en.wikipedia.org/wiki/Kochanek-Bartels_curves
+//
+// Tension: -1 = Round -> 1 = Tight
+// Bias: -1 = Pre-shoot (bias left) -> 1 = Post-shoot (bias right)
+// Continuity: -1 = Box corners -> 1 = Inverted corners
+//
+// If T=B=C=0 it's the same matrix as Catmull-Rom.
+// If T=1 & B=C=0 it's the same as Cubic.
+// If T=B=0 & C=-1 it's just linear interpolation
+//
+// See http://news.povray.org/povray.binaries.tutorials/attachment/%[email protected]%3E/Splines.bas.txt
+// for example code and descriptions of various spline types...
+//
+void Kochanek_Bartels_Spline(
+ float tension,
+ float bias,
+ float continuity,
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+void Kochanek_Bartels_Spline_NormalizeX(
+ float tension,
+ float bias,
+ float continuity,
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// See link at Kochanek_Bartels_Spline for info on the basis matrix used
+void Cubic_Spline(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+void Cubic_Spline_NormalizeX(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// See link at Kochanek_Bartels_Spline for info on the basis matrix used
+void BSpline(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+void BSpline_NormalizeX(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// See link at Kochanek_Bartels_Spline for info on the basis matrix used
+void Parabolic_Spline(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+void Parabolic_Spline_NormalizeX(
+ const Vector &p1,
+ const Vector &p2,
+ const Vector &p3,
+ const Vector &p4,
+ float t,
+ Vector& output );
+
+// Evaluate the cubic Bernstein basis for the input parametric coordinate.
+// Output is the coefficient for that basis polynomial.
+float CubicBasis0( float t );
+float CubicBasis1( float t );
+float CubicBasis2( float t );
+float CubicBasis3( float t );
+
+// quintic interpolating polynomial from Perlin.
+// 0->0, 1->1, smooth-in between with smooth tangents
+FORCEINLINE float QuinticInterpolatingPolynomial(float t)
+{
+ // 6t^5-15t^4+10t^3
+ return t * t * t *( t * ( t* 6.0 - 15.0 ) + 10.0 );
+}
+
+// given a table of sorted tabulated positions, return the two indices and blendfactor to linear
+// interpolate. Does a search. Can be used to find the blend value to interpolate between
+// keyframes.
+void GetInterpolationData( float const *pKnotPositions,
+ float const *pKnotValues,
+ int nNumValuesinList,
+ int nInterpolationRange,
+ float flPositionToInterpolateAt,
+ bool bWrap,
+ float *pValueA,
+ float *pValueB,
+ float *pInterpolationValue);
+float RangeCompressor( float flValue, float flMin, float flMax, float flBase );
+
+// Get the minimum distance from vOrigin to the bounding box defined by [mins,maxs]
+// using voronoi regions.
+// 0 is returned if the origin is inside the box.
+float CalcSqrDistanceToAABB( const Vector &mins, const Vector &maxs, const Vector &point );
+void CalcClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut );
+void CalcSqrDistAndClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut, float &distSqrOut );
+
+inline float CalcDistanceToAABB( const Vector &mins, const Vector &maxs, const Vector &point )
+{
+ float flDistSqr = CalcSqrDistanceToAABB( mins, maxs, point );
+ return sqrt(flDistSqr);
+}
+
+// Get the closest point from P to the (infinite) line through vLineA and vLineB and
+// calculate the shortest distance from P to the line.
+// If you pass in a value for t, it will tell you the t for (A + (B-A)t) to get the closest point.
+// If the closest point lies on the segment between A and B, then 0 <= t <= 1.
+void CalcClosestPointOnLine( const Vector &P, const Vector &vLineA, const Vector &vLineB, Vector &vClosest, float *t=0 );
+float CalcDistanceToLine( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 );
+float CalcDistanceSqrToLine( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 );
+
+// The same three functions as above, except now the line is closed between A and B.
+void CalcClosestPointOnLineSegment( const Vector &P, const Vector &vLineA, const Vector &vLineB, Vector &vClosest, float *t=0 );
+float CalcDistanceToLineSegment( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 );
+float CalcDistanceSqrToLineSegment( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 );
+
+// A function to compute the closes line segment connnection two lines (or false if the lines are parallel, etc.)
+bool CalcLineToLineIntersectionSegment(
+ const Vector& p1,const Vector& p2,const Vector& p3,const Vector& p4,Vector *s1,Vector *s2,
+ float *t1, float *t2 );
+
+// The above functions in 2D
+void CalcClosestPointOnLine2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, Vector2D &vClosest, float *t=0 );
+float CalcDistanceToLine2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 );
+float CalcDistanceSqrToLine2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 );
+void CalcClosestPointOnLineSegment2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, Vector2D &vClosest, float *t=0 );
+float CalcDistanceToLineSegment2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 );
+float CalcDistanceSqrToLineSegment2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 );
+
+// Init the mathlib
+void MathLib_Init( float gamma = 2.2f, float texGamma = 2.2f, float brightness = 0.0f, int overbright = 2.0f, bool bAllow3DNow = true, bool bAllowSSE = true, bool bAllowSSE2 = true, bool bAllowMMX = true );
+bool MathLib_MMXEnabled( void );
+bool MathLib_SSEEnabled( void );
+bool MathLib_SSE2Enabled( void );
+
+inline float Approach( float target, float value, float speed );
+float ApproachAngle( float target, float value, float speed );
+float AngleDiff( float destAngle, float srcAngle );
+float AngleDistance( float next, float cur );
+float AngleNormalize( float angle );
+
+// ensure that 0 <= angle <= 360
+float AngleNormalizePositive( float angle );
+
+bool AnglesAreEqual( float a, float b, float tolerance = 0.0f );
+
+
+void RotationDeltaAxisAngle( const QAngle &srcAngles, const QAngle &destAngles, Vector &deltaAxis, float &deltaAngle );
+void RotationDelta( const QAngle &srcAngles, const QAngle &destAngles, QAngle *out );
+
+//-----------------------------------------------------------------------------
+// Clips a line segment such that only the portion in the positive half-space
+// of the plane remains. If the segment is entirely clipped, the vectors
+// are set to vec3_invalid (all components are FLT_MAX).
+//
+// flBias is added to the dot product with the normal. A positive bias
+// results in a more inclusive positive half-space, while a negative bias
+// results in a more exclusive positive half-space.
+//-----------------------------------------------------------------------------
+void ClipLineSegmentToPlane( const Vector &vNormal, const Vector &vPlanePoint, Vector *p1, Vector *p2, float flBias = 0.0f );
+
+void ComputeTrianglePlane( const Vector& v1, const Vector& v2, const Vector& v3, Vector& normal, float& intercept );
+int PolyFromPlane( Vector *pOutVerts, const Vector& normal, float dist, float fHalfScale = 9000.0f );
+void PolyFromPlane_SIMD( fltx4 *pOutVerts, const fltx4 & plane, float fHalfScale = 9000.0f );
+int ClipPolyToPlane( Vector *inVerts, int vertCount, Vector *outVerts, const Vector& normal, float dist, float fOnPlaneEpsilon = 0.1f );
+int ClipPolyToPlane_SIMD( fltx4 *pInVerts, int vertCount, fltx4 *pOutVerts, const fltx4& plane, float fOnPlaneEpsilon = 0.1f );
+int ClipPolyToPlane_Precise( double *inVerts, int vertCount, double *outVerts, const double *normal, double dist, double fOnPlaneEpsilon = 0.1 );
+float TetrahedronVolume( const Vector &p0, const Vector &p1, const Vector &p2, const Vector &p3 );
+float TriangleArea( const Vector &p0, const Vector &p1, const Vector &p2 );
+
+//-----------------------------------------------------------------------------
+// Computes a reasonable tangent space for a triangle
+//-----------------------------------------------------------------------------
+void CalcTriangleTangentSpace( const Vector &p0, const Vector &p1, const Vector &p2,
+ const Vector2D &t0, const Vector2D &t1, const Vector2D& t2,
+ Vector &sVect, Vector &tVect );
+
+//-----------------------------------------------------------------------------
+// Transforms a AABB into another space; which will inherently grow the box.
+//-----------------------------------------------------------------------------
+void TransformAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut );
+
+//-----------------------------------------------------------------------------
+// Uses the inverse transform of in1
+//-----------------------------------------------------------------------------
+void ITransformAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut );
+
+//-----------------------------------------------------------------------------
+// Rotates a AABB into another space; which will inherently grow the box.
+// (same as TransformAABB, but doesn't take the translation into account)
+//-----------------------------------------------------------------------------
+void RotateAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut );
+
+//-----------------------------------------------------------------------------
+// Uses the inverse transform of in1
+//-----------------------------------------------------------------------------
+void IRotateAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut );
+
+//-----------------------------------------------------------------------------
+// Transform a plane
+//-----------------------------------------------------------------------------
+inline void MatrixTransformPlane( const matrix3x4_t &src, const cplane_t &inPlane, cplane_t &outPlane )
+{
+ // What we want to do is the following:
+ // 1) transform the normal into the new space.
+ // 2) Determine a point on the old plane given by plane dist * plane normal
+ // 3) Transform that point into the new space
+ // 4) Plane dist = DotProduct( new normal, new point )
+
+ // An optimized version, which works if the plane is orthogonal.
+ // 1) Transform the normal into the new space
+ // 2) Realize that transforming the old plane point into the new space
+ // is given by [ d * n'x + Tx, d * n'y + Ty, d * n'z + Tz ]
+ // where d = old plane dist, n' = transformed normal, Tn = translational component of transform
+ // 3) Compute the new plane dist using the dot product of the normal result of #2
+
+ // For a correct result, this should be an inverse-transpose matrix
+ // but that only matters if there are nonuniform scale or skew factors in this matrix.
+ VectorRotate( inPlane.normal, src, outPlane.normal );
+ outPlane.dist = inPlane.dist * DotProduct( outPlane.normal, outPlane.normal );
+ outPlane.dist += outPlane.normal.x * src[0][3] + outPlane.normal.y * src[1][3] + outPlane.normal.z * src[2][3];
+}
+
+inline void MatrixITransformPlane( const matrix3x4_t &src, const cplane_t &inPlane, cplane_t &outPlane )
+{
+ // The trick here is that Tn = translational component of transform,
+ // but for an inverse transform, Tn = - R^-1 * T
+ Vector vecTranslation;
+ MatrixGetColumn( src, 3, vecTranslation );
+
+ Vector vecInvTranslation;
+ VectorIRotate( vecTranslation, src, vecInvTranslation );
+
+ VectorIRotate( inPlane.normal, src, outPlane.normal );
+ outPlane.dist = inPlane.dist * DotProduct( outPlane.normal, outPlane.normal );
+ outPlane.dist -= outPlane.normal.x * vecInvTranslation[0] + outPlane.normal.y * vecInvTranslation[1] + outPlane.normal.z * vecInvTranslation[2];
+}
+
+int CeilPow2( int in );
+int FloorPow2( int in );
+
+FORCEINLINE float * UnpackNormal_HEND3N( const unsigned int *pPackedNormal, float *pNormal )
+{
+ int temp[3];
+ temp[0] = ((*pPackedNormal >> 0L) & 0x7ff);
+ if ( temp[0] & 0x400 )
+ {
+ temp[0] = 2048 - temp[0];
+ }
+ temp[1] = ((*pPackedNormal >> 11L) & 0x7ff);
+ if ( temp[1] & 0x400 )
+ {
+ temp[1] = 2048 - temp[1];
+ }
+ temp[2] = ((*pPackedNormal >> 22L) & 0x3ff);
+ if ( temp[2] & 0x200 )
+ {
+ temp[2] = 1024 - temp[2];
+ }
+ pNormal[0] = (float)temp[0] * 1.0f/1023.0f;
+ pNormal[1] = (float)temp[1] * 1.0f/1023.0f;
+ pNormal[2] = (float)temp[2] * 1.0f/511.0f;
+ return pNormal;
+}
+
+
+FORCEINLINE unsigned int * PackNormal_HEND3N( const float *pNormal, unsigned int *pPackedNormal )
+{
+ int temp[3];
+
+ temp[0] = Float2Int( pNormal[0] * 1023.0f );
+ temp[1] = Float2Int( pNormal[1] * 1023.0f );
+ temp[2] = Float2Int( pNormal[2] * 511.0f );
+
+ // the normal is out of bounds, determine the source and fix
+ // clamping would be even more of a slowdown here
+ Assert( temp[0] >= -1023 && temp[0] <= 1023 );
+ Assert( temp[1] >= -1023 && temp[1] <= 1023 );
+ Assert( temp[2] >= -511 && temp[2] <= 511 );
+
+ *pPackedNormal = ( ( temp[2] & 0x3ff ) << 22L ) |
+ ( ( temp[1] & 0x7ff ) << 11L ) |
+ ( ( temp[0] & 0x7ff ) << 0L );
+ return pPackedNormal;
+}
+
+
+FORCEINLINE unsigned int * PackNormal_HEND3N( float nx, float ny, float nz, unsigned int *pPackedNormal )
+{
+ int temp[3];
+
+ temp[0] = Float2Int( nx * 1023.0f );
+ temp[1] = Float2Int( ny * 1023.0f );
+ temp[2] = Float2Int( nz * 511.0f );
+
+ // the normal is out of bounds, determine the source and fix
+ // clamping would be even more of a slowdown here
+ Assert( temp[0] >= -1023 && temp[0] <= 1023 );
+ Assert( temp[1] >= -1023 && temp[1] <= 1023 );
+ Assert( temp[2] >= -511 && temp[2] <= 511 );
+
+ *pPackedNormal = ( ( temp[2] & 0x3ff ) << 22L ) |
+ ( ( temp[1] & 0x7ff ) << 11L ) |
+ ( ( temp[0] & 0x7ff ) << 0L );
+ return pPackedNormal;
+}
+
+
+
+FORCEINLINE float * UnpackNormal_SHORT2( const unsigned int *pPackedNormal, float *pNormal, bool bIsTangent = FALSE )
+{
+ // Unpacks from Jason's 2-short format (fills in a 4th binormal-sign (+1/-1) value, if this is a tangent vector)
+
+ // FIXME: short math is slow on 360 - use ints here instead (bit-twiddle to deal w/ the sign bits)
+ short iX = (*pPackedNormal & 0x0000FFFF);
+ short iY = (*pPackedNormal & 0xFFFF0000) >> 16;
+
+ float zSign = +1;
+ if ( iX < 0 )
+ {
+ zSign = -1;
+ iX = -iX;
+ }
+ float tSign = +1;
+ if ( iY < 0 )
+ {
+ tSign = -1;
+ iY = -iY;
+ }
+
+ pNormal[0] = ( iX - 16384.0f ) / 16384.0f;
+ pNormal[1] = ( iY - 16384.0f ) / 16384.0f;
+ float mag = ( pNormal[0]*pNormal[0] + pNormal[1]*pNormal[1] );
+ if ( mag > 1.0f )
+ {
+ mag = 1.0f;
+ }
+ pNormal[2] = zSign*sqrtf( 1.0f - mag );
+ if ( bIsTangent )
+ {
+ pNormal[3] = tSign;
+ }
+
+ return pNormal;
+}
+
+FORCEINLINE unsigned int * PackNormal_SHORT2( float nx, float ny, float nz, unsigned int *pPackedNormal, float binormalSign = +1.0f )
+{
+ // Pack a vector (ASSUMED TO BE NORMALIZED) into Jason's 4-byte (SHORT2) format.
+ // This simply reconstructs Z from X & Y. It uses the sign bits of the X & Y coords
+ // to reconstruct the sign of Z and, if this is a tangent vector, the sign of the
+ // binormal (this is needed because tangent/binormal vectors are supposed to follow
+ // UV gradients, but shaders reconstruct the binormal from the tangent and normal
+ // assuming that they form a right-handed basis).
+
+ nx += 1; // [-1,+1] -> [0,2]
+ ny += 1;
+ nx *= 16384.0f; // [ 0, 2] -> [0,32768]
+ ny *= 16384.0f;
+
+ // '0' and '32768' values are invalid encodings
+ nx = MAX( nx, 1.0f ); // Make sure there are no zero values
+ ny = MAX( ny, 1.0f );
+ nx = MIN( nx, 32767.0f ); // Make sure there are no 32768 values
+ ny = MIN( ny, 32767.0f );
+
+ if ( nz < 0.0f )
+ nx = -nx; // Set the sign bit for z
+
+ ny *= binormalSign; // Set the sign bit for the binormal (use when encoding a tangent vector)
+
+ // FIXME: short math is slow on 360 - use ints here instead (bit-twiddle to deal w/ the sign bits), also use Float2Int()
+ short sX = (short)nx; // signed short [1,32767]
+ short sY = (short)ny;
+
+ *pPackedNormal = ( sX & 0x0000FFFF ) | ( sY << 16 ); // NOTE: The mask is necessary (if sX is negative and cast to an int...)
+
+ return pPackedNormal;
+}
+
+FORCEINLINE unsigned int * PackNormal_SHORT2( const float *pNormal, unsigned int *pPackedNormal, float binormalSign = +1.0f )
+{
+ return PackNormal_SHORT2( pNormal[0], pNormal[1], pNormal[2], pPackedNormal, binormalSign );
+}
+
+// Unpacks a UBYTE4 normal (for a tangent, the result's fourth component receives the binormal 'sign')
+FORCEINLINE float * UnpackNormal_UBYTE4( const unsigned int *pPackedNormal, float *pNormal, bool bIsTangent = FALSE )
+{
+ unsigned char cX, cY;
+ if ( bIsTangent )
+ {
+ cX = *pPackedNormal >> 16; // Unpack Z
+ cY = *pPackedNormal >> 24; // Unpack W
+ }
+ else
+ {
+ cX = *pPackedNormal >> 0; // Unpack X
+ cY = *pPackedNormal >> 8; // Unpack Y
+ }
+
+ float x = cX - 128.0f;
+ float y = cY - 128.0f;
+ float z;
+
+ float zSignBit = x < 0 ? 1.0f : 0.0f; // z and t negative bits (like slt asm instruction)
+ float tSignBit = y < 0 ? 1.0f : 0.0f;
+ float zSign = -( 2*zSignBit - 1 ); // z and t signs
+ float tSign = -( 2*tSignBit - 1 );
+
+ x = x*zSign - zSignBit; // 0..127
+ y = y*tSign - tSignBit;
+ x = x - 64; // -64..63
+ y = y - 64;
+
+ float xSignBit = x < 0 ? 1.0f : 0.0f; // x and y negative bits (like slt asm instruction)
+ float ySignBit = y < 0 ? 1.0f : 0.0f;
+ float xSign = -( 2*xSignBit - 1 ); // x and y signs
+ float ySign = -( 2*ySignBit - 1 );
+
+ x = ( x*xSign - xSignBit ) / 63.0f; // 0..1 range
+ y = ( y*ySign - ySignBit ) / 63.0f;
+ z = 1.0f - x - y;
+
+ float oolen = 1.0f / sqrt( x*x + y*y + z*z ); // Normalize and
+ x *= oolen * xSign; // Recover signs
+ y *= oolen * ySign;
+ z *= oolen * zSign;
+
+ pNormal[0] = x;
+ pNormal[1] = y;
+ pNormal[2] = z;
+ if ( bIsTangent )
+ {
+ pNormal[3] = tSign;
+ }
+
+ return pNormal;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// See: http://www.oroboro.com/rafael/docserv.php/index/programming/article/unitv2
+//
+// UBYTE4 encoding, using per-octant projection onto x+y+z=1
+// Assume input vector is already unit length
+//
+// binormalSign specifies 'sign' of binormal, stored in t sign bit of tangent
+// (lets the shader know whether norm/tan/bin form a right-handed basis)
+//
+// bIsTangent is used to specify which WORD of the output to store the data
+// The expected usage is to call once with the normal and once with
+// the tangent and binormal sign flag, bitwise OR'ing the returned DWORDs
+FORCEINLINE unsigned int * PackNormal_UBYTE4( float nx, float ny, float nz, unsigned int *pPackedNormal, bool bIsTangent = false, float binormalSign = +1.0f )
+{
+ float xSign = nx < 0.0f ? -1.0f : 1.0f; // -1 or 1 sign
+ float ySign = ny < 0.0f ? -1.0f : 1.0f;
+ float zSign = nz < 0.0f ? -1.0f : 1.0f;
+ float tSign = binormalSign;
+ Assert( ( binormalSign == +1.0f ) || ( binormalSign == -1.0f ) );
+
+ float xSignBit = 0.5f*( 1 - xSign ); // [-1,+1] -> [1,0]
+ float ySignBit = 0.5f*( 1 - ySign ); // 1 is negative bit (like slt instruction)
+ float zSignBit = 0.5f*( 1 - zSign );
+ float tSignBit = 0.5f*( 1 - binormalSign );
+
+ float absX = xSign*nx; // 0..1 range (abs)
+ float absY = ySign*ny;
+ float absZ = zSign*nz;
+
+ float xbits = absX / ( absX + absY + absZ ); // Project onto x+y+z=1 plane
+ float ybits = absY / ( absX + absY + absZ );
+
+ xbits *= 63; // 0..63
+ ybits *= 63;
+
+ xbits = xbits * xSign - xSignBit; // -64..63 range
+ ybits = ybits * ySign - ySignBit;
+ xbits += 64.0f; // 0..127 range
+ ybits += 64.0f;
+
+ xbits = xbits * zSign - zSignBit; // Negate based on z and t
+ ybits = ybits * tSign - tSignBit; // -128..127 range
+
+ xbits += 128.0f; // 0..255 range
+ ybits += 128.0f;
+
+ unsigned char cX = (unsigned char) xbits;
+ unsigned char cY = (unsigned char) ybits;
+
+ if ( !bIsTangent )
+ *pPackedNormal = (cX << 0) | (cY << 8); // xy for normal
+ else
+ *pPackedNormal = (cX << 16) | (cY << 24); // zw for tangent
+
+ return pPackedNormal;
+}
+
+FORCEINLINE unsigned int * PackNormal_UBYTE4( const float *pNormal, unsigned int *pPackedNormal, bool bIsTangent = false, float binormalSign = +1.0f )
+{
+ return PackNormal_UBYTE4( pNormal[0], pNormal[1], pNormal[2], pPackedNormal, bIsTangent, binormalSign );
+}
+
+FORCEINLINE void RGB2YUV( int &nR, int &nG, int &nB, float &fY, float &fU, float &fV, bool bApplySaturationCurve )
+{
+ // YUV conversion:
+ // |Y| | 0.299f 0.587f 0.114f | |R|
+ // |U| = | -0.14713f -0.28886f 0.436f | x |G|
+ // |V| | 0.615f -0.51499f -0.10001f | |B|
+ //
+ // The coefficients in the first row sum to one, whereas the 2nd and 3rd rows each sum to zero (UV (0,0) means greyscale).
+ // Ranges are Y [0,1], U [-0.436,+0.436] and V [-0.615,+0.615].
+ // We scale and offset to [0,1] and allow the caller to round as they please.
+
+ fY = ( 0.29900f*nR + 0.58700f*nG + 0.11400f*nB ) / 255;
+ fU = ( -0.14713f*nR + -0.28886f*nG + 0.43600f*nB )*( 0.5f / 0.436f ) / 255 + 0.5f;
+ fV = ( 0.61500f*nR + -0.51499f*nG + -0.10001f*nB )*( 0.5f / 0.615f ) / 255 + 0.5f;
+
+ if ( bApplySaturationCurve )
+ {
+ // Apply a curve to saturation, and snap-to-grey for low saturations
+ const float SNAP_TO_GREY = 0;//0.0125f; Disabled, saturation curve seems sufficient
+ float dX, dY, sat, scale;
+ dX = 2*( fU - 0.5f );
+ dY = 2*( fV - 0.5f );
+ sat = sqrtf( dX*dX + dY*dY );
+ sat = clamp( ( sat*( 1 + SNAP_TO_GREY ) - SNAP_TO_GREY ), 0, 1 );
+ scale = ( sat == 0 ) ? 0 : MIN( ( sqrtf( sat ) / sat ), 4.0f );
+ fU = 0.5f + scale*( fU - 0.5f );
+ fV = 0.5f + scale*( fV - 0.5f );
+ }
+}
+
+#ifdef _X360
+// Used for direct CPU access to VB data on 360 (used by shaderapi, studiorender and engine)
+struct VBCPU_AccessInfo_t
+{
+ // Points to the GPU data pointer in the CVertexBuffer struct (VB data can be relocated during level transitions)
+ const byte **ppBaseAddress;
+ // pBaseAddress should be computed from ppBaseAddress immediately before use
+ const byte *pBaseAddress;
+ int nStride;
+ int nPositionOffset;
+ int nTexCoord0_Offset;
+ int nNormalOffset;
+ int nBoneIndexOffset;
+ int nBoneWeightOffset;
+ int nCompressionType;
+ // TODO: if needed, add colour and tangents
+};
+#endif
+
+//-----------------------------------------------------------------------------
+// Convert RGB to HSV
+//-----------------------------------------------------------------------------
+void RGBtoHSV( const Vector &rgb, Vector &hsv );
+
+
+//-----------------------------------------------------------------------------
+// Convert HSV to RGB
+//-----------------------------------------------------------------------------
+void HSVtoRGB( const Vector &hsv, Vector &rgb );
+
+
+//-----------------------------------------------------------------------------
+// Fast version of pow and log
+//-----------------------------------------------------------------------------
+#ifndef _PS3 // these actually aren't fast (or correct) on the PS3
+float FastLog2(float i); // log2( i )
+float FastPow2(float i); // 2^i
+float FastPow(float a, float b); // a^b
+float FastPow10( float i ); // 10^i
+#else
+inline float FastLog2(float i) {return logbf(i);} // log2( i )
+inline float FastPow2(float i) {return exp2f(i);} // 2^i
+inline float FastPow(float a, float b) {return powf(a,b);} // a^b
+#define LOGBASE2OF10 3.3219280948873623478703194294893901758648313930
+inline float FastPow10( float i ) { return exp2f( i * LOGBASE2OF10 ); } // 10^i, transform to base two, so log2(10^y) = y log2(10) . log2(10) = 3.3219280948873623478703194294893901758648313930
+#endif
+
+//-----------------------------------------------------------------------------
+// For testing float equality
+//-----------------------------------------------------------------------------
+
+inline bool CloseEnough( float a, float b, float epsilon = EQUAL_EPSILON )
+{
+ return fabs( a - b ) <= epsilon;
+}
+
+inline bool CloseEnough( const Vector &a, const Vector &b, float epsilon = EQUAL_EPSILON )
+{
+ return fabs( a.x - b.x ) <= epsilon &&
+ fabs( a.y - b.y ) <= epsilon &&
+ fabs( a.z - b.z ) <= epsilon;
+}
+
+// Fast compare
+// maxUlps is the maximum error in terms of Units in the Last Place. This
+// specifies how big an error we are willing to accept in terms of the value
+// of the least significant digit of the floating point number�s
+// representation. maxUlps can also be interpreted in terms of how many
+// representable floats we are willing to accept between A and B.
+// This function will allow maxUlps-1 floats between A and B.
+bool AlmostEqual(float a, float b, int maxUlps = 10);
+
+inline bool AlmostEqual( const Vector &a, const Vector &b, int maxUlps = 10)
+{
+ return AlmostEqual( a.x, b.x, maxUlps ) &&
+ AlmostEqual( a.y, b.y, maxUlps ) &&
+ AlmostEqual( a.z, b.z, maxUlps );
+}
+
+inline float Approach( float target, float value, float speed )
+{
+ float delta = target - value;
+
+#if defined(_X360) || defined( _PS3 ) // use conditional move for speed on 360
+
+ return fsel( delta-speed, // delta >= speed ?
+ value + speed, // if delta == speed, then value + speed == value + delta == target
+ fsel( (-speed) - delta, // delta <= -speed
+ value - speed,
+ target )
+ ); // delta < speed && delta > -speed
+
+#else
+
+ if ( delta > speed )
+ value += speed;
+ else if ( delta < -speed )
+ value -= speed;
+ else
+ value = target;
+
+ return value;
+
+#endif
+}
+
+// on PPC we can do this truncate without converting to int
+#if defined(_X360) || defined(_PS3)
+inline double TruncateFloatToIntAsFloat( double flVal )
+{
+#if defined(_X360)
+ double flIntFormat = __fctiwz( flVal );
+ return __fcfid( flIntFormat );
+#elif defined(_PS3)
+ double flIntFormat = __builtin_fctiwz( flVal );
+ return __builtin_fcfid( flIntFormat );
+#endif
+}
+#endif
+
+inline double SubtractIntegerPart( double flVal )
+{
+#if defined(_X360) || defined(_PS3)
+ return flVal - TruncateFloatToIntAsFloat(flVal);
+#else
+ return flVal - int(flVal);
+#endif
+}
+#endif // MATH_BASE_H
+
diff --git a/external/vpc/public/mathlib/vector.h b/external/vpc/public/mathlib/vector.h
new file mode 100644
index 0000000..dac51a4
--- /dev/null
+++ b/external/vpc/public/mathlib/vector.h
@@ -0,0 +1,2633 @@
+//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <math.h>
+#include <float.h>
+
+// For vec_t, put this somewhere else?
+#include "tier0/basetypes.h"
+
+#if defined( _PS3 )
+//#include <ssemath.h>
+#include <vectormath/c/vectormath_aos.h>
+#include "platform.h"
+#include "mathlib/math_pfns.h"
+#endif
+
+#ifndef PLATFORM_PPC // we want our linux with xmm support
+// For MMX intrinsics
+#include <xmmintrin.h>
+#endif
+
+#ifndef ALIGN16_POST
+#define ALIGN16_POST
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/platform.h"
+#include "tier0/threadtools.h"
+#include "mathlib/vector2d.h"
+#include "mathlib/math_pfns.h"
+#include "tier0/memalloc.h"
+#include "vstdlib/random.h"
+// Uncomment this to add extra Asserts to check for NANs, uninitialized vecs, etc.
+//#define VECTOR_PARANOIA 1
+
+// Uncomment this to make sure we don't do anything slow with our vectors
+//#define VECTOR_NO_SLOW_OPERATIONS 1
+
+
+// Used to make certain code easier to read.
+#define X_INDEX 0
+#define Y_INDEX 1
+#define Z_INDEX 2
+
+
+#ifdef VECTOR_PARANOIA
+#define CHECK_VALID( _v) Assert( (_v).IsValid() )
+#else
+#ifdef GNUC
+#define CHECK_VALID( _v)
+#else
+#define CHECK_VALID( _v) 0
+#endif
+#endif
+
+#define VecToString(v) (static_cast<const char *>(CFmtStr("(%f, %f, %f)", (v).x, (v).y, (v).z))) // ** Note: this generates a temporary, don't hold reference!
+
+class VectorByValue;
+
+//=========================================================
+// 3D Vector
+//=========================================================
+class Vector
+{
+public:
+ // Members
+ vec_t x, y, z;
+
+ // Construction/destruction:
+ Vector(void);
+ Vector(vec_t X, vec_t Y, vec_t Z);
+
+ // Initialization
+ void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f);
+ // TODO (Ilya): Should there be an init that takes a single float for consistency?
+
+ // Got any nasty NAN's?
+ bool IsValid() const;
+ void Invalidate();
+
+ // array access...
+ vec_t operator[](int i) const;
+ vec_t& operator[](int i);
+
+ // Base address...
+ vec_t* Base();
+ vec_t const* Base() const;
+
+ // Cast to Vector2D...
+ Vector2D& AsVector2D();
+ const Vector2D& AsVector2D() const;
+
+ // Initialization methods
+ void Random( vec_t minVal, vec_t maxVal );
+ inline void Zero(); ///< zero out a vector
+
+ // equality
+ bool operator==(const Vector& v) const;
+ bool operator!=(const Vector& v) const;
+
+ // arithmetic operations
+ FORCEINLINE Vector& operator+=(const Vector &v);
+ FORCEINLINE Vector& operator-=(const Vector &v);
+ FORCEINLINE Vector& operator*=(const Vector &v);
+ FORCEINLINE Vector& operator*=(float s);
+ FORCEINLINE Vector& operator/=(const Vector &v);
+ FORCEINLINE Vector& operator/=(float s);
+ FORCEINLINE Vector& operator+=(float fl) ; ///< broadcast add
+ FORCEINLINE Vector& operator-=(float fl) ; ///< broadcast sub
+
+// negate the vector components
+ void Negate();
+
+ // Get the vector's magnitude.
+ inline vec_t Length() const;
+
+ // Get the vector's magnitude squared.
+ FORCEINLINE vec_t LengthSqr(void) const
+ {
+ CHECK_VALID(*this);
+ return (x*x + y*y + z*z);
+ }
+
+ // Get one over the vector's length
+ // via fast hardware approximation
+ inline vec_t LengthRecipFast(void) const
+ {
+ return FastRSqrtFast( LengthSqr() );
+ }
+
+ // return true if this vector is (0,0,0) within tolerance
+ bool IsZero( float tolerance = 0.01f ) const
+ {
+ return (x > -tolerance && x < tolerance &&
+ y > -tolerance && y < tolerance &&
+ z > -tolerance && z < tolerance);
+ }
+
+
+ // return true if this vector is exactly (0,0,0) -- only fast if vector is coming from memory, not registers
+ inline bool IsZeroFast( ) const RESTRICT
+ {
+ COMPILE_TIME_ASSERT( sizeof(vec_t) == sizeof(int) );
+ return ( *(const int *)(&x) == 0 &&
+ *(const int *)(&y) == 0 &&
+ *(const int *)(&z) == 0 );
+ }
+
+ vec_t NormalizeInPlace();
+ Vector Normalized() const;
+ bool IsLengthGreaterThan( float val ) const;
+ bool IsLengthLessThan( float val ) const;
+
+ // check if a vector is within the box defined by two other vectors
+ FORCEINLINE bool WithinAABox( Vector const &boxmin, Vector const &boxmax);
+
+ // Get the distance from this vector to the other one.
+ vec_t DistTo(const Vector &vOther) const;
+
+ // Get the distance from this vector to the other one squared.
+ // NJS: note, VC wasn't inlining it correctly in several deeply nested inlines due to being an 'out of line' inline.
+ // may be able to tidy this up after switching to VC7
+ FORCEINLINE vec_t DistToSqr(const Vector &vOther) const
+ {
+ Vector delta;
+
+ delta.x = x - vOther.x;
+ delta.y = y - vOther.y;
+ delta.z = z - vOther.z;
+
+ return delta.LengthSqr();
+ }
+
+ // Copy
+ void CopyToArray(float* rgfl) const;
+
+ // Multiply, add, and assign to this (ie: *this = a + b * scalar). This
+ // is about 12% faster than the actual vector equation (because it's done per-component
+ // rather than per-vector).
+ void MulAdd(const Vector& a, const Vector& b, float scalar);
+
+ // Dot product.
+ vec_t Dot(const Vector& vOther) const;
+
+ // assignment
+ Vector& operator=(const Vector &vOther);
+
+ // returns 0, 1, 2 corresponding to the component with the largest absolute value
+ inline int LargestComponent() const;
+
+ // 2d
+ vec_t Length2D(void) const;
+ vec_t Length2DSqr(void) const;
+
+ /// get the component of this vector parallel to some other given vector
+ inline Vector ProjectOnto( const Vector& onto );
+
+ operator VectorByValue &() { return *((VectorByValue *)(this)); }
+ operator const VectorByValue &() const { return *((const VectorByValue *)(this)); }
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+ // copy constructors
+// Vector(const Vector &vOther);
+
+ // arithmetic operations
+ Vector operator-(void) const;
+
+ Vector operator+(const Vector& v) const;
+ Vector operator-(const Vector& v) const;
+ Vector operator*(const Vector& v) const;
+ Vector operator/(const Vector& v) const;
+ Vector operator*(float fl) const;
+ Vector operator/(float fl) const;
+
+ // Cross product between two vectors.
+ Vector Cross(const Vector &vOther) const;
+
+ // Returns a vector with the min or max in X, Y, and Z.
+ Vector Min(const Vector &vOther) const;
+ Vector Max(const Vector &vOther) const;
+
+#else
+
+private:
+ // No copy constructors allowed if we're in optimal mode
+ Vector(const Vector& vOther);
+#endif
+};
+
+
+
+#define USE_M64S defined( PLATFORM_WINDOWS_PC )
+
+
+
+//=========================================================
+// 4D Short Vector (aligned on 8-byte boundary)
+//=========================================================
+class ALIGN8 ShortVector
+{
+public:
+
+ short x, y, z, w;
+
+ // Initialization
+ void Init(short ix = 0, short iy = 0, short iz = 0, short iw = 0 );
+
+
+#if USE_M64S
+ __m64 &AsM64() { return *(__m64*)&x; }
+ const __m64 &AsM64() const { return *(const __m64*)&x; }
+#endif
+
+ // Setter
+ void Set( const ShortVector& vOther );
+ void Set( const short ix, const short iy, const short iz, const short iw );
+
+ // array access...
+ short operator[](int i) const;
+ short& operator[](int i);
+
+ // Base address...
+ short* Base();
+ short const* Base() const;
+
+ // equality
+ bool operator==(const ShortVector& v) const;
+ bool operator!=(const ShortVector& v) const;
+
+ // Arithmetic operations
+ FORCEINLINE ShortVector& operator+=(const ShortVector &v);
+ FORCEINLINE ShortVector& operator-=(const ShortVector &v);
+ FORCEINLINE ShortVector& operator*=(const ShortVector &v);
+ FORCEINLINE ShortVector& operator*=(float s);
+ FORCEINLINE ShortVector& operator/=(const ShortVector &v);
+ FORCEINLINE ShortVector& operator/=(float s);
+ FORCEINLINE ShortVector operator*(float fl) const;
+
+private:
+
+ // No copy constructors allowed if we're in optimal mode
+// ShortVector(ShortVector const& vOther);
+
+ // No assignment operators either...
+// ShortVector& operator=( ShortVector const& src );
+
+} ALIGN8_POST;
+
+
+
+
+
+
+//=========================================================
+// 4D Integer Vector
+//=========================================================
+class IntVector4D
+{
+public:
+
+ int x, y, z, w;
+
+ // Initialization
+ void Init(int ix = 0, int iy = 0, int iz = 0, int iw = 0 );
+
+#if USE_M64S
+ __m64 &AsM64() { return *(__m64*)&x; }
+ const __m64 &AsM64() const { return *(const __m64*)&x; }
+#endif
+
+ // Setter
+ void Set( const IntVector4D& vOther );
+ void Set( const int ix, const int iy, const int iz, const int iw );
+
+ // array access...
+ int operator[](int i) const;
+ int& operator[](int i);
+
+ // Base address...
+ int* Base();
+ int const* Base() const;
+
+ // equality
+ bool operator==(const IntVector4D& v) const;
+ bool operator!=(const IntVector4D& v) const;
+
+ // Arithmetic operations
+ FORCEINLINE IntVector4D& operator+=(const IntVector4D &v);
+ FORCEINLINE IntVector4D& operator-=(const IntVector4D &v);
+ FORCEINLINE IntVector4D& operator*=(const IntVector4D &v);
+ FORCEINLINE IntVector4D& operator*=(float s);
+ FORCEINLINE IntVector4D& operator/=(const IntVector4D &v);
+ FORCEINLINE IntVector4D& operator/=(float s);
+ FORCEINLINE IntVector4D operator*(float fl) const;
+
+private:
+
+ // No copy constructors allowed if we're in optimal mode
+ // IntVector4D(IntVector4D const& vOther);
+
+ // No assignment operators either...
+ // IntVector4D& operator=( IntVector4D const& src );
+
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Allows us to specifically pass the vector by value when we need to
+//-----------------------------------------------------------------------------
+class VectorByValue : public Vector
+{
+public:
+ // Construction/destruction:
+ VectorByValue(void) : Vector() {}
+ VectorByValue(vec_t X, vec_t Y, vec_t Z) : Vector( X, Y, Z ) {}
+ VectorByValue(const VectorByValue& vOther) { *this = vOther; }
+};
+
+
+//-----------------------------------------------------------------------------
+// Utility to simplify table construction. No constructor means can use
+// traditional C-style initialization
+//-----------------------------------------------------------------------------
+class TableVector
+{
+public:
+ vec_t x, y, z;
+
+ operator Vector &() { return *((Vector *)(this)); }
+ operator const Vector &() const { return *((const Vector *)(this)); }
+
+ // array access...
+ inline vec_t& operator[](int i)
+ {
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+ }
+
+ inline vec_t operator[](int i) const
+ {
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Here's where we add all those lovely SSE optimized routines
+//-----------------------------------------------------------------------------
+
+class ALIGN16 VectorAligned : public Vector
+{
+public:
+ inline VectorAligned(void) {};
+ inline VectorAligned(vec_t X, vec_t Y, vec_t Z)
+ {
+ Init(X,Y,Z);
+ }
+
+#ifdef VECTOR_NO_SLOW_OPERATIONS
+
+private:
+ // No copy constructors allowed if we're in optimal mode
+ VectorAligned(const VectorAligned& vOther);
+ VectorAligned(const Vector &vOther);
+
+#else
+public:
+ explicit VectorAligned(const Vector &vOther)
+ {
+ Init(vOther.x, vOther.y, vOther.z);
+ }
+
+ VectorAligned& operator=(const Vector &vOther)
+ {
+ Init(vOther.x, vOther.y, vOther.z);
+ return *this;
+ }
+
+ VectorAligned& operator=(const VectorAligned &vOther)
+ {
+ // we know we're aligned, so use simd
+ // we can't use the convenient abstract interface coz it gets declared later
+#ifdef _X360
+ XMStoreVector4A(Base(), XMLoadVector4A(vOther.Base()));
+#elif _WIN32
+ _mm_store_ps(Base(), _mm_load_ps( vOther.Base() ));
+#else
+ Init(vOther.x, vOther.y, vOther.z);
+#endif
+ return *this;
+ }
+
+
+#endif
+ float w; // this space is used anyway
+
+#if !defined(NO_MALLOC_OVERRIDE)
+ void* operator new[] ( size_t nSize)
+ {
+ return MemAlloc_AllocAligned(nSize, 16);
+ }
+
+ void* operator new[] ( size_t nSize, const char *pFileName, int nLine)
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+
+ void* operator new[] ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine)
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+
+ void operator delete[] ( void* p)
+ {
+ MemAlloc_FreeAligned(p);
+ }
+
+ void operator delete[] ( void* p, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+
+ void operator delete[] ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+
+ // please don't allocate a single quaternion...
+ void* operator new ( size_t nSize )
+ {
+ return MemAlloc_AllocAligned(nSize, 16);
+ }
+ void* operator new ( size_t nSize, const char *pFileName, int nLine )
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+ void* operator new ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine )
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+ void operator delete ( void* p)
+ {
+ MemAlloc_FreeAligned(p);
+ }
+
+ void operator delete ( void* p, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+
+ void operator delete ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+#endif
+} ALIGN16_POST;
+
+//-----------------------------------------------------------------------------
+// Vector related operations
+//-----------------------------------------------------------------------------
+
+// Vector clear
+FORCEINLINE void VectorClear( Vector& a );
+
+// Copy
+FORCEINLINE void VectorCopy( const Vector& src, Vector& dst );
+
+// Vector arithmetic
+FORCEINLINE void VectorAdd( const Vector& a, const Vector& b, Vector& result );
+FORCEINLINE void VectorSubtract( const Vector& a, const Vector& b, Vector& result );
+FORCEINLINE void VectorMultiply( const Vector& a, vec_t b, Vector& result );
+FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& result );
+FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& result );
+FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& result );
+inline void VectorScale ( const Vector& in, vec_t scale, Vector& result );
+void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest );
+
+// Vector equality with tolerance
+bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance = 0.0f );
+
+#define VectorExpand(v) (v).x, (v).y, (v).z
+
+
+// Normalization
+// FIXME: Can't use quite yet
+//vec_t VectorNormalize( Vector& v );
+
+// Length
+inline vec_t VectorLength( const Vector& v );
+
+// Dot Product
+FORCEINLINE vec_t DotProduct(const Vector& a, const Vector& b);
+
+// Cross product
+void CrossProduct(const Vector& a, const Vector& b, Vector& result );
+
+// Store the min or max of each of x, y, and z into the result.
+void VectorMin( const Vector &a, const Vector &b, Vector &result );
+void VectorMax( const Vector &a, const Vector &b, Vector &result );
+
+// Linearly interpolate between two vectors
+void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest );
+Vector VectorLerp(const Vector& src1, const Vector& src2, vec_t t );
+
+FORCEINLINE Vector ReplicateToVector( float x )
+{
+ return Vector( x, x, x );
+}
+
+FORCEINLINE bool PointWithinViewAngle( Vector const &vecSrcPosition,
+ Vector const &vecTargetPosition,
+ Vector const &vecLookDirection, float flCosHalfFOV )
+{
+ Vector vecDelta = vecTargetPosition - vecSrcPosition;
+ float cosDiff = DotProduct( vecLookDirection, vecDelta );
+
+ if ( flCosHalfFOV <= 0 ) // >180
+ {
+ // signs are different, answer is implicit
+ if ( cosDiff > 0 )
+ return true;
+
+ // a/sqrt(b) > c == a^2 < b * c ^2
+ // IFF left and right sides are <= 0
+ float flLen2 = vecDelta.LengthSqr();
+ return ( cosDiff * cosDiff <= flLen2 * flCosHalfFOV * flCosHalfFOV );
+ }
+ else // flCosHalfFOV > 0
+ {
+ // signs are different, answer is implicit
+ if ( cosDiff < 0 )
+ return false;
+
+ // a/sqrt(b) > c == a^2 > b * c ^2
+ // IFF left and right sides are >= 0
+ float flLen2 = vecDelta.LengthSqr();
+ return ( cosDiff * cosDiff >= flLen2 * flCosHalfFOV * flCosHalfFOV );
+ }
+}
+
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+// Cross product
+Vector CrossProduct( const Vector& a, const Vector& b );
+
+// Random vector creation
+Vector RandomVector( vec_t minVal, vec_t maxVal );
+
+#endif
+
+float RandomVectorInUnitSphere( Vector *pVector );
+float RandomVectorInUnitCircle( Vector2D *pVector );
+
+
+//-----------------------------------------------------------------------------
+//
+// Inlined Vector methods
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// constructors
+//-----------------------------------------------------------------------------
+inline Vector::Vector(void)
+{
+#ifdef _DEBUG
+#ifdef VECTOR_PARANOIA
+ // Initialize to NAN to catch errors
+ x = y = z = VEC_T_NAN;
+#endif
+#endif
+}
+
+inline Vector::Vector(vec_t X, vec_t Y, vec_t Z)
+{
+ x = X; y = Y; z = Z;
+ CHECK_VALID(*this);
+}
+
+//inline Vector::Vector(const float *pFloat)
+//{
+// Assert( pFloat );
+// x = pFloat[0]; y = pFloat[1]; z = pFloat[2];
+// CHECK_VALID(*this);
+//}
+
+#if 0
+//-----------------------------------------------------------------------------
+// copy constructor
+//-----------------------------------------------------------------------------
+
+inline Vector::Vector(const Vector &vOther)
+{
+ CHECK_VALID(vOther);
+ x = vOther.x; y = vOther.y; z = vOther.z;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// initialization
+//-----------------------------------------------------------------------------
+
+inline void Vector::Init( vec_t ix, vec_t iy, vec_t iz )
+{
+ x = ix; y = iy; z = iz;
+ CHECK_VALID(*this);
+}
+
+inline void Vector::Random( vec_t minVal, vec_t maxVal )
+{
+ x = RandomFloat( minVal, maxVal );
+ y = RandomFloat( minVal, maxVal );
+ z = RandomFloat( minVal, maxVal );
+ CHECK_VALID(*this);
+}
+
+// This should really be a single opcode on the PowerPC (move r0 onto the vec reg)
+inline void Vector::Zero()
+{
+ x = y = z = 0.0f;
+}
+
+inline void VectorClear( Vector& a )
+{
+ a.x = a.y = a.z = 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+// assignment
+//-----------------------------------------------------------------------------
+
+inline Vector& Vector::operator=(const Vector &vOther)
+{
+ CHECK_VALID(vOther);
+ x=vOther.x; y=vOther.y; z=vOther.z;
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+inline vec_t& Vector::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+}
+
+inline vec_t Vector::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// Base address...
+//-----------------------------------------------------------------------------
+inline vec_t* Vector::Base()
+{
+ return (vec_t*)this;
+}
+
+inline vec_t const* Vector::Base() const
+{
+ return (vec_t const*)this;
+}
+
+//-----------------------------------------------------------------------------
+// Cast to Vector2D...
+//-----------------------------------------------------------------------------
+
+inline Vector2D& Vector::AsVector2D()
+{
+ return *(Vector2D*)this;
+}
+
+inline const Vector2D& Vector::AsVector2D() const
+{
+ return *(const Vector2D*)this;
+}
+
+//-----------------------------------------------------------------------------
+// IsValid?
+//-----------------------------------------------------------------------------
+
+inline bool Vector::IsValid() const
+{
+ return IsFinite(x) && IsFinite(y) && IsFinite(z);
+}
+
+//-----------------------------------------------------------------------------
+// Invalidate
+//-----------------------------------------------------------------------------
+
+inline void Vector::Invalidate()
+{
+//#ifdef _DEBUG
+//#ifdef VECTOR_PARANOIA
+ x = y = z = VEC_T_NAN;
+//#endif
+//#endif
+}
+
+//-----------------------------------------------------------------------------
+// comparison
+//-----------------------------------------------------------------------------
+
+inline bool Vector::operator==( const Vector& src ) const
+{
+ CHECK_VALID(src);
+ CHECK_VALID(*this);
+ return (src.x == x) && (src.y == y) && (src.z == z);
+}
+
+inline bool Vector::operator!=( const Vector& src ) const
+{
+ CHECK_VALID(src);
+ CHECK_VALID(*this);
+ return (src.x != x) || (src.y != y) || (src.z != z);
+}
+
+
+//-----------------------------------------------------------------------------
+// Copy
+//-----------------------------------------------------------------------------
+
+FORCEINLINE void VectorCopy( const Vector& src, Vector& dst )
+{
+ CHECK_VALID(src);
+ dst.x = src.x;
+ dst.y = src.y;
+ dst.z = src.z;
+}
+
+inline void Vector::CopyToArray(float* rgfl) const
+{
+ Assert( rgfl );
+ CHECK_VALID(*this);
+ rgfl[0] = x, rgfl[1] = y, rgfl[2] = z;
+}
+
+//-----------------------------------------------------------------------------
+// standard math operations
+//-----------------------------------------------------------------------------
+// #pragma message("TODO: these should be SSE")
+
+inline void Vector::Negate()
+{
+ CHECK_VALID(*this);
+ x = -x; y = -y; z = -z;
+}
+
+FORCEINLINE Vector& Vector::operator+=(const Vector& v)
+{
+ CHECK_VALID(*this);
+ CHECK_VALID(v);
+ x+=v.x; y+=v.y; z += v.z;
+ return *this;
+}
+
+FORCEINLINE Vector& Vector::operator-=(const Vector& v)
+{
+ CHECK_VALID(*this);
+ CHECK_VALID(v);
+ x-=v.x; y-=v.y; z -= v.z;
+ return *this;
+}
+
+FORCEINLINE Vector& Vector::operator*=(float fl)
+{
+ x *= fl;
+ y *= fl;
+ z *= fl;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+FORCEINLINE Vector& Vector::operator*=(const Vector& v)
+{
+ CHECK_VALID(v);
+ x *= v.x;
+ y *= v.y;
+ z *= v.z;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+// this ought to be an opcode.
+FORCEINLINE Vector& Vector::operator+=(float fl)
+{
+ x += fl;
+ y += fl;
+ z += fl;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+FORCEINLINE Vector& Vector::operator-=(float fl)
+{
+ x -= fl;
+ y -= fl;
+ z -= fl;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+
+
+FORCEINLINE Vector& Vector::operator/=(float fl)
+{
+ Assert( fl != 0.0f );
+ float oofl = 1.0f / fl;
+ x *= oofl;
+ y *= oofl;
+ z *= oofl;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+FORCEINLINE Vector& Vector::operator/=(const Vector& v)
+{
+ CHECK_VALID(v);
+ Assert( v.x != 0.0f && v.y != 0.0f && v.z != 0.0f );
+ x /= v.x;
+ y /= v.y;
+ z /= v.z;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+
+// get the component of this vector parallel to some other given vector
+inline Vector Vector::ProjectOnto( const Vector& onto )
+{
+ return onto * ( this->Dot(onto) / ( onto.LengthSqr() ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inlined Short Vector methods
+//
+//-----------------------------------------------------------------------------
+
+
+inline void ShortVector::Init( short ix, short iy, short iz, short iw )
+{
+ x = ix; y = iy; z = iz; w = iw;
+}
+
+FORCEINLINE void ShortVector::Set( const ShortVector& vOther )
+{
+ x = vOther.x;
+ y = vOther.y;
+ z = vOther.z;
+ w = vOther.w;
+}
+
+FORCEINLINE void ShortVector::Set( const short ix, const short iy, const short iz, const short iw )
+{
+ x = ix;
+ y = iy;
+ z = iz;
+ w = iw;
+}
+
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+inline short ShortVector::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 4) );
+ return ((short*)this)[i];
+}
+
+inline short& ShortVector::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 4) );
+ return ((short*)this)[i];
+}
+
+//-----------------------------------------------------------------------------
+// Base address...
+//-----------------------------------------------------------------------------
+inline short* ShortVector::Base()
+{
+ return (short*)this;
+}
+
+inline short const* ShortVector::Base() const
+{
+ return (short const*)this;
+}
+
+
+//-----------------------------------------------------------------------------
+// comparison
+//-----------------------------------------------------------------------------
+
+inline bool ShortVector::operator==( const ShortVector& src ) const
+{
+ return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w);
+}
+
+inline bool ShortVector::operator!=( const ShortVector& src ) const
+{
+ return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w);
+}
+
+
+
+//-----------------------------------------------------------------------------
+// standard math operations
+//-----------------------------------------------------------------------------
+
+FORCEINLINE ShortVector& ShortVector::operator+=(const ShortVector& v)
+{
+ x+=v.x; y+=v.y; z += v.z; w += v.w;
+ return *this;
+}
+
+FORCEINLINE ShortVector& ShortVector::operator-=(const ShortVector& v)
+{
+ x-=v.x; y-=v.y; z -= v.z; w -= v.w;
+ return *this;
+}
+
+FORCEINLINE ShortVector& ShortVector::operator*=(float fl)
+{
+ x = (short)(x * fl);
+ y = (short)(y * fl);
+ z = (short)(z * fl);
+ w = (short)(w * fl);
+ return *this;
+}
+
+FORCEINLINE ShortVector& ShortVector::operator*=(const ShortVector& v)
+{
+ x = (short)(x * v.x);
+ y = (short)(y * v.y);
+ z = (short)(z * v.z);
+ w = (short)(w * v.w);
+ return *this;
+}
+
+FORCEINLINE ShortVector& ShortVector::operator/=(float fl)
+{
+ Assert( fl != 0.0f );
+ float oofl = 1.0f / fl;
+ x = (short)(x * oofl);
+ y = (short)(y * oofl);
+ z = (short)(z * oofl);
+ w = (short)(w * oofl);
+ return *this;
+}
+
+FORCEINLINE ShortVector& ShortVector::operator/=(const ShortVector& v)
+{
+ Assert( v.x != 0 && v.y != 0 && v.z != 0 && v.w != 0 );
+ x = (short)(x / v.x);
+ y = (short)(y / v.y);
+ z = (short)(z / v.z);
+ w = (short)(w / v.w);
+ return *this;
+}
+
+FORCEINLINE void ShortVectorMultiply( const ShortVector& src, float fl, ShortVector& res )
+{
+ Assert( IsFinite(fl) );
+ res.x = (short)(src.x * fl);
+ res.y = (short)(src.y * fl);
+ res.z = (short)(src.z * fl);
+ res.w = (short)(src.w * fl);
+}
+
+FORCEINLINE ShortVector ShortVector::operator*(float fl) const
+{
+ ShortVector res;
+ ShortVectorMultiply( *this, fl, res );
+ return res;
+}
+
+
+
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Inlined Integer Vector methods
+//
+//-----------------------------------------------------------------------------
+
+
+inline void IntVector4D::Init( int ix, int iy, int iz, int iw )
+{
+ x = ix; y = iy; z = iz; w = iw;
+}
+
+FORCEINLINE void IntVector4D::Set( const IntVector4D& vOther )
+{
+ x = vOther.x;
+ y = vOther.y;
+ z = vOther.z;
+ w = vOther.w;
+}
+
+FORCEINLINE void IntVector4D::Set( const int ix, const int iy, const int iz, const int iw )
+{
+ x = ix;
+ y = iy;
+ z = iz;
+ w = iw;
+}
+
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+inline int IntVector4D::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 4) );
+ return ((int*)this)[i];
+}
+
+inline int& IntVector4D::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 4) );
+ return ((int*)this)[i];
+}
+
+//-----------------------------------------------------------------------------
+// Base address...
+//-----------------------------------------------------------------------------
+inline int* IntVector4D::Base()
+{
+ return (int*)this;
+}
+
+inline int const* IntVector4D::Base() const
+{
+ return (int const*)this;
+}
+
+
+//-----------------------------------------------------------------------------
+// comparison
+//-----------------------------------------------------------------------------
+
+inline bool IntVector4D::operator==( const IntVector4D& src ) const
+{
+ return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w);
+}
+
+inline bool IntVector4D::operator!=( const IntVector4D& src ) const
+{
+ return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w);
+}
+
+
+
+//-----------------------------------------------------------------------------
+// standard math operations
+//-----------------------------------------------------------------------------
+
+FORCEINLINE IntVector4D& IntVector4D::operator+=(const IntVector4D& v)
+{
+ x+=v.x; y+=v.y; z += v.z; w += v.w;
+ return *this;
+}
+
+FORCEINLINE IntVector4D& IntVector4D::operator-=(const IntVector4D& v)
+{
+ x-=v.x; y-=v.y; z -= v.z; w -= v.w;
+ return *this;
+}
+
+FORCEINLINE IntVector4D& IntVector4D::operator*=(float fl)
+{
+ x = (int)(x * fl);
+ y = (int)(y * fl);
+ z = (int)(z * fl);
+ w = (int)(w * fl);
+ return *this;
+}
+
+FORCEINLINE IntVector4D& IntVector4D::operator*=(const IntVector4D& v)
+{
+ x = (int)(x * v.x);
+ y = (int)(y * v.y);
+ z = (int)(z * v.z);
+ w = (int)(w * v.w);
+ return *this;
+}
+
+FORCEINLINE IntVector4D& IntVector4D::operator/=(float fl)
+{
+ Assert( fl != 0.0f );
+ float oofl = 1.0f / fl;
+ x = (int)(x * oofl);
+ y = (int)(y * oofl);
+ z = (int)(z * oofl);
+ w = (int)(w * oofl);
+ return *this;
+}
+
+FORCEINLINE IntVector4D& IntVector4D::operator/=(const IntVector4D& v)
+{
+ Assert( v.x != 0 && v.y != 0 && v.z != 0 && v.w != 0 );
+ x = (int)(x / v.x);
+ y = (int)(y / v.y);
+ z = (int)(z / v.z);
+ w = (int)(w / v.w);
+ return *this;
+}
+
+FORCEINLINE void IntVector4DMultiply( const IntVector4D& src, float fl, IntVector4D& res )
+{
+ Assert( IsFinite(fl) );
+ res.x = (int)(src.x * fl);
+ res.y = (int)(src.y * fl);
+ res.z = (int)(src.z * fl);
+ res.w = (int)(src.w * fl);
+}
+
+FORCEINLINE IntVector4D IntVector4D::operator*(float fl) const
+{
+ IntVector4D res;
+ IntVector4DMultiply( *this, fl, res );
+ return res;
+}
+
+
+
+// =======================
+
+
+FORCEINLINE void VectorAdd( const Vector& a, const Vector& b, Vector& c )
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ c.x = a.x + b.x;
+ c.y = a.y + b.y;
+ c.z = a.z + b.z;
+}
+
+FORCEINLINE void VectorSubtract( const Vector& a, const Vector& b, Vector& c )
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ c.x = a.x - b.x;
+ c.y = a.y - b.y;
+ c.z = a.z - b.z;
+}
+
+FORCEINLINE void VectorMultiply( const Vector& a, vec_t b, Vector& c )
+{
+ CHECK_VALID(a);
+ Assert( IsFinite(b) );
+ c.x = a.x * b;
+ c.y = a.y * b;
+ c.z = a.z * b;
+}
+
+FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& c )
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ c.x = a.x * b.x;
+ c.y = a.y * b.y;
+ c.z = a.z * b.z;
+}
+
+// for backwards compatability
+inline void VectorScale ( const Vector& in, vec_t scale, Vector& result )
+{
+ VectorMultiply( in, scale, result );
+}
+
+
+FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& c )
+{
+ CHECK_VALID(a);
+ Assert( b != 0.0f );
+ vec_t oob = 1.0f / b;
+ c.x = a.x * oob;
+ c.y = a.y * oob;
+ c.z = a.z * oob;
+}
+
+FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& c )
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ Assert( (b.x != 0.0f) && (b.y != 0.0f) && (b.z != 0.0f) );
+ c.x = a.x / b.x;
+ c.y = a.y / b.y;
+ c.z = a.z / b.z;
+}
+
+// FIXME: Remove
+// For backwards compatability
+inline void Vector::MulAdd(const Vector& a, const Vector& b, float scalar)
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ x = a.x + b.x * scalar;
+ y = a.y + b.y * scalar;
+ z = a.z + b.z * scalar;
+}
+
+inline void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest )
+{
+ CHECK_VALID(src1);
+ CHECK_VALID(src2);
+ dest.x = src1.x + (src2.x - src1.x) * t;
+ dest.y = src1.y + (src2.y - src1.y) * t;
+ dest.z = src1.z + (src2.z - src1.z) * t;
+}
+
+inline Vector VectorLerp(const Vector& src1, const Vector& src2, vec_t t )
+{
+ Vector result;
+ VectorLerp( src1, src2, t, result );
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// Temporary storage for vector results so const Vector& results can be returned
+//-----------------------------------------------------------------------------
+inline Vector &AllocTempVector()
+{
+ static Vector s_vecTemp[128];
+ static CInterlockedInt s_nIndex;
+
+ int nIndex;
+ for (;;)
+ {
+ int nOldIndex = s_nIndex;
+ nIndex = ( (nOldIndex + 0x10001) & 0x7F );
+
+ if ( s_nIndex.AssignIf( nOldIndex, nIndex ) )
+ {
+ break;
+ }
+ ThreadPause();
+ }
+ return s_vecTemp[nIndex & 0xffff];
+}
+
+
+
+//-----------------------------------------------------------------------------
+// dot, cross
+//-----------------------------------------------------------------------------
+FORCEINLINE vec_t DotProduct(const Vector& a, const Vector& b)
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ return( a.x*b.x + a.y*b.y + a.z*b.z );
+}
+
+// for backwards compatability
+inline vec_t Vector::Dot( const Vector& vOther ) const
+{
+ CHECK_VALID(vOther);
+ return DotProduct( *this, vOther );
+}
+
+inline int Vector::LargestComponent() const
+{
+ float flAbsx = fabs(x);
+ float flAbsy = fabs(y);
+ float flAbsz = fabs(z);
+ if ( flAbsx > flAbsy )
+ {
+ if ( flAbsx > flAbsz )
+ return X_INDEX;
+ return Z_INDEX;
+ }
+ if ( flAbsy > flAbsz )
+ return Y_INDEX;
+ return Z_INDEX;
+}
+
+inline void CrossProduct(const Vector& a, const Vector& b, Vector& result )
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ Assert( &a != &result );
+ Assert( &b != &result );
+ result.x = a.y*b.z - a.z*b.y;
+ result.y = a.z*b.x - a.x*b.z;
+ result.z = a.x*b.y - a.y*b.x;
+}
+
+inline vec_t DotProductAbs( const Vector &v0, const Vector &v1 )
+{
+ CHECK_VALID(v0);
+ CHECK_VALID(v1);
+ return FloatMakePositive(v0.x*v1.x) + FloatMakePositive(v0.y*v1.y) + FloatMakePositive(v0.z*v1.z);
+}
+
+inline vec_t DotProductAbs( const Vector &v0, const float *v1 )
+{
+ return FloatMakePositive(v0.x * v1[0]) + FloatMakePositive(v0.y * v1[1]) + FloatMakePositive(v0.z * v1[2]);
+}
+
+//-----------------------------------------------------------------------------
+// length
+//-----------------------------------------------------------------------------
+
+inline vec_t VectorLength( const Vector& v )
+{
+ CHECK_VALID(v);
+ return (vec_t)FastSqrt(v.x*v.x + v.y*v.y + v.z*v.z);
+}
+
+
+inline vec_t Vector::Length(void) const
+{
+ CHECK_VALID(*this);
+ return VectorLength( *this );
+}
+
+
+//-----------------------------------------------------------------------------
+// Normalization
+//-----------------------------------------------------------------------------
+
+/*
+// FIXME: Can't use until we're un-macroed in mathlib.h
+inline vec_t VectorNormalize( Vector& v )
+{
+ Assert( v.IsValid() );
+ vec_t l = v.Length();
+ if (l != 0.0f)
+ {
+ v /= l;
+ }
+ else
+ {
+ // FIXME:
+ // Just copying the existing implemenation; shouldn't res.z == 0?
+ v.x = v.y = 0.0f; v.z = 1.0f;
+ }
+ return l;
+}
+*/
+
+
+// check a point against a box
+bool Vector::WithinAABox( Vector const &boxmin, Vector const &boxmax)
+{
+ return (
+ ( x >= boxmin.x ) && ( x <= boxmax.x) &&
+ ( y >= boxmin.y ) && ( y <= boxmax.y) &&
+ ( z >= boxmin.z ) && ( z <= boxmax.z)
+ );
+}
+
+//-----------------------------------------------------------------------------
+// Get the distance from this vector to the other one
+//-----------------------------------------------------------------------------
+inline vec_t Vector::DistTo(const Vector &vOther) const
+{
+ Vector delta;
+ VectorSubtract( *this, vOther, delta );
+ return delta.Length();
+}
+
+
+//-----------------------------------------------------------------------------
+// Vector equality with tolerance
+//-----------------------------------------------------------------------------
+inline bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance )
+{
+ if (FloatMakePositive(src1.x - src2.x) > tolerance)
+ return false;
+ if (FloatMakePositive(src1.y - src2.y) > tolerance)
+ return false;
+ return (FloatMakePositive(src1.z - src2.z) <= tolerance);
+}
+
+
+//-----------------------------------------------------------------------------
+// Computes the closest point to vecTarget no farther than flMaxDist from vecStart
+//-----------------------------------------------------------------------------
+inline void ComputeClosestPoint( const Vector& vecStart, float flMaxDist, const Vector& vecTarget, Vector *pResult )
+{
+ Vector vecDelta;
+ VectorSubtract( vecTarget, vecStart, vecDelta );
+ float flDistSqr = vecDelta.LengthSqr();
+ if ( flDistSqr <= flMaxDist * flMaxDist )
+ {
+ *pResult = vecTarget;
+ }
+ else
+ {
+ vecDelta /= FastSqrt( flDistSqr );
+ VectorMA( vecStart, flMaxDist, vecDelta, *pResult );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Takes the absolute value of a vector
+//-----------------------------------------------------------------------------
+inline void VectorAbs( const Vector& src, Vector& dst )
+{
+ dst.x = FloatMakePositive(src.x);
+ dst.y = FloatMakePositive(src.y);
+ dst.z = FloatMakePositive(src.z);
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Slow methods
+//
+//-----------------------------------------------------------------------------
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+//-----------------------------------------------------------------------------
+// Returns a vector with the min or max in X, Y, and Z.
+//-----------------------------------------------------------------------------
+inline Vector Vector::Min(const Vector &vOther) const
+{
+ return Vector(x < vOther.x ? x : vOther.x,
+ y < vOther.y ? y : vOther.y,
+ z < vOther.z ? z : vOther.z);
+}
+
+inline Vector Vector::Max(const Vector &vOther) const
+{
+ return Vector(x > vOther.x ? x : vOther.x,
+ y > vOther.y ? y : vOther.y,
+ z > vOther.z ? z : vOther.z);
+}
+
+
+//-----------------------------------------------------------------------------
+// arithmetic operations
+//-----------------------------------------------------------------------------
+
+inline Vector Vector::operator-(void) const
+{
+ return Vector(-x,-y,-z);
+}
+
+inline Vector Vector::operator+(const Vector& v) const
+{
+ Vector res;
+ VectorAdd( *this, v, res );
+ return res;
+}
+
+inline Vector Vector::operator-(const Vector& v) const
+{
+ Vector res;
+ VectorSubtract( *this, v, res );
+ return res;
+}
+
+inline Vector Vector::operator*(float fl) const
+{
+ Vector res;
+ VectorMultiply( *this, fl, res );
+ return res;
+}
+
+inline Vector Vector::operator*(const Vector& v) const
+{
+ Vector res;
+ VectorMultiply( *this, v, res );
+ return res;
+}
+
+inline Vector Vector::operator/(float fl) const
+{
+ Vector res;
+ VectorDivide( *this, fl, res );
+ return res;
+}
+
+inline Vector Vector::operator/(const Vector& v) const
+{
+ Vector res;
+ VectorDivide( *this, v, res );
+ return res;
+}
+
+inline Vector operator*(float fl, const Vector& v)
+{
+ return v * fl;
+}
+
+//-----------------------------------------------------------------------------
+// cross product
+//-----------------------------------------------------------------------------
+
+inline Vector Vector::Cross(const Vector& vOther) const
+{
+ Vector res;
+ CrossProduct( *this, vOther, res );
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// 2D
+//-----------------------------------------------------------------------------
+
+inline vec_t Vector::Length2D(void) const
+{
+ return (vec_t)FastSqrt(x*x + y*y);
+}
+
+inline vec_t Vector::Length2DSqr(void) const
+{
+ return (x*x + y*y);
+}
+
+inline Vector CrossProduct(const Vector& a, const Vector& b)
+{
+ return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x );
+}
+
+inline void VectorMin( const Vector &a, const Vector &b, Vector &result )
+{
+ result.x = fpmin(a.x, b.x);
+ result.y = fpmin(a.y, b.y);
+ result.z = fpmin(a.z, b.z);
+}
+
+inline void VectorMax( const Vector &a, const Vector &b, Vector &result )
+{
+ result.x = fpmax(a.x, b.x);
+ result.y = fpmax(a.y, b.y);
+ result.z = fpmax(a.z, b.z);
+}
+
+// and when you want to return the vector rather than cause a LHS with it...
+inline Vector VectorMin( const Vector &a, const Vector &b )
+{
+ return Vector( fpmin(a.x, b.x), fpmin(a.y, b.y), fpmin(a.z, b.z) );
+}
+
+inline Vector VectorMax( const Vector &a, const Vector &b )
+{
+ return Vector( fpmax(a.x, b.x), fpmax(a.y, b.y), fpmax(a.z, b.z) );
+}
+
+inline float ComputeVolume( const Vector &vecMins, const Vector &vecMaxs )
+{
+ Vector vecDelta;
+ VectorSubtract( vecMaxs, vecMins, vecDelta );
+ return DotProduct( vecDelta, vecDelta );
+}
+
+// Get a random vector.
+inline Vector RandomVector( float minVal, float maxVal )
+{
+ Vector random;
+ random.Random( minVal, maxVal );
+ return random;
+}
+
+#endif //slow
+
+//-----------------------------------------------------------------------------
+// Helper debugging stuff....
+//-----------------------------------------------------------------------------
+
+inline bool operator==( float const* f, const Vector& v )
+{
+ // AIIIEEEE!!!!
+ Assert(0);
+ return false;
+}
+
+inline bool operator==( const Vector& v, float const* f )
+{
+ // AIIIEEEE!!!!
+ Assert(0);
+ return false;
+}
+
+inline bool operator!=( float const* f, const Vector& v )
+{
+ // AIIIEEEE!!!!
+ Assert(0);
+ return false;
+}
+
+inline bool operator!=( const Vector& v, float const* f )
+{
+ // AIIIEEEE!!!!
+ Assert(0);
+ return false;
+}
+
+
+// return a vector perpendicular to another, with smooth variation. The difference between this and
+// something like VectorVectors is that there are now discontinuities. _unlike_ VectorVectors,
+// you won't get an "u
+void VectorPerpendicularToVector( Vector const &in, Vector *pvecOut );
+
+//-----------------------------------------------------------------------------
+// AngularImpulse
+//-----------------------------------------------------------------------------
+// AngularImpulse are exponetial maps (an axis scaled by a "twist" angle in degrees)
+typedef Vector AngularImpulse;
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+inline AngularImpulse RandomAngularImpulse( float minVal, float maxVal )
+{
+ AngularImpulse angImp;
+ angImp.Random( minVal, maxVal );
+ return angImp;
+}
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Quaternion
+//-----------------------------------------------------------------------------
+
+class RadianEuler;
+
+class Quaternion // same data-layout as engine's vec4_t,
+{ // which is a vec_t[4]
+public:
+ inline Quaternion(void) {
+
+ // Initialize to NAN to catch errors
+#ifdef _DEBUG
+#ifdef VECTOR_PARANOIA
+ x = y = z = w = VEC_T_NAN;
+#endif
+#endif
+ }
+ inline Quaternion(vec_t ix, vec_t iy, vec_t iz, vec_t iw) : x(ix), y(iy), z(iz), w(iw) { }
+ inline Quaternion(RadianEuler const &angle); // evil auto type promotion!!!
+
+ inline void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f, vec_t iw=0.0f) { x = ix; y = iy; z = iz; w = iw; }
+
+ bool IsValid() const;
+ void Invalidate();
+
+ bool operator==( const Quaternion &src ) const;
+ bool operator!=( const Quaternion &src ) const;
+
+ inline Quaternion Conjugate() const { return Quaternion( -x, -y, -z, w ); }
+
+ vec_t* Base() { return (vec_t*)this; }
+ const vec_t* Base() const { return (vec_t*)this; }
+
+ // convenience for debugging
+ inline void Print() const;
+
+ // array access...
+ vec_t operator[](int i) const;
+ vec_t& operator[](int i);
+
+ vec_t x, y, z, w;
+};
+
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+inline vec_t& Quaternion::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 4) );
+ return ((vec_t*)this)[i];
+}
+
+inline vec_t Quaternion::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 4) );
+ return ((vec_t*)this)[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// Equality test
+//-----------------------------------------------------------------------------
+inline bool Quaternion::operator==( const Quaternion &src ) const
+{
+ return ( x == src.x ) && ( y == src.y ) && ( z == src.z ) && ( w == src.w );
+}
+
+inline bool Quaternion::operator!=( const Quaternion &src ) const
+{
+ return !operator==( src );
+}
+
+
+//-----------------------------------------------------------------------------
+// Debugging only
+//-----------------------------------------------------------------------------
+void Quaternion::Print() const
+{
+#ifndef _CERT
+ Msg("q{ %.3fi + %.3fj + %.3fk + %.3f }", x, y, z, w );
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Quaternion equality with tolerance
+//-----------------------------------------------------------------------------
+inline bool QuaternionsAreEqual( const Quaternion& src1, const Quaternion& src2, float tolerance )
+{
+ if (FloatMakePositive(src1.x - src2.x) > tolerance)
+ return false;
+ if (FloatMakePositive(src1.y - src2.y) > tolerance)
+ return false;
+ if (FloatMakePositive(src1.z - src2.z) > tolerance)
+ return false;
+ return (FloatMakePositive(src1.w - src2.w) <= tolerance);
+}
+
+
+//-----------------------------------------------------------------------------
+// Here's where we add all those lovely SSE optimized routines
+//-----------------------------------------------------------------------------
+class ALIGN16 QuaternionAligned : public Quaternion
+{
+public:
+ inline QuaternionAligned(void) {};
+ inline QuaternionAligned(vec_t X, vec_t Y, vec_t Z, vec_t W)
+ {
+ Init(X,Y,Z,W);
+ }
+
+ operator Quaternion * () { return this; }
+ operator const Quaternion * () { return this; }
+
+#ifdef VECTOR_NO_SLOW_OPERATIONS
+
+private:
+ // No copy constructors allowed if we're in optimal mode
+ QuaternionAligned(const QuaternionAligned& vOther);
+ QuaternionAligned(const Quaternion &vOther);
+
+#else
+public:
+ explicit QuaternionAligned(const Quaternion &vOther)
+ {
+ Init(vOther.x, vOther.y, vOther.z, vOther.w);
+ }
+
+ QuaternionAligned& operator=(const Quaternion &vOther)
+ {
+ Init(vOther.x, vOther.y, vOther.z, vOther.w);
+ return *this;
+ }
+
+ QuaternionAligned& operator=(const QuaternionAligned &vOther)
+ {
+ // we know we're aligned, so use simd
+ // we can't use the convenient abstract interface coz it gets declared later
+#ifdef _X360
+ XMStoreVector4A(Base(), XMLoadVector4A(vOther.Base()));
+#elif _WIN32
+ _mm_store_ps(Base(), _mm_load_ps( vOther.Base() ));
+#else
+ Init(vOther.x, vOther.y, vOther.z, vOther.w);
+#endif
+ return *this;
+ }
+
+#endif
+
+#if !defined(NO_MALLOC_OVERRIDE)
+ void* operator new[] ( size_t nSize)
+ {
+ return MemAlloc_AllocAligned(nSize, 16);
+ }
+
+ void* operator new[] ( size_t nSize, const char *pFileName, int nLine)
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+
+ void* operator new[] ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine)
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+
+ void operator delete[] ( void* p)
+ {
+ MemAlloc_FreeAligned(p);
+ }
+
+ void operator delete[] ( void* p, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+
+ void operator delete[] ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+
+ // please don't allocate a single quaternion...
+ void* operator new ( size_t nSize )
+ {
+ return MemAlloc_AllocAligned(nSize, 16);
+ }
+ void* operator new ( size_t nSize, const char *pFileName, int nLine )
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+ void* operator new ( size_t nSize, int /*nBlockUse*/, const char *pFileName, int nLine )
+ {
+ return MemAlloc_AllocAlignedFileLine(nSize, 16, pFileName, nLine);
+ }
+ void operator delete ( void* p)
+ {
+ MemAlloc_FreeAligned(p);
+ }
+
+ void operator delete ( void* p, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+
+ void operator delete ( void* p, int /*nBlockUse*/, const char *pFileName, int nLine)
+ {
+ MemAlloc_FreeAligned(p, pFileName, nLine);
+ }
+#endif
+} ALIGN16_POST;
+
+//-----------------------------------------------------------------------------
+// Radian Euler angle aligned to axis (NOT ROLL/PITCH/YAW)
+//-----------------------------------------------------------------------------
+class QAngle;
+class RadianEuler
+{
+public:
+ inline RadianEuler(void) { }
+ inline RadianEuler(vec_t X, vec_t Y, vec_t Z) { x = X; y = Y; z = Z; }
+ inline RadianEuler(Quaternion const &q); // evil auto type promotion!!!
+ inline RadianEuler(QAngle const &angles); // evil auto type promotion!!!
+
+ // Initialization
+ inline void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f) { x = ix; y = iy; z = iz; }
+
+ // conversion to qangle
+ QAngle ToQAngle( void ) const;
+ bool IsValid() const;
+ void Invalidate();
+
+ inline vec_t *Base() { return &x; }
+ inline const vec_t *Base() const { return &x; }
+
+ // array access...
+ vec_t operator[](int i) const;
+ vec_t& operator[](int i);
+
+ vec_t x, y, z;
+};
+
+
+extern void AngleQuaternion( RadianEuler const &angles, Quaternion &qt );
+extern void QuaternionAngles( Quaternion const &q, RadianEuler &angles );
+inline Quaternion::Quaternion(RadianEuler const &angle)
+{
+ AngleQuaternion( angle, *this );
+}
+
+inline bool Quaternion::IsValid() const
+{
+ return IsFinite(x) && IsFinite(y) && IsFinite(z) && IsFinite(w);
+}
+
+inline void Quaternion::Invalidate()
+{
+//#ifdef _DEBUG
+//#ifdef VECTOR_PARANOIA
+ x = y = z = w = VEC_T_NAN;
+//#endif
+//#endif
+}
+
+inline RadianEuler::RadianEuler(Quaternion const &q)
+{
+ QuaternionAngles( q, *this );
+}
+
+inline void VectorCopy( RadianEuler const& src, RadianEuler &dst )
+{
+ CHECK_VALID(src);
+ dst.x = src.x;
+ dst.y = src.y;
+ dst.z = src.z;
+}
+
+inline void VectorScale( RadianEuler const& src, float b, RadianEuler &dst )
+{
+ CHECK_VALID(src);
+ Assert( IsFinite(b) );
+ dst.x = src.x * b;
+ dst.y = src.y * b;
+ dst.z = src.z * b;
+}
+
+inline bool RadianEuler::IsValid() const
+{
+ return IsFinite(x) && IsFinite(y) && IsFinite(z);
+}
+
+inline void RadianEuler::Invalidate()
+{
+//#ifdef _DEBUG
+//#ifdef VECTOR_PARANOIA
+ x = y = z = VEC_T_NAN;
+//#endif
+//#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+inline vec_t& RadianEuler::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+}
+
+inline vec_t RadianEuler::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// Degree Euler QAngle pitch, yaw, roll
+//-----------------------------------------------------------------------------
+class QAngleByValue;
+
+class QAngle
+{
+public:
+ // Members
+ vec_t x, y, z;
+
+ // Construction/destruction
+ QAngle(void);
+ QAngle(vec_t X, vec_t Y, vec_t Z);
+#ifndef _PS3
+// QAngle(RadianEuler const &angles); // evil auto type promotion!!!
+#endif
+
+ // Allow pass-by-value
+ operator QAngleByValue &() { return *((QAngleByValue *)(this)); }
+ operator const QAngleByValue &() const { return *((const QAngleByValue *)(this)); }
+
+ // Initialization
+ void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f);
+ void Random( vec_t minVal, vec_t maxVal );
+
+ // Got any nasty NAN's?
+ bool IsValid() const;
+ void Invalidate();
+
+ // array access...
+ vec_t operator[](int i) const;
+ vec_t& operator[](int i);
+
+ // Base address...
+ vec_t* Base();
+ vec_t const* Base() const;
+
+ // equality
+ bool operator==(const QAngle& v) const;
+ bool operator!=(const QAngle& v) const;
+
+ // arithmetic operations
+ QAngle& operator+=(const QAngle &v);
+ QAngle& operator-=(const QAngle &v);
+ QAngle& operator*=(float s);
+ QAngle& operator/=(float s);
+
+ // Get the vector's magnitude.
+ vec_t Length() const;
+ vec_t LengthSqr() const;
+
+ // negate the QAngle components
+ //void Negate();
+
+ // No assignment operators either...
+ QAngle& operator=( const QAngle& src );
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+ // copy constructors
+
+ // arithmetic operations
+ QAngle operator-(void) const;
+
+ QAngle operator+(const QAngle& v) const;
+ QAngle operator-(const QAngle& v) const;
+ QAngle operator*(float fl) const;
+ QAngle operator/(float fl) const;
+#else
+
+private:
+ // No copy constructors allowed if we're in optimal mode
+ QAngle(const QAngle& vOther);
+
+#endif
+};
+
+//-----------------------------------------------------------------------------
+// Allows us to specifically pass the vector by value when we need to
+//-----------------------------------------------------------------------------
+class QAngleByValue : public QAngle
+{
+public:
+ // Construction/destruction:
+ QAngleByValue(void) : QAngle() {}
+ QAngleByValue(vec_t X, vec_t Y, vec_t Z) : QAngle( X, Y, Z ) {}
+ QAngleByValue(const QAngleByValue& vOther) { *this = vOther; }
+};
+
+
+inline void VectorAdd( const QAngle& a, const QAngle& b, QAngle& result )
+{
+ CHECK_VALID(a);
+ CHECK_VALID(b);
+ result.x = a.x + b.x;
+ result.y = a.y + b.y;
+ result.z = a.z + b.z;
+}
+
+inline void VectorMA( const QAngle &start, float scale, const QAngle &direction, QAngle &dest )
+{
+ CHECK_VALID(start);
+ CHECK_VALID(direction);
+ dest.x = start.x + scale * direction.x;
+ dest.y = start.y + scale * direction.y;
+ dest.z = start.z + scale * direction.z;
+}
+
+
+//-----------------------------------------------------------------------------
+// constructors
+//-----------------------------------------------------------------------------
+inline QAngle::QAngle(void)
+{
+#ifdef _DEBUG
+#ifdef VECTOR_PARANOIA
+ // Initialize to NAN to catch errors
+ x = y = z = VEC_T_NAN;
+#endif
+#endif
+}
+
+inline QAngle::QAngle(vec_t X, vec_t Y, vec_t Z)
+{
+ x = X; y = Y; z = Z;
+ CHECK_VALID(*this);
+}
+
+
+//-----------------------------------------------------------------------------
+// initialization
+//-----------------------------------------------------------------------------
+inline void QAngle::Init( vec_t ix, vec_t iy, vec_t iz )
+{
+ x = ix; y = iy; z = iz;
+ CHECK_VALID(*this);
+}
+
+inline void QAngle::Random( vec_t minVal, vec_t maxVal )
+{
+ x = RandomFloat( minVal, maxVal );
+ y = RandomFloat( minVal, maxVal );
+ z = RandomFloat( minVal, maxVal );
+ CHECK_VALID(*this);
+}
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+inline QAngle RandomAngle( float minVal, float maxVal )
+{
+ Vector random;
+ random.Random( minVal, maxVal );
+ QAngle ret( random.x, random.y, random.z );
+ return ret;
+}
+
+#endif
+
+inline RadianEuler::RadianEuler(QAngle const &angles)
+{
+ Init(
+ angles.z * 3.14159265358979323846f / 180.f,
+ angles.x * 3.14159265358979323846f / 180.f,
+ angles.y * 3.14159265358979323846f / 180.f );
+}
+
+
+
+
+inline QAngle RadianEuler::ToQAngle( void) const
+{
+ return QAngle(
+ y * 180.f / 3.14159265358979323846f,
+ z * 180.f / 3.14159265358979323846f,
+ x * 180.f / 3.14159265358979323846f );
+}
+
+//-----------------------------------------------------------------------------
+// assignment
+//-----------------------------------------------------------------------------
+inline QAngle& QAngle::operator=(const QAngle &vOther)
+{
+ CHECK_VALID(vOther);
+ x=vOther.x; y=vOther.y; z=vOther.z;
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+inline vec_t& QAngle::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+}
+
+inline vec_t QAngle::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 3) );
+ return ((vec_t*)this)[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// Base address...
+//-----------------------------------------------------------------------------
+inline vec_t* QAngle::Base()
+{
+ return (vec_t*)this;
+}
+
+inline vec_t const* QAngle::Base() const
+{
+ return (vec_t const*)this;
+}
+
+
+//-----------------------------------------------------------------------------
+// IsValid?
+//-----------------------------------------------------------------------------
+inline bool QAngle::IsValid() const
+{
+ return IsFinite(x) && IsFinite(y) && IsFinite(z);
+}
+
+//-----------------------------------------------------------------------------
+// Invalidate
+//-----------------------------------------------------------------------------
+
+inline void QAngle::Invalidate()
+{
+//#ifdef _DEBUG
+//#ifdef VECTOR_PARANOIA
+ x = y = z = VEC_T_NAN;
+//#endif
+//#endif
+}
+
+//-----------------------------------------------------------------------------
+// comparison
+//-----------------------------------------------------------------------------
+inline bool QAngle::operator==( const QAngle& src ) const
+{
+ CHECK_VALID(src);
+ CHECK_VALID(*this);
+ return (src.x == x) && (src.y == y) && (src.z == z);
+}
+
+inline bool QAngle::operator!=( const QAngle& src ) const
+{
+ CHECK_VALID(src);
+ CHECK_VALID(*this);
+ return (src.x != x) || (src.y != y) || (src.z != z);
+}
+
+
+//-----------------------------------------------------------------------------
+// Copy
+//-----------------------------------------------------------------------------
+inline void VectorCopy( const QAngle& src, QAngle& dst )
+{
+ CHECK_VALID(src);
+ dst.x = src.x;
+ dst.y = src.y;
+ dst.z = src.z;
+}
+
+
+//-----------------------------------------------------------------------------
+// standard math operations
+//-----------------------------------------------------------------------------
+inline QAngle& QAngle::operator+=(const QAngle& v)
+{
+ CHECK_VALID(*this);
+ CHECK_VALID(v);
+ x+=v.x; y+=v.y; z += v.z;
+ return *this;
+}
+
+inline QAngle& QAngle::operator-=(const QAngle& v)
+{
+ CHECK_VALID(*this);
+ CHECK_VALID(v);
+ x-=v.x; y-=v.y; z -= v.z;
+ return *this;
+}
+
+inline QAngle& QAngle::operator*=(float fl)
+{
+ x *= fl;
+ y *= fl;
+ z *= fl;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+inline QAngle& QAngle::operator/=(float fl)
+{
+ Assert( fl != 0.0f );
+ float oofl = 1.0f / fl;
+ x *= oofl;
+ y *= oofl;
+ z *= oofl;
+ CHECK_VALID(*this);
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+// length
+//-----------------------------------------------------------------------------
+inline vec_t QAngle::Length( ) const
+{
+ CHECK_VALID(*this);
+ return (vec_t)FastSqrt( LengthSqr( ) );
+}
+
+
+inline vec_t QAngle::LengthSqr( ) const
+{
+ CHECK_VALID(*this);
+ return x * x + y * y + z * z;
+}
+
+
+//-----------------------------------------------------------------------------
+// Vector equality with tolerance
+//-----------------------------------------------------------------------------
+inline bool QAnglesAreEqual( const QAngle& src1, const QAngle& src2, float tolerance = 0.0f )
+{
+ if (FloatMakePositive(src1.x - src2.x) > tolerance)
+ return false;
+ if (FloatMakePositive(src1.y - src2.y) > tolerance)
+ return false;
+ return (FloatMakePositive(src1.z - src2.z) <= tolerance);
+}
+
+
+//-----------------------------------------------------------------------------
+// arithmetic operations (SLOW!!)
+//-----------------------------------------------------------------------------
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+inline QAngle QAngle::operator-(void) const
+{
+ QAngle ret(-x,-y,-z);
+ return ret;
+}
+
+inline QAngle QAngle::operator+(const QAngle& v) const
+{
+ QAngle res;
+ res.x = x + v.x;
+ res.y = y + v.y;
+ res.z = z + v.z;
+ return res;
+}
+
+inline QAngle QAngle::operator-(const QAngle& v) const
+{
+ QAngle res;
+ res.x = x - v.x;
+ res.y = y - v.y;
+ res.z = z - v.z;
+ return res;
+}
+
+inline QAngle QAngle::operator*(float fl) const
+{
+ QAngle res;
+ res.x = x * fl;
+ res.y = y * fl;
+ res.z = z * fl;
+ return res;
+}
+
+inline QAngle QAngle::operator/(float fl) const
+{
+ QAngle res;
+ res.x = x / fl;
+ res.y = y / fl;
+ res.z = z / fl;
+ return res;
+}
+
+inline QAngle operator*(float fl, const QAngle& v)
+{
+ QAngle ret( v * fl );
+ return ret;
+}
+
+#endif // VECTOR_NO_SLOW_OPERATIONS
+
+
+//-----------------------------------------------------------------------------
+// NOTE: These are not completely correct. The representations are not equivalent
+// unless the QAngle represents a rotational impulse along a coordinate axis (x,y,z)
+inline void QAngleToAngularImpulse( const QAngle &angles, AngularImpulse &impulse )
+{
+ impulse.x = angles.z;
+ impulse.y = angles.x;
+ impulse.z = angles.y;
+}
+
+inline void AngularImpulseToQAngle( const AngularImpulse &impulse, QAngle &angles )
+{
+ angles.x = impulse.y;
+ angles.y = impulse.z;
+ angles.z = impulse.x;
+}
+
+#if !defined( _X360 ) && !defined( _PS3 )
+
+FORCEINLINE vec_t InvRSquared( const float* v )
+{
+ return 1.0 / MAX( 1.0, v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
+}
+
+FORCEINLINE vec_t InvRSquared( const Vector &v )
+{
+ return InvRSquared( v.Base() );
+}
+
+#else
+
+// call directly
+FORCEINLINE float _VMX_InvRSquared( const Vector &v )
+{
+#if !defined (_PS3)
+ XMVECTOR xmV = XMVector3ReciprocalLength( XMLoadVector3( v.Base() ) );
+ xmV = XMVector3Dot( xmV, xmV );
+ return xmV.x;
+#else //!_PS3
+ vector_float_union vRet;
+ vec_float4 v0, v1, vIn, vOut;
+ vector unsigned char permMask;
+ v0 = vec_ld( 0, v.Base() );
+ permMask = vec_lvsl( 0, v.Base() );
+ v1 = vec_ld( 11, v.Base() );
+ vIn = vec_perm(v0, v1, permMask);
+ vOut = vec_madd( vIn, vIn, _VEC_ZEROF );
+ vec_float4 vTmp = vec_sld( vIn, vIn, 4 );
+ vec_float4 vTmp2 = vec_sld( vIn, vIn, 8 );
+ vOut = vec_madd( vTmp, vTmp, vOut );
+ vOut = vec_madd( vTmp2, vTmp2, vOut );
+ vOut = vec_re( vec_add(vOut, _VEC_EPSILONF) );
+ vec_st(vOut,0,&vRet.vf);
+ float ret = vRet.f[0];
+ return ret;
+#endif //!_PS3
+}
+
+#define InvRSquared(x) _VMX_InvRSquared(x)
+
+#endif // _X360
+
+#if !defined( _X360 ) && !defined( _PS3 )
+
+// FIXME: Change this back to a #define once we get rid of the vec_t version
+float VectorNormalize( Vector& v );
+
+// FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s
+FORCEINLINE float VectorNormalize( float * v )
+{
+ return VectorNormalize(*(reinterpret_cast<Vector *>(v)));
+}
+
+#else
+#if !defined( _PS3 )
+// modified version of Microsoft's XMVector3Length
+// microsoft's version will return INF for very small vectors
+// e.g. Vector vTest(7.98555446e-20,-6.85012984e-21,0); VectorNormalize( vTest );
+// so we clamp to epsilon instead of checking for zero
+XMFINLINE XMVECTOR XMVector3Length_Fixed
+(
+ FXMVECTOR V
+ )
+{
+ // Returns a QNaN on infinite vectors.
+ static CONST XMVECTOR g_fl4SmallVectorEpsilon = {1e-24f,1e-24f,1e-24f,1e-24f};
+
+ XMVECTOR D;
+ XMVECTOR Rsq;
+ XMVECTOR Rcp;
+ XMVECTOR Zero;
+ XMVECTOR RT;
+ XMVECTOR Result;
+ XMVECTOR Length;
+ XMVECTOR H;
+
+ H = __vspltisw(1);
+ D = __vmsum3fp(V, V);
+ H = __vcfsx(H, 1);
+ Rsq = __vrsqrtefp(D);
+ RT = __vmulfp(D, H);
+ Rcp = __vmulfp(Rsq, Rsq);
+ H = __vnmsubfp(RT, Rcp, H);
+ Rsq = __vmaddfp(Rsq, H, Rsq);
+ Zero = __vspltisw(0);
+ Result = __vcmpgefp( g_fl4SmallVectorEpsilon, D );
+ Length = __vmulfp(D, Rsq);
+ Result = __vsel(Length, Zero, Result);
+
+ return Result;
+}
+#endif
+
+// call directly
+FORCEINLINE float _VMX_VectorNormalize( Vector &vec )
+{
+#if !defined _PS3
+ float mag = XMVector3Length_Fixed( XMLoadVector3( vec.Base() ) ).x;
+ float den = 1.f / (mag + FLT_EPSILON );
+ vec.x *= den;
+ vec.y *= den;
+ vec.z *= den;
+ return mag;
+#else // !_PS3
+ vec_float4 vIn;
+ vec_float4 v0, v1;
+ vector unsigned char permMask;
+ v0 = vec_ld( 0, vec.Base() );
+ permMask = vec_lvsl( 0, vec.Base() );
+ v1 = vec_ld( 11, vec.Base() );
+ vIn = vec_perm(v0, v1, permMask);
+ float mag = vmathV3Length((VmathVector3 *)&vIn);
+ float den = 1.f / (mag + FLT_EPSILON );
+ vec.x *= den;
+ vec.y *= den;
+ vec.z *= den;
+ return mag;
+#endif // !_PS3
+}
+// FIXME: Change this back to a #define once we get rid of the vec_t version
+FORCEINLINE float VectorNormalize( Vector& v )
+{
+ return _VMX_VectorNormalize( v );
+}
+// FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s
+FORCEINLINE float VectorNormalize( float *pV )
+{
+ return _VMX_VectorNormalize(*(reinterpret_cast<Vector*>(pV)));
+}
+
+#endif // _X360
+
+#if !defined( _X360 ) && !defined( _PS3 )
+FORCEINLINE void VectorNormalizeFast (Vector& vec)
+{
+ float ool = FastRSqrt( FLT_EPSILON + vec.x * vec.x + vec.y * vec.y + vec.z * vec.z );
+
+ vec.x *= ool;
+ vec.y *= ool;
+ vec.z *= ool;
+}
+#else
+
+// call directly
+FORCEINLINE void VectorNormalizeFast( Vector &vec )
+{
+#if !defined (_PS3)
+ XMVECTOR xmV = XMVector3LengthEst( XMLoadVector3( vec.Base() ) );
+ float den = 1.f / (xmV.x + FLT_EPSILON);
+ vec.x *= den;
+ vec.y *= den;
+ vec.z *= den;
+#else // !_PS3
+ vector_float_union vVec;
+
+ vec_float4 vIn, vOut, vOOLen, vDot;
+
+ // load
+ vec_float4 v0, v1;
+ vector unsigned char permMask;
+ v0 = vec_ld( 0, vec.Base() );
+ permMask = vec_lvsl( 0, vec.Base() );
+ v1 = vec_ld( 11, vec.Base() );
+ vIn = vec_perm(v0, v1, permMask);
+
+ // vec.vec
+ vOut = vec_madd( vIn, vIn, _VEC_ZEROF );
+ vec_float4 vTmp = vec_sld( vIn, vIn, 4 );
+ vec_float4 vTmp2 = vec_sld( vIn, vIn, 8 );
+ vOut = vec_madd( vTmp, vTmp, vOut );
+ vOut = vec_madd( vTmp2, vTmp2, vOut );
+
+ // splat dot to all
+ vDot = vec_splat( vOut, 0 );
+
+ vOOLen = vec_rsqrte( vec_add( vDot, _VEC_EPSILONF ) );
+
+ // vec * 1.0/sqrt(vec.vec)
+ vOut = vec_madd( vIn, vOOLen, _VEC_ZEROF );
+
+ // store
+ vec_st(vOut,0,&vVec.vf);
+
+ // store vec
+ vec.x = vVec.f[0];
+ vec.y = vVec.f[1];
+ vec.z = vVec.f[2];
+
+#endif // !_PS3
+}
+
+#endif // _X360
+
+inline vec_t Vector::NormalizeInPlace()
+{
+ return VectorNormalize( *this );
+}
+
+inline Vector Vector::Normalized() const
+{
+ Vector norm = *this;
+ VectorNormalize( norm );
+ return norm;
+}
+
+inline bool Vector::IsLengthGreaterThan( float val ) const
+{
+ return LengthSqr() > val*val;
+}
+
+inline bool Vector::IsLengthLessThan( float val ) const
+{
+ return LengthSqr() < val*val;
+}
+
+#endif
+
diff --git a/external/vpc/public/mathlib/vector2d.h b/external/vpc/public/mathlib/vector2d.h
new file mode 100644
index 0000000..30fcc86
--- /dev/null
+++ b/external/vpc/public/mathlib/vector2d.h
@@ -0,0 +1,670 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef VECTOR2D_H
+#define VECTOR2D_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <math.h>
+#include <float.h>
+
+// For vec_t, put this somewhere else?
+#include "tier0/basetypes.h"
+
+// For RandomFloat()
+#include "vstdlib/random.h"
+
+#include "tier0/dbg.h"
+#include "mathlib/math_pfns.h"
+
+//=========================================================
+// 2D Vector2D
+//=========================================================
+
+class Vector2D
+{
+public:
+ // Members
+ vec_t x, y;
+
+ // Construction/destruction
+ Vector2D(void);
+ Vector2D(vec_t X, vec_t Y);
+ Vector2D(const float *pFloat);
+
+ // Initialization
+ void Init(vec_t ix=0.0f, vec_t iy=0.0f);
+
+ // Got any nasty NAN's?
+ bool IsValid() const;
+
+ // array access...
+ vec_t operator[](int i) const;
+ vec_t& operator[](int i);
+
+ // Base address...
+ vec_t* Base();
+ vec_t const* Base() const;
+
+ // Initialization methods
+ void Random( float minVal, float maxVal );
+
+ // equality
+ bool operator==(const Vector2D& v) const;
+ bool operator!=(const Vector2D& v) const;
+
+ // arithmetic operations
+ Vector2D& operator+=(const Vector2D &v);
+ Vector2D& operator-=(const Vector2D &v);
+ Vector2D& operator*=(const Vector2D &v);
+ Vector2D& operator*=(float s);
+ Vector2D& operator/=(const Vector2D &v);
+ Vector2D& operator/=(float s);
+
+ // negate the Vector2D components
+ void Negate();
+
+ // Get the Vector2D's magnitude.
+ vec_t Length() const;
+
+ // Get the Vector2D's magnitude squared.
+ vec_t LengthSqr(void) const;
+
+ // return true if this vector is (0,0) within tolerance
+ bool IsZero( float tolerance = 0.01f ) const
+ {
+ return (x > -tolerance && x < tolerance &&
+ y > -tolerance && y < tolerance);
+ }
+
+ // Normalize in place and return the old length.
+ vec_t NormalizeInPlace();
+
+ // Compare length.
+ bool IsLengthGreaterThan( float val ) const;
+ bool IsLengthLessThan( float val ) const;
+
+ // Get the distance from this Vector2D to the other one.
+ vec_t DistTo(const Vector2D &vOther) const;
+
+ // Get the distance from this Vector2D to the other one squared.
+ vec_t DistToSqr(const Vector2D &vOther) const;
+
+ // Copy
+ void CopyToArray(float* rgfl) const;
+
+ // Multiply, add, and assign to this (ie: *this = a + b * scalar). This
+ // is about 12% faster than the actual Vector2D equation (because it's done per-component
+ // rather than per-Vector2D).
+ void MulAdd(const Vector2D& a, const Vector2D& b, float scalar);
+
+ // Dot product.
+ vec_t Dot(const Vector2D& vOther) const;
+
+ // assignment
+ Vector2D& operator=(const Vector2D &vOther);
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+ // copy constructors
+ Vector2D(const Vector2D &vOther);
+
+ // arithmetic operations
+ Vector2D operator-(void) const;
+
+ Vector2D operator+(const Vector2D& v) const;
+ Vector2D operator-(const Vector2D& v) const;
+ Vector2D operator*(const Vector2D& v) const;
+ Vector2D operator/(const Vector2D& v) const;
+ Vector2D operator*(float fl) const;
+ Vector2D operator/(float fl) const;
+
+ // Cross product between two vectors.
+ Vector2D Cross(const Vector2D &vOther) const;
+
+ // Returns a Vector2D with the min or max in X, Y, and Z.
+ Vector2D Min(const Vector2D &vOther) const;
+ Vector2D Max(const Vector2D &vOther) const;
+
+#else
+
+private:
+ // No copy constructors allowed if we're in optimal mode
+ Vector2D(const Vector2D& vOther);
+#endif
+};
+
+//-----------------------------------------------------------------------------
+
+const Vector2D vec2_origin(0,0);
+const Vector2D vec2_invalid( FLT_MAX, FLT_MAX );
+
+//-----------------------------------------------------------------------------
+// Vector2D related operations
+//-----------------------------------------------------------------------------
+
+// Vector2D clear
+void Vector2DClear( Vector2D& a );
+
+// Copy
+void Vector2DCopy( const Vector2D& src, Vector2D& dst );
+
+// Vector2D arithmetic
+void Vector2DAdd( const Vector2D& a, const Vector2D& b, Vector2D& result );
+void Vector2DSubtract( const Vector2D& a, const Vector2D& b, Vector2D& result );
+void Vector2DMultiply( const Vector2D& a, vec_t b, Vector2D& result );
+void Vector2DMultiply( const Vector2D& a, const Vector2D& b, Vector2D& result );
+void Vector2DDivide( const Vector2D& a, vec_t b, Vector2D& result );
+void Vector2DDivide( const Vector2D& a, const Vector2D& b, Vector2D& result );
+void Vector2DMA( const Vector2D& start, float s, const Vector2D& dir, Vector2D& result );
+
+// Store the min or max of each of x, y, and z into the result.
+void Vector2DMin( const Vector2D &a, const Vector2D &b, Vector2D &result );
+void Vector2DMax( const Vector2D &a, const Vector2D &b, Vector2D &result );
+
+#define Vector2DExpand( v ) (v).x, (v).y
+
+// Normalization
+vec_t Vector2DNormalize( Vector2D& v );
+
+// Length
+vec_t Vector2DLength( const Vector2D& v );
+
+// Dot Product
+vec_t DotProduct2D(const Vector2D& a, const Vector2D& b);
+
+// Linearly interpolate between two vectors
+void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest );
+
+
+//-----------------------------------------------------------------------------
+//
+// Inlined Vector2D methods
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// constructors
+//-----------------------------------------------------------------------------
+
+inline Vector2D::Vector2D(void)
+{
+#ifdef _DEBUG
+ // Initialize to NAN to catch errors
+ x = y = VEC_T_NAN;
+#endif
+}
+
+inline Vector2D::Vector2D(vec_t X, vec_t Y)
+{
+ x = X; y = Y;
+ Assert( IsValid() );
+}
+
+inline Vector2D::Vector2D(const float *pFloat)
+{
+ Assert( pFloat );
+ x = pFloat[0]; y = pFloat[1];
+ Assert( IsValid() );
+}
+
+
+//-----------------------------------------------------------------------------
+// copy constructor
+//-----------------------------------------------------------------------------
+
+inline Vector2D::Vector2D(const Vector2D &vOther)
+{
+ Assert( vOther.IsValid() );
+ x = vOther.x; y = vOther.y;
+}
+
+//-----------------------------------------------------------------------------
+// initialization
+//-----------------------------------------------------------------------------
+
+inline void Vector2D::Init( vec_t ix, vec_t iy )
+{
+ x = ix; y = iy;
+ Assert( IsValid() );
+}
+
+inline void Vector2D::Random( float minVal, float maxVal )
+{
+ x = RandomFloat( minVal , maxVal );
+ y = RandomFloat( minVal , maxVal );
+}
+
+inline void Vector2DClear( Vector2D& a )
+{
+ a.x = a.y = 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+// assignment
+//-----------------------------------------------------------------------------
+
+inline Vector2D& Vector2D::operator=(const Vector2D &vOther)
+{
+ Assert( vOther.IsValid() );
+ x=vOther.x; y=vOther.y;
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+// Array access
+//-----------------------------------------------------------------------------
+
+inline vec_t& Vector2D::operator[](int i)
+{
+ Assert( (i >= 0) && (i < 2) );
+ return ((vec_t*)this)[i];
+}
+
+inline vec_t Vector2D::operator[](int i) const
+{
+ Assert( (i >= 0) && (i < 2) );
+ return ((vec_t*)this)[i];
+}
+
+//-----------------------------------------------------------------------------
+// Base address...
+//-----------------------------------------------------------------------------
+
+inline vec_t* Vector2D::Base()
+{
+ return (vec_t*)this;
+}
+
+inline vec_t const* Vector2D::Base() const
+{
+ return (vec_t const*)this;
+}
+
+//-----------------------------------------------------------------------------
+// IsValid?
+//-----------------------------------------------------------------------------
+
+inline bool Vector2D::IsValid() const
+{
+ return IsFinite(x) && IsFinite(y);
+}
+
+//-----------------------------------------------------------------------------
+// comparison
+//-----------------------------------------------------------------------------
+
+inline bool Vector2D::operator==( const Vector2D& src ) const
+{
+ Assert( src.IsValid() && IsValid() );
+ return (src.x == x) && (src.y == y);
+}
+
+inline bool Vector2D::operator!=( const Vector2D& src ) const
+{
+ Assert( src.IsValid() && IsValid() );
+ return (src.x != x) || (src.y != y);
+}
+
+
+//-----------------------------------------------------------------------------
+// Copy
+//-----------------------------------------------------------------------------
+
+inline void Vector2DCopy( const Vector2D& src, Vector2D& dst )
+{
+ Assert( src.IsValid() );
+ dst.x = src.x;
+ dst.y = src.y;
+}
+
+inline void Vector2D::CopyToArray(float* rgfl) const
+{
+ Assert( IsValid() );
+ Assert( rgfl );
+ rgfl[0] = x; rgfl[1] = y;
+}
+
+//-----------------------------------------------------------------------------
+// standard math operations
+//-----------------------------------------------------------------------------
+
+inline void Vector2D::Negate()
+{
+ Assert( IsValid() );
+ x = -x; y = -y;
+}
+
+inline Vector2D& Vector2D::operator+=(const Vector2D& v)
+{
+ Assert( IsValid() && v.IsValid() );
+ x+=v.x; y+=v.y;
+ return *this;
+}
+
+inline Vector2D& Vector2D::operator-=(const Vector2D& v)
+{
+ Assert( IsValid() && v.IsValid() );
+ x-=v.x; y-=v.y;
+ return *this;
+}
+
+inline Vector2D& Vector2D::operator*=(float fl)
+{
+ x *= fl;
+ y *= fl;
+ Assert( IsValid() );
+ return *this;
+}
+
+inline Vector2D& Vector2D::operator*=(const Vector2D& v)
+{
+ x *= v.x;
+ y *= v.y;
+ Assert( IsValid() );
+ return *this;
+}
+
+inline Vector2D& Vector2D::operator/=(float fl)
+{
+ Assert( fl != 0.0f );
+ float oofl = 1.0f / fl;
+ x *= oofl;
+ y *= oofl;
+ Assert( IsValid() );
+ return *this;
+}
+
+inline Vector2D& Vector2D::operator/=(const Vector2D& v)
+{
+ Assert( v.x != 0.0f && v.y != 0.0f );
+ x /= v.x;
+ y /= v.y;
+ Assert( IsValid() );
+ return *this;
+}
+
+inline void Vector2DAdd( const Vector2D& a, const Vector2D& b, Vector2D& c )
+{
+ Assert( a.IsValid() && b.IsValid() );
+ c.x = a.x + b.x;
+ c.y = a.y + b.y;
+}
+
+inline void Vector2DSubtract( const Vector2D& a, const Vector2D& b, Vector2D& c )
+{
+ Assert( a.IsValid() && b.IsValid() );
+ c.x = a.x - b.x;
+ c.y = a.y - b.y;
+}
+
+inline void Vector2DMultiply( const Vector2D& a, vec_t b, Vector2D& c )
+{
+ Assert( a.IsValid() && IsFinite(b) );
+ c.x = a.x * b;
+ c.y = a.y * b;
+}
+
+inline void Vector2DMultiply( const Vector2D& a, const Vector2D& b, Vector2D& c )
+{
+ Assert( a.IsValid() && b.IsValid() );
+ c.x = a.x * b.x;
+ c.y = a.y * b.y;
+}
+
+
+inline void Vector2DDivide( const Vector2D& a, vec_t b, Vector2D& c )
+{
+ Assert( a.IsValid() );
+ Assert( b != 0.0f );
+ vec_t oob = 1.0f / b;
+ c.x = a.x * oob;
+ c.y = a.y * oob;
+}
+
+inline void Vector2DDivide( const Vector2D& a, const Vector2D& b, Vector2D& c )
+{
+ Assert( a.IsValid() );
+ Assert( (b.x != 0.0f) && (b.y != 0.0f) );
+ c.x = a.x / b.x;
+ c.y = a.y / b.y;
+}
+
+inline void Vector2DMA( const Vector2D& start, float s, const Vector2D& dir, Vector2D& result )
+{
+ Assert( start.IsValid() && IsFinite(s) && dir.IsValid() );
+ result.x = start.x + s*dir.x;
+ result.y = start.y + s*dir.y;
+}
+
+// FIXME: Remove
+// For backwards compatability
+inline void Vector2D::MulAdd(const Vector2D& a, const Vector2D& b, float scalar)
+{
+ x = a.x + b.x * scalar;
+ y = a.y + b.y * scalar;
+}
+
+inline void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest )
+{
+ dest[0] = src1[0] + (src2[0] - src1[0]) * t;
+ dest[1] = src1[1] + (src2[1] - src1[1]) * t;
+}
+
+//-----------------------------------------------------------------------------
+// dot, cross
+//-----------------------------------------------------------------------------
+inline vec_t DotProduct2D(const Vector2D& a, const Vector2D& b)
+{
+ Assert( a.IsValid() && b.IsValid() );
+ return( a.x*b.x + a.y*b.y );
+}
+
+// for backwards compatability
+inline vec_t Vector2D::Dot( const Vector2D& vOther ) const
+{
+ return DotProduct2D( *this, vOther );
+}
+
+
+//-----------------------------------------------------------------------------
+// length
+//-----------------------------------------------------------------------------
+inline vec_t Vector2DLength( const Vector2D& v )
+{
+ Assert( v.IsValid() );
+ return (vec_t)FastSqrt(v.x*v.x + v.y*v.y);
+}
+
+inline vec_t Vector2D::LengthSqr(void) const
+{
+ Assert( IsValid() );
+ return (x*x + y*y);
+}
+
+inline vec_t Vector2D::NormalizeInPlace()
+{
+ return Vector2DNormalize( *this );
+}
+
+inline bool Vector2D::IsLengthGreaterThan( float val ) const
+{
+ return LengthSqr() > val*val;
+}
+
+inline bool Vector2D::IsLengthLessThan( float val ) const
+{
+ return LengthSqr() < val*val;
+}
+
+inline vec_t Vector2D::Length(void) const
+{
+ return Vector2DLength( *this );
+}
+
+
+inline void Vector2DMin( const Vector2D &a, const Vector2D &b, Vector2D &result )
+{
+ result.x = (a.x < b.x) ? a.x : b.x;
+ result.y = (a.y < b.y) ? a.y : b.y;
+}
+
+
+inline void Vector2DMax( const Vector2D &a, const Vector2D &b, Vector2D &result )
+{
+ result.x = (a.x > b.x) ? a.x : b.x;
+ result.y = (a.y > b.y) ? a.y : b.y;
+}
+
+
+//-----------------------------------------------------------------------------
+// Normalization
+//-----------------------------------------------------------------------------
+inline vec_t Vector2DNormalize( Vector2D& v )
+{
+ Assert( v.IsValid() );
+ vec_t l = v.Length();
+ if (l != 0.0f)
+ {
+ v /= l;
+ }
+ else
+ {
+ v.x = v.y = 0.0f;
+ }
+ return l;
+}
+
+
+//-----------------------------------------------------------------------------
+// Get the distance from this Vector2D to the other one
+//-----------------------------------------------------------------------------
+inline vec_t Vector2D::DistTo(const Vector2D &vOther) const
+{
+ Vector2D delta;
+ Vector2DSubtract( *this, vOther, delta );
+ return delta.Length();
+}
+
+inline vec_t Vector2D::DistToSqr(const Vector2D &vOther) const
+{
+ Vector2D delta;
+ Vector2DSubtract( *this, vOther, delta );
+ return delta.LengthSqr();
+}
+
+
+//-----------------------------------------------------------------------------
+// Computes the closest point to vecTarget no farther than flMaxDist from vecStart
+//-----------------------------------------------------------------------------
+inline void ComputeClosestPoint2D( const Vector2D& vecStart, float flMaxDist, const Vector2D& vecTarget, Vector2D *pResult )
+{
+ Vector2D vecDelta;
+ Vector2DSubtract( vecTarget, vecStart, vecDelta );
+ float flDistSqr = vecDelta.LengthSqr();
+ if ( flDistSqr <= flMaxDist * flMaxDist )
+ {
+ *pResult = vecTarget;
+ }
+ else
+ {
+ vecDelta /= FastSqrt( flDistSqr );
+ Vector2DMA( vecStart, flMaxDist, vecDelta, *pResult );
+ }
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Slow methods
+//
+//-----------------------------------------------------------------------------
+
+#ifndef VECTOR_NO_SLOW_OPERATIONS
+
+//-----------------------------------------------------------------------------
+// Returns a Vector2D with the min or max in X, Y, and Z.
+//-----------------------------------------------------------------------------
+
+inline Vector2D Vector2D::Min(const Vector2D &vOther) const
+{
+ return Vector2D(x < vOther.x ? x : vOther.x,
+ y < vOther.y ? y : vOther.y);
+}
+
+inline Vector2D Vector2D::Max(const Vector2D &vOther) const
+{
+ return Vector2D(x > vOther.x ? x : vOther.x,
+ y > vOther.y ? y : vOther.y);
+}
+
+
+//-----------------------------------------------------------------------------
+// arithmetic operations
+//-----------------------------------------------------------------------------
+
+inline Vector2D Vector2D::operator-(void) const
+{
+ return Vector2D(-x,-y);
+}
+
+inline Vector2D Vector2D::operator+(const Vector2D& v) const
+{
+ Vector2D res;
+ Vector2DAdd( *this, v, res );
+ return res;
+}
+
+inline Vector2D Vector2D::operator-(const Vector2D& v) const
+{
+ Vector2D res;
+ Vector2DSubtract( *this, v, res );
+ return res;
+}
+
+inline Vector2D Vector2D::operator*(float fl) const
+{
+ Vector2D res;
+ Vector2DMultiply( *this, fl, res );
+ return res;
+}
+
+inline Vector2D Vector2D::operator*(const Vector2D& v) const
+{
+ Vector2D res;
+ Vector2DMultiply( *this, v, res );
+ return res;
+}
+
+inline Vector2D Vector2D::operator/(float fl) const
+{
+ Vector2D res;
+ Vector2DDivide( *this, fl, res );
+ return res;
+}
+
+inline Vector2D Vector2D::operator/(const Vector2D& v) const
+{
+ Vector2D res;
+ Vector2DDivide( *this, v, res );
+ return res;
+}
+
+inline Vector2D operator*(float fl, const Vector2D& v)
+{
+ return v * fl;
+}
+
+#endif //slow
+
+#endif // VECTOR2D_H
+
diff --git a/external/vpc/public/p4lib/ip4.h b/external/vpc/public/p4lib/ip4.h
new file mode 100644
index 0000000..651d613
--- /dev/null
+++ b/external/vpc/public/p4lib/ip4.h
@@ -0,0 +1,191 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef IP4_H
+#define IP4_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlsymbol.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlstring.h"
+#include "appframework/iappsystem.h"
+
+
+//-----------------------------------------------------------------------------
+// Current perforce file state
+//-----------------------------------------------------------------------------
+enum P4FileState_t
+{
+ P4FILE_UNOPENED = 0,
+ P4FILE_OPENED_FOR_ADD,
+ P4FILE_OPENED_FOR_EDIT,
+ P4FILE_OPENED_FOR_DELETE,
+ P4FILE_OPENED_FOR_INTEGRATE,
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: definition of a file
+//-----------------------------------------------------------------------------
+struct P4File_t
+{
+ CUtlSymbol m_sName; // file name
+ CUtlSymbol m_sPath; // residing folder
+ CUtlSymbol m_sDepotFile; // the name in the depot
+ CUtlSymbol m_sClientFile; // the name on the client in Perforce syntax
+ CUtlSymbol m_sLocalFile; // the name on the client in local syntax
+ int m_iHeadRevision; // head revision number
+ int m_iHaveRevision; // the revision the clientspec has synced locally
+ bool m_bOpenedByOther; // opened by another user
+ bool m_bDir; // directory
+ bool m_bDeleted; // deleted
+ P4FileState_t m_eOpenState; // current change state
+ int m_iChangelist; // changelist current opened in
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: a single revision of a file
+//-----------------------------------------------------------------------------
+struct P4Revision_t
+{
+ int m_iChange; // changelist number
+ int m_nYear, m_nMonth, m_nDay;
+ int m_nHour, m_nMinute, m_nSecond;
+
+ CUtlSymbol m_sUser; // submitting user
+ CUtlSymbol m_sClient; // submitting client
+ CUtlString m_Description;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: a single clientspec
+//-----------------------------------------------------------------------------
+struct P4Client_t
+{
+ CUtlSymbol m_sName;
+ CUtlSymbol m_sUser;
+ CUtlSymbol m_sHost; // machine name this client is on
+ CUtlSymbol m_sLocalRoot; // local path
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Interface to accessing P4 commands
+//-----------------------------------------------------------------------------
+#define P4_MAX_INPUT_BUFFER_SIZE 16384 // descriptions should be limited to this size!
+
+abstract_class IP4 : public IAppSystem
+{
+public:
+ // name of the current clientspec
+ virtual P4Client_t &GetActiveClient() = 0;
+
+ // changes the current client
+ virtual void SetActiveClient(const char *clientname) = 0;
+
+ // Refreshes the current client from p4 settings
+ virtual void RefreshActiveClient() = 0;
+
+ // translate filespecs into the desired syntax
+ virtual void GetDepotFilePath(char *depotFilePath, const char *filespec, int size) = 0;
+ virtual void GetClientFilePath(char *clientFilePath, const char *filespec, int size) = 0;
+ virtual void GetLocalFilePath(char *localFilePath, const char *filespec, int size) = 0;
+
+ // retreives the list of files in a path
+ virtual CUtlVector<P4File_t> &GetFileList( const char *path ) = 0;
+
+ // returns the list of files opened for edit/integrate/delete
+ virtual void GetOpenedFileList( CUtlVector<P4File_t> &fileList, bool bDefaultChangeOnly ) = 0;
+ virtual void GetOpenedFileList( const char *pRootDirectory, CUtlVector<P4File_t> &fileList ) = 0;
+ virtual void GetOpenedFileListInPath( const char *pPathID, CUtlVector<P4File_t> &fileList ) = 0;
+
+ // retrieves revision history for a file or directory
+ virtual CUtlVector<P4Revision_t> &GetRevisionList( const char *path, bool bIsDir ) = 0;
+
+ // returns a list of clientspecs
+ virtual CUtlVector<P4Client_t> &GetClientList() = 0;
+
+ // changes the clientspec to remove the specified path (cloaking)
+ virtual void RemovePathFromActiveClientspec( const char *path ) = 0;
+
+ // file manipulation
+ virtual bool OpenFileForAdd( const char *pFullPath ) = 0;
+ virtual bool OpenFileForEdit( const char *pFullPath ) = 0;
+ virtual bool OpenFileForDelete( const char *pFullPath ) = 0;
+ virtual bool SyncFile( const char *pFullPath, int nRevision = -1 ) = 0; // default revision is to sync to the head revision
+
+ // submit/revert
+ virtual bool SubmitFile( const char *pFullPath, const char *pDescription ) = 0;
+ virtual bool RevertFile( const char *pFullPath ) = 0;
+
+ // file checkin/checkout for multiple files
+ virtual bool OpenFilesForAdd( int nCount, const char **ppFullPathList ) = 0;
+ virtual bool OpenFilesForEdit( int nCount, const char **ppFullPathList ) = 0;
+ virtual bool OpenFilesForDelete( int nCount, const char **ppFullPathList ) = 0;
+
+ // submit/revert for multiple files
+ virtual bool SubmitFiles( int nCount, const char **ppFullPathList, const char *pDescription ) = 0;
+ virtual bool RevertFiles( int nCount, const char **ppFullPathList ) = 0;
+
+ // Is this file in perforce?
+ virtual bool IsFileInPerforce( const char *pFullPath ) = 0;
+
+ // Get the perforce file state
+ virtual P4FileState_t GetFileState( const char *pFullPath ) = 0;
+
+ // depot root
+ virtual const char *GetDepotRoot() = 0;
+ virtual int GetDepotRootLength() = 0;
+
+ // local root
+ virtual const char *GetLocalRoot() = 0;
+ virtual int GetLocalRootLength() = 0;
+
+ // Gets a string for a symbol
+ virtual const char *String( CUtlSymbol s ) const = 0;
+
+ // Returns which clientspec a file lies under. This will
+ // search for p4config files in root directories of the file
+ // It returns false if it didn't find a p4config file.
+ virtual bool GetClientSpecForFile( const char *pFullPath, char *pClientSpec, int nMaxLen ) = 0;
+ virtual bool GetClientSpecForDirectory( const char *pFullPathDir, char *pClientSpec, int nMaxLen ) = 0;
+
+ // Returns which clientspec a filesystem path ID lies under. This will
+ // search for p4config files in all root directories of the all paths in
+ // the search path. NOTE: All directories in a path need to use the same clientspec
+ // or this function will return false.
+ // It returns false if it didn't find a p4config file.
+ virtual bool GetClientSpecForPath( const char *pPathId, char *pClientSpec, int nMaxLen ) = 0;
+
+ // Opens a file in p4 win
+ virtual void OpenFileInP4Win( const char *pFullPath ) = 0;
+
+ // have we connected? if not, nothing works
+ virtual bool IsConnectedToServer( bool bRetry = true ) = 0;
+
+ // Returns file information for a single file
+ virtual bool GetFileInfo( const char *pFullPath, P4File_t *pFileInfo ) = 0;
+
+ // retrieves the list of files in a path, using a known client spec
+ virtual CUtlVector<P4File_t> &GetFileListUsingClientSpec( const char *pPath, const char *pClientSpec ) = 0;
+
+ // retrieves the last error from the last op (which is likely to span multiple lines)
+ // this is only valid after OpenFile[s]For{Add,Edit,Delete} or {Submit,Revert}File[s]
+ virtual const char *GetLastError() = 0;
+
+ // sets the name of the changelist to open files under, NULL for "Default" changelist
+ virtual void SetOpenFileChangeList( const char *pChangeListName ) = 0;
+
+ virtual void GetFileListInChangelist( unsigned int changeListNumber, CUtlVector<P4File_t> &fileList ) = 0;
+};
+
+DECLARE_TIER2_INTERFACE( IP4, p4 );
+
+#endif // IP4_H
diff --git a/external/vpc/public/tier0/annotations.h b/external/vpc/public/tier0/annotations.h
new file mode 100644
index 0000000..d10e530
--- /dev/null
+++ b/external/vpc/public/tier0/annotations.h
@@ -0,0 +1,116 @@
+#ifndef ANALYSIS_ANNOTATIONS_H
+#define ANALYSIS_ANNOTATIONS_H
+
+#if _MSC_VER >= 1600 // VS 2010 and above.
+//-----------------------------------------------------------------------------
+// Upgrading important helpful warnings to errors
+//-----------------------------------------------------------------------------
+#pragma warning(error : 4789 ) // warning C4789: destination of memory copy is too small
+
+// Suppress some code analysis warnings
+#ifdef _PREFAST_
+// Include the annotation header file.
+#include <sal.h>
+
+// /Analyze warnings can only be suppressed when using a compiler that supports them, which VS 2010
+// Professional does not.
+
+// We don't care about these warnings because they are bugs that can only occur during resource
+// exhaustion or other unexpected API failure, which we are nowhere near being able to handle.
+#pragma warning(disable : 6308) // warning C6308: 'realloc' might return null pointer: assigning null pointer to 's_ppTestCases', which is passed as an argument to 'realloc', will cause the original memory block to be leaked
+#pragma warning(disable : 6255) // warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
+#pragma warning(disable : 6387) // warning C6387: 'argument 1' might be '0': this does not adhere to the specification for the function 'GetProcAddress'
+#pragma warning(disable : 6309) // warning C6309: Argument '1' is null: this does not adhere to function specification of 'GetProcAddress'
+#pragma warning(disable : 6011) // warning C6011: Dereferencing NULL pointer 'm_ppTestCases'
+#pragma warning(disable : 6211) // warning C6211: Leaking memory 'newKeyValue' due to an exception. Consider using a local catch block to clean up memory
+#pragma warning(disable : 6031) // warning C6031: Return value ignored: '_getcwd'
+
+// These warnings are because /analyze doesn't like our use of constants, especially things like IsPC()
+#pragma warning(disable : 6326) // warning C6326: Potential comparison of a constant with another constant
+#pragma warning(disable : 6239) // warning C6239: (<non-zero constant> && <expression>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?
+#pragma warning(disable : 6285) // warning C6285: (<non-zero constant> || <non-zero constant>) is always a non-zero constant. Did you intend to use the bitwise-and operator?
+#pragma warning(disable : 6237) // warning C6237: (<zero> && <expression>) is always zero. <expression> is never evaluated and might have side effects
+#pragma warning(disable : 6235) // warning C6235: (<non-zero constant> || <expression>) is always a non-zero constant
+#pragma warning(disable : 6240) // warning C6240: (<expression> && <non-zero constant>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?
+
+// These warnings aren't really important:
+#pragma warning(disable : 6323) // warning C6323: Use of arithmetic operator on Boolean type(s)
+
+// Miscellaneous other /analyze warnings. We should consider fixing these at some point.
+//#pragma warning(disable : 6204) // warning C6204: Possible buffer overrun in call to 'memcpy': use of unchecked parameter 'src'
+//#pragma warning(disable : 6262) // warning C6262: Function uses '16464' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap
+// This is a serious warning. Don't suppress it.
+//#pragma warning(disable : 6263) // warning C6263: Using _alloca in a loop: this can quickly overflow stack
+// 6328 is also used for passing __int64 to printf when int is expected so we can't suppress it.
+//#pragma warning(disable : 6328) // warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'V_isdigit'
+// /analyze doesn't like GCOMPILER_ASSERT's implementation of compile-time asserts
+#pragma warning(disable : 6326) // warning C6326: Potential comparison of a constant with another constant
+#pragma warning(disable : 6335) // warning C6335: Leaking process information handle 'pi.hThread'
+#pragma warning(disable : 6320) // warning C6320: Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled
+#pragma warning(disable : 6250) // warning C6250: Calling 'VirtualFree' without the MEM_RELEASE flag might free memory but not address descriptors (VADs). This causes address space leaks
+#pragma warning(disable : 6384) // ientity2_class_h_schema_gen.cpp(76): warning C6384: Dividing sizeof a pointer by another value
+
+// For temporarily suppressing warnings -- the warnings are suppressed for the next source line.
+#define ANALYZE_SUPPRESS(wnum) __pragma(warning(suppress: wnum))
+#define ANALYZE_SUPPRESS2(wnum1, wnum2) __pragma(warning(supress: wnum1 wnum2))
+#define ANALYZE_SUPPRESS3(wnum1, wnum2, wnum3) __pragma(warning(suppress: wnum1 wnum2 wnum3))
+#define ANALYZE_SUPPRESS4(wnum1, wnum2, wnum3, wnum4) __pragma(warning(suppress: wnum1 wnum2 wnum3 wnum4))
+
+// Tag all printf style format strings with this
+#define PRINTF_FORMAT_STRING _Printf_format_string_
+#define SCANF_FORMAT_STRING _Scanf_format_string_impl_
+// Various macros for specifying the capacity of the buffer pointed
+// to by a function parameter. Variations include in/out/inout,
+// CAP (elements) versus BYTECAP (bytes), and null termination or
+// not (_Z).
+#define IN_Z _In_z_
+#define IN_CAP(x) _In_count_(x)
+#define IN_BYTECAP(x) _In_bytecount_(x)
+#define OUT_Z_CAP(x) _Out_z_cap_(x)
+#define OUT_CAP(x) _Out_cap_(x)
+#define OUT_BYTECAP(x) _Out_bytecap_(x)
+#define OUT_Z_BYTECAP(x) _Out_z_bytecap_(x)
+#define INOUT_BYTECAP(x) _Inout_bytecap_(x)
+#define INOUT_Z_CAP(x) _Inout_z_cap_(x)
+#define INOUT_Z_BYTECAP(x) _Inout_z_bytecap_(x)
+// These macros are use for annotating array reference parameters, typically used in functions
+// such as V_strcpy_safe. Because they are array references the capacity is already known.
+#if _MSC_VER >= 1700
+#define IN_Z_ARRAY _Pre_z_
+#define OUT_Z_ARRAY _Post_z_
+#define INOUT_Z_ARRAY _Prepost_z_
+#else
+#define IN_Z_ARRAY _Deref_pre_z_
+#define OUT_Z_ARRAY _Deref_post_z_
+#define INOUT_Z_ARRAY _Deref_prepost_z_
+#endif // _MSC_VER >= 1700
+// Use the macros above to annotate string functions that fill buffers as shown here,
+// in order to give VS's /analyze more opportunities to find bugs.
+// void V_wcsncpy( OUT_Z_BYTECAP(maxLenInBytes) wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
+// int V_snwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, ... );
+
+#endif // _PREFAST_
+#endif // _MSC_VER >= 1600 // VS 2010 and above.
+
+#ifndef ANALYZE_SUPPRESS
+#define ANALYZE_SUPPRESS(wnum)
+#define ANALYZE_SUPPRESS2(wnum1, wnum2)
+#define ANALYZE_SUPPRESS3(wnum1, wnum2, wnum3)
+#define ANALYZE_SUPPRESS4(wnum1, wnum2, wnum3, wnum4)
+#define PRINTF_FORMAT_STRING
+#define SCANF_FORMAT_STRING
+#define IN_Z
+#define IN_CAP(x)
+#define IN_BYTECAP(x)
+#define OUT_Z_CAP(x)
+#define OUT_CAP(x)
+#define OUT_BYTECAP(x)
+#define OUT_Z_BYTECAP(x)
+#define INOUT_BYTECAP(x)
+#define INOUT_Z_CAP(x)
+#define INOUT_Z_BYTECAP(x)
+#define OUT_Z_ARRAY
+#define INOUT_Z_ARRAY
+#endif
+
+#endif // ANALYSIS_ANNOTATIONS_H
diff --git a/external/vpc/public/tier0/basetypes.h b/external/vpc/public/tier0/basetypes.h
new file mode 100644
index 0000000..caa297e
--- /dev/null
+++ b/external/vpc/public/tier0/basetypes.h
@@ -0,0 +1,650 @@
+//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef BASETYPES_H
+#define BASETYPES_H
+
+#ifdef COMPILER_MSVC
+#pragma once
+#endif
+
+// This is a trick to get the DLL extension off the -D option on the command line.
+#define DLLExtTokenPaste(x) #x
+#define DLLExtTokenPaste2(x) DLLExtTokenPaste(x)
+#define DLL_EXT_STRING DLLExtTokenPaste2( _DLL_EXT )
+
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef schema
+#define schema namespace ValveSchemaMarker {}
+#endif
+
+#ifdef COMPILING_SCHEMA
+#define UNSCHEMATIZED_METHOD( x )
+#else
+#define UNSCHEMATIZED_METHOD( x ) x
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "tier0/platform.h"
+#include "commonmacros.h"
+#include "wchartypes.h"
+#ifdef _PS3
+#include <float.h>
+#elif defined( PLATFORM_POSIX )
+#include <math.h>
+#endif
+
+#include "tier0/valve_off.h"
+
+// There's a different version of this file in the xbox codeline
+// so the PC version built in the xbox branch includes things like
+// tickrate changes.
+#include "xbox_codeline_defines.h"
+
+#if defined(_PS3)
+#include <ppu_intrinsics.h>
+#include <sys/fs.h>
+#define PATH_MAX CELL_FS_MAX_FS_PATH_LENGTH
+#define _MAX_PATH PATH_MAX
+#endif
+// stdio.h
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef PLATFORM_POSIX
+#include <stdint.h>
+
+template<class T>
+T abs( const T &a )
+{
+ if ( a < 0 )
+ return -a;
+ else
+ return a;
+}
+#endif
+
+#define ExecuteNTimes( nTimes, x ) \
+ { \
+ static int __executeCount=0;\
+ if ( __executeCount < nTimes )\
+ { \
+ ++__executeCount; \
+ x; \
+ } \
+ }
+
+
+#define ExecuteOnce( x ) ExecuteNTimes( 1, x )
+
+
+
+// Pad a number so it lies on an N byte boundary.
+// So PAD_NUMBER(0,4) is 0 and PAD_NUMBER(1,4) is 4
+#define PAD_NUMBER(number, boundary) \
+ ( ((number) + ((boundary)-1)) / (boundary) ) * (boundary)
+
+// In case this ever changes
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+// #define COMPILETIME_MAX and COMPILETIME_MIN for max/min in constant expressions
+#define COMPILETIME_MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
+#define COMPILETIME_MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#ifndef MIN
+#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+#ifndef MAX
+#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+
+
+
+#ifdef __cplusplus
+
+template< class T, class Y, class X >
+inline T clamp( T const &val, Y const &minVal, X const &maxVal )
+{
+ if( val < minVal )
+ return minVal;
+ else if( val > maxVal )
+ return maxVal;
+ else
+ return val;
+}
+
+#else
+
+#define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
+
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+//-----------------------------------------------------------------------------
+// fsel
+//-----------------------------------------------------------------------------
+#if !defined(_PS3) && !defined(_X360)
+
+#define fsel(c,x,y) ( (c) >= 0 ? (x) : (y) )
+
+// integer conditional move
+// if a >= 0, return x, else y
+#define isel(a,x,y) ( ((a) >= 0) ? (x) : (y) )
+
+// if x = y, return a, else b
+#define ieqsel(x,y,a,b) (( (x) == (y) ) ? (a) : (b))
+
+// if the nth bit of a is set (counting with 0 = LSB),
+// return x, else y
+// this is fast if nbit is a compile-time immediate
+#define ibitsel(a, nbit, x, y) ( ( ((a) & (1 << (nbit))) != 0 ) ? (x) : (y) )
+
+
+FORCEINLINE double fpmin( double a, double b )
+{
+ return a > b ? b : a;
+}
+
+FORCEINLINE double fpmax( double a, double b )
+{
+ return a >= b ? a : b;
+}
+
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE float fclamp( float x, float a, float b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE double fclamp( double x, double a, double b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+
+// At some point, we will need a unified API.
+#define imin( x, y ) ( (x) < (y) ? (x) : (y) )
+#define imax( x, y ) ( (x) > (y) ? (x) : (y) )
+#define iclamp clamp
+
+#else
+
+// __fsel(double fComparand, double fValGE, double fLT) == fComparand >= 0 ? fValGE : fLT
+// this is much faster than if ( aFloat > 0 ) { x = .. }
+// the XDK defines two intrinsics, one for floats and one for doubles -- it's the same
+// opcode, but the __fself version tells the compiler not to do a wasteful unnecessary
+// rounding op after each sel.
+// #define fsel __fsel
+#ifdef _X360
+FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) { return __fsel( fComparand, fValGE, fLT ); }
+FORCEINLINE float fsel(float fComparand, float fValGE, float fLT) { return __fself( fComparand, fValGE, fLT ); }
+#else
+FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) { return __fsel( fComparand, fValGE, fLT ); }
+FORCEINLINE float fsel(float fComparand, float fValGE, float fLT) { return __fsels( fComparand, fValGE, fLT ); }
+#endif
+
+#if !defined(_X360)
+FORCEINLINE float fpmin( float a, float b )
+{
+ return fsel( a-b, b,a);
+}
+FORCEINLINE double fpmin( double a, double b )
+{
+ return fsel( a-b, b,a);
+}
+
+FORCEINLINE float fpmax( float a, float b )
+{
+ return fsel( a-b, a,b);
+}
+FORCEINLINE double fpmax( double a, double b )
+{
+ return fsel( a-b, a,b);
+}
+
+// any mixed calls should promote to double
+FORCEINLINE double fpmax(float a, double b)
+{
+ return fpmax( (double) a, b );
+}
+// any mixed calls should promote to double
+FORCEINLINE double fpmax(double a, float b)
+{
+ return fpmax( (double) a, (double) b );
+}
+#endif
+
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE float fclamp( float x, float a, float b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE double fclamp( double x, double a, double b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+
+// if a >= 0, return x, else y
+FORCEINLINE int isel( int a, int x, int y )
+{
+ int mask = a >> 31; // arithmetic shift right, splat out the sign bit
+ return x + ((y - x) & mask);
+};
+
+// if a >= 0, return x, else y
+FORCEINLINE unsigned isel( int a, unsigned x, unsigned y )
+{
+ int mask = a >> 31; // arithmetic shift right, splat out the sign bit
+ return x + ((y - x) & mask);
+};
+
+// ( x == y ) ? a : b
+FORCEINLINE unsigned ieqsel( unsigned x, unsigned y, unsigned a, unsigned b )
+{
+ unsigned mask = (x == y) ? 0 : -1;
+ return a + ((b - a) & mask);
+};
+
+// ( x == y ) ? a : b
+FORCEINLINE int ieqsel( int x, int y, int a, int b )
+{
+ int mask = (x == y) ? 0 : -1;
+ return a + ((b - a) & mask);
+};
+
+FORCEINLINE int imin( int x, int y )
+{
+ int nMaxSign = x - y; // Positive if x greater than y
+ int nMaxMask = nMaxSign >> 31; // 0 if x greater than y, 0xffffffff if x smaller than y
+ int nMaxSaturated = y + ( nMaxSign & nMaxMask );
+ return nMaxSaturated;
+}
+
+FORCEINLINE int imax( int x, int y )
+{
+ int nMinSign = y - x; // Positive if x smaller than y
+ int nMinMask = nMinSign >> 31; // 0 if x smaller than y, 0xffffffff if x greater than y
+ int nMinSaturated = y - ( nMinSign & nMinMask);
+ return nMinSaturated;
+}
+
+FORCEINLINE int iclamp( int x, int min, int max )
+{
+ int nResult = imin( x, max );
+ return imax( nResult, min );
+}
+
+// if the nth bit of a is set (counting with 0 = LSB),
+// return x, else y
+// this is fast if nbit is a compile-time immediate
+#define ibitsel(a, nbit, x, y) ( (x) + (((y) - (x)) & (((a) & (1 << (nbit))) ? 0 : -1)) )
+
+#endif
+
+#if CROSS_PLATFORM_VERSION < 1
+
+#ifndef DONT_DEFINE_BOOL // Needed for Cocoa stuff to compile.
+typedef int BOOL;
+#endif
+
+typedef int qboolean;
+//typedef uint32 ULONG;
+typedef uint8 BYTE;
+typedef uint8 byte;
+typedef uint16 word;
+#endif
+
+#if defined( _WIN32 ) || defined( _PS3 )
+typedef wchar_t ucs2; // under windows & PS3 wchar_t is ucs2
+#else
+typedef unsigned short ucs2;
+#endif
+
+enum ThreeState_t
+{
+ TRS_FALSE,
+ TRS_TRUE,
+ TRS_NONE,
+};
+
+typedef float vec_t;
+#ifdef _WIN32
+typedef __int32 vec_t_as_gpr; // a general purpose register type equal in size to a vec_t (in case we have to avoid the fpu for some reason)
+#endif
+
+
+template <typename T>
+inline T AlignValue( T val, uintp alignment )
+{
+ return (T)( ( (uintp)val + alignment - 1 ) & ~( alignment - 1 ) );
+}
+
+
+// FIXME: this should move
+#ifndef __cplusplus
+#define true TRUE
+#define false FALSE
+#endif
+
+//-----------------------------------------------------------------------------
+// look for NANs, infinities, and underflows.
+// This assumes the ANSI/IEEE 754-1985 standard
+//-----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+
+inline uint32 FloatBits( const vec_t &f )
+{
+ union Convertor_t
+ {
+ vec_t f;
+ uint32 ul;
+ }tmp;
+
+ switch( false ) { case false: ; case (sizeof( tmp ) == 4 && sizeof( tmp.f ) == 4 && sizeof( tmp.ul ) == 4):; };
+ tmp.f = f;
+ return tmp.ul;
+}
+
+inline vec_t BitsToFloat( uint32 i )
+{
+ union Convertor_t
+ {
+ vec_t f;
+ uint32 ul;
+ }tmp;
+ switch( false ) { case false: ; case (sizeof( tmp ) == 4 && sizeof( tmp.f ) == 4 && sizeof( tmp.ul ) == 4 ):; };
+ tmp.ul = i;
+ return tmp.f;
+}
+
+inline bool IsFinite( const vec_t &f )
+{
+#ifdef _GAMECONSOLE
+ return f == f && fabs(f) <= FLT_MAX;
+#else
+ return ((FloatBits(f) & 0x7F800000) != 0x7F800000);
+#endif
+}
+
+#if defined( WIN32 )
+
+//#include <math.h>
+// Just use prototype from math.h
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ double __cdecl fabs(double);
+ //_CRT_JIT_INTRINSIC _CRTIMP float __cdecl fabsf( __in float _X);
+ float __cdecl fabsf( _In_ float );
+#ifdef __cplusplus
+}
+#endif
+
+// In win32 try to use the intrinsic fabs so the optimizer can do it's thing inline in the code
+#pragma intrinsic( fabs )
+// Also, alias float make positive to use fabs, too
+// NOTE: Is there a perf issue with double<->float conversion?
+inline float FloatMakePositive( vec_t f )
+{
+ return fabsf( f );
+}
+#else
+inline float FloatMakePositive( vec_t f )
+{
+ return fabsf(f); // was since 2002: BitsToFloat( FloatBits(f) & 0x7FFFFFFF ); fixed in 2010
+}
+#endif
+
+inline float FloatNegate( vec_t f )
+{
+ return -f; //BitsToFloat( FloatBits(f) ^ 0x80000000 );
+}
+
+
+#define FLOAT32_NAN_BITS (uint32)0x7FC00000 // not a number!
+#define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS )
+
+#define VEC_T_NAN FLOAT32_NAN
+
+#endif
+
+inline float FloatMakeNegative( vec_t f )
+{
+ return -fabsf( f );// was since 2002: BitsToFloat( FloatBits(f) | 0x80000000 ); fixed in 2010
+}
+
+
+// FIXME: why are these here? Hardly anyone actually needs them.
+struct color24
+{
+ byte r, g, b;
+};
+
+typedef struct color32_s
+{
+ bool operator!=( const struct color32_s &other ) const;
+ byte r, g, b, a;
+
+ // assign and copy by using the whole register rather
+ // than byte-by-byte copy. (No, the compiler is not
+ // smart enough to do this for you. /FAcs if you
+ // don't believe me.)
+ inline unsigned *asInt(void) { return reinterpret_cast<unsigned*>(this); }
+ inline const unsigned *asInt(void) const { return reinterpret_cast<const unsigned*>(this); }
+ // This thing is in a union elsewhere, and union members can't have assignment
+ // operators, so you have to explicitly assign using this, or be slow. SUCK.
+ inline void Copy(const color32_s &rhs)
+ {
+ *asInt() = *rhs.asInt();
+ }
+
+} color32;
+
+inline bool color32::operator!=( const color32 &other ) const
+{
+ return r != other.r || g != other.g || b != other.b || a != other.a;
+}
+
+struct colorVec
+{
+ unsigned r, g, b, a;
+};
+
+
+#ifndef NOTE_UNUSED
+#define NOTE_UNUSED(arg) ((void)arg) // for pesky compiler / lint warnings
+#endif
+#ifdef __cplusplus
+
+struct vrect_t
+{
+ int x,y,width,height;
+ vrect_t *pnext;
+};
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// MaterialRect_t struct - used for DrawDebugText
+//-----------------------------------------------------------------------------
+struct Rect_t
+{
+ int x, y;
+ int width, height;
+};
+
+struct Rect3D_t
+{
+ int x, y, z;
+ int width, height, depth;
+
+ FORCEINLINE Rect3D_t( int nX, int nY, int nZ, int nWidth, int nHeight, int nDepth )
+ {
+ x = nX;
+ y = nY;
+ z = nZ;
+ width = nWidth;
+ height = nHeight;
+ depth = nDepth;
+ }
+
+ FORCEINLINE Rect3D_t( void )
+ {
+ }
+
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Interval, used by soundemittersystem + the game
+//-----------------------------------------------------------------------------
+struct interval_t
+{
+ float start;
+ float range;
+};
+
+
+//-----------------------------------------------------------------------------
+// Declares a type-safe handle type; you can't assign one handle to the next
+//-----------------------------------------------------------------------------
+
+// 32-bit pointer handles.
+
+// Typesafe 8-bit and 16-bit handles.
+template< class HandleType >
+class CBaseIntHandle
+{
+public:
+
+ inline bool operator==( const CBaseIntHandle &other ) { return m_Handle == other.m_Handle; }
+ inline bool operator!=( const CBaseIntHandle &other ) { return m_Handle != other.m_Handle; }
+
+ // Only the code that doles out these handles should use these functions.
+ // Everyone else should treat them as a transparent type.
+ inline HandleType GetHandleValue() { return m_Handle; }
+ inline void SetHandleValue( HandleType val ) { m_Handle = val; }
+
+ typedef HandleType HANDLE_TYPE;
+
+protected:
+
+ HandleType m_Handle;
+};
+
+template< class DummyType >
+class CIntHandle16 : public CBaseIntHandle< unsigned short >
+{
+public:
+ inline CIntHandle16() {}
+
+ static inline CIntHandle16<DummyType> MakeHandle( HANDLE_TYPE val )
+ {
+ return CIntHandle16<DummyType>( val );
+ }
+
+protected:
+ inline CIntHandle16( HANDLE_TYPE val )
+ {
+ m_Handle = val;
+ }
+};
+
+
+template< class DummyType >
+class CIntHandle32 : public CBaseIntHandle< uint32 >
+{
+public:
+ inline CIntHandle32() {}
+
+ static inline CIntHandle32<DummyType> MakeHandle( HANDLE_TYPE val )
+ {
+ return CIntHandle32<DummyType>( val );
+ }
+
+protected:
+ inline CIntHandle32( HANDLE_TYPE val )
+ {
+ m_Handle = val;
+ }
+};
+
+
+// NOTE: This macro is the same as windows uses; so don't change the guts of it
+#define DECLARE_HANDLE_16BIT(name) typedef CIntHandle16< struct name##__handle * > name;
+#define DECLARE_HANDLE_32BIT(name) typedef CIntHandle32< struct name##__handle * > name;
+
+#define DECLARE_POINTER_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
+#define FORWARD_DECLARE_HANDLE(name) typedef struct name##__ *name
+
+#define DECLARE_DERIVED_POINTER_HANDLE( _name, _basehandle ) struct _name##__ : public _basehandle##__ {}; typedef struct _name##__ *_name
+#define DECLARE_ALIASED_POINTER_HANDLE( _name, _alias ) typedef struct _alias##__ *name
+
+// @TODO: Find a better home for this
+#if !defined(_STATIC_LINKED) && !defined(PUBLISH_DLL_SUBSYSTEM)
+// for platforms built with dynamic linking, the dll interface does not need spoofing
+#define PUBLISH_DLL_SUBSYSTEM()
+#endif
+
+#define UID_PREFIX generated_id_
+#define UID_CAT1(a,c) a ## c
+#define UID_CAT2(a,c) UID_CAT1(a,c)
+#define EXPAND_CONCAT(a,c) UID_CAT1(a,c)
+#ifdef _MSC_VER
+#define UNIQUE_ID UID_CAT2(UID_PREFIX,__COUNTER__)
+#else
+#define UNIQUE_ID UID_CAT2(UID_PREFIX,__LINE__)
+#endif
+
+#define _MKSTRING(arg) #arg
+#define MKSTRING(arg) _MKSTRING(arg)
+
+
+// this allows enumerations to be used as flags, and still remain type-safe!
+#define DEFINE_ENUM_BITWISE_OPERATORS( Type ) \
+ inline Type operator| ( Type a, Type b ) { return Type( int( a ) | int( b ) ); } \
+ inline Type operator& ( Type a, Type b ) { return Type( int( a ) & int( b ) ); } \
+ inline Type operator^ ( Type a, Type b ) { return Type( int( a ) ^ int( b ) ); } \
+ inline Type operator<< ( Type a, int b ) { return Type( int( a ) << b ); } \
+ inline Type operator>> ( Type a, int b ) { return Type( int( a ) >> b ); } \
+ inline Type &operator|= ( Type &a, Type b ) { return a = a | b; } \
+ inline Type &operator&= ( Type &a, Type b ) { return a = a & b; } \
+ inline Type &operator^= ( Type &a, Type b ) { return a = a ^ b; } \
+ inline Type &operator<<=( Type &a, int b ) { return a = a << b; } \
+ inline Type &operator>>=( Type &a, int b ) { return a = a >> b; } \
+ inline Type operator~( Type a ) { return Type( ~int( a ) ); }
+
+// defines increment/decrement operators for enums for easy iteration
+#define DEFINE_ENUM_INCREMENT_OPERATORS( Type ) \
+ inline Type &operator++( Type &a ) { return a = Type( int( a ) + 1 ); } \
+ inline Type &operator--( Type &a ) { return a = Type( int( a ) - 1 ); } \
+ inline Type operator++( Type &a, int ) { Type t = a; ++a; return t; } \
+ inline Type operator--( Type &a, int ) { Type t = a; --a; return t; }
+
+// Max 2 player splitscreen in portal (don't merge this back), saves a bunch of memory [8/31/2010 tom]
+#define MAX_SPLITSCREEN_CLIENT_BITS 1
+// this should == MAX_JOYSTICKS in InputEnums.h
+#define MAX_SPLITSCREEN_CLIENTS ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 2
+
+#include "tier0/valve_on.h"
+
+#endif // BASETYPES_H
diff --git a/external/vpc/public/tier0/commonmacros.h b/external/vpc/public/tier0/commonmacros.h
new file mode 100644
index 0000000..1c12442
--- /dev/null
+++ b/external/vpc/public/tier0/commonmacros.h
@@ -0,0 +1,149 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef COMMONMACROS_H
+#define COMMONMACROS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// -------------------------------------------------------
+//
+// commonmacros.h
+//
+// This should contain ONLY general purpose macros that are
+// appropriate for use in engine/launcher/all tools
+//
+// -------------------------------------------------------
+
+// Makes a 4-byte "packed ID" int out of 4 characters
+#define MAKEID(d,c,b,a) ( ((int)(a) << 24) | ((int)(b) << 16) | ((int)(c) << 8) | ((int)(d)) )
+
+// Compares a string with a 4-byte packed ID constant
+#define STRING_MATCHES_ID( p, id ) ( (*((int *)(p)) == (id) ) ? true : false )
+#define ID_TO_STRING( id, p ) ( (p)[3] = (((id)>>24) & 0xFF), (p)[2] = (((id)>>16) & 0xFF), (p)[1] = (((id)>>8) & 0xFF), (p)[0] = (((id)>>0) & 0xFF) )
+
+#define V_ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
+
+#define SETBITS(iBitVector, bits) ((iBitVector) |= (bits))
+#define CLEARBITS(iBitVector, bits) ((iBitVector) &= ~(bits))
+#define FBitSet(iBitVector, bits) ((iBitVector) & (bits))
+
+inline bool IsPowerOfTwo( int value )
+{
+ return (value & ( value - 1 )) == 0;
+}
+
+#ifndef REFERENCE
+#define REFERENCE(arg) ((void)arg)
+#endif
+
+#define CONST_INTEGER_AS_STRING(x) #x //Wraps the integer in quotes, allowing us to form constant strings with it
+#define __HACK_LINE_AS_STRING__(x) CONST_INTEGER_AS_STRING(x) //__LINE__ can only be converted to an actual number by going through this, otherwise the output is literally "__LINE__"
+#define __LINE__AS_STRING __HACK_LINE_AS_STRING__(__LINE__) //Gives you the line number in constant string form
+
+// Using ARRAYSIZE implementation from winnt.h:
+#ifdef ARRAYSIZE
+#undef ARRAYSIZE
+#endif
+
+// Return the number of elements in a statically sized array.
+// DWORD Buffer[100];
+// RTL_NUMBER_OF(Buffer) == 100
+// This is also popularly known as: NUMBER_OF, ARRSIZE, _countof, NELEM, etc.
+//
+#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))
+
+#if defined(__cplusplus) && \
+ !defined(MIDL_PASS) && \
+ !defined(RC_INVOKED) && \
+ !defined(_PREFAST_) && \
+ (_MSC_FULL_VER >= 13009466) && \
+ !defined(SORTPP_PASS)
+
+// From crtdefs.h
+#if !defined(UNALIGNED)
+#if defined(_M_IA64) || defined(_M_AMD64)
+#define UNALIGNED __unaligned
+#else
+#define UNALIGNED
+#endif
+#endif
+
+// RtlpNumberOf is a function that takes a reference to an array of N Ts.
+//
+// typedef T array_of_T[N];
+// typedef array_of_T &reference_to_array_of_T;
+//
+// RtlpNumberOf returns a pointer to an array of N chars.
+// We could return a reference instead of a pointer but older compilers do not accept that.
+//
+// typedef char array_of_char[N];
+// typedef array_of_char *pointer_to_array_of_char;
+//
+// sizeof(array_of_char) == N
+// sizeof(*pointer_to_array_of_char) == N
+//
+// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
+//
+// We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
+// We do not even implement RtlpNumberOf, we just decare it.
+//
+// Attempts to pass pointers instead of arrays to this macro result in compile time errors.
+// That is the point.
+extern "C++" // templates cannot be declared to have 'C' linkage
+template <typename T, size_t N>
+char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
+
+#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
+
+// This does not work with:
+//
+// void Foo()
+// {
+// struct { int x; } y[2];
+// RTL_NUMBER_OF_V2(y); // illegal use of anonymous local type in template instantiation
+// }
+//
+// You must instead do:
+//
+// struct Foo1 { int x; };
+//
+// void Foo()
+// {
+// Foo1 y[2];
+// RTL_NUMBER_OF_V2(y); // ok
+// }
+//
+// OR
+//
+// void Foo()
+// {
+// struct { int x; } y[2];
+// RTL_NUMBER_OF_V1(y); // ok
+// }
+//
+// OR
+//
+// void Foo()
+// {
+// struct { int x; } y[2];
+// _ARRAYSIZE(y); // ok
+// }
+
+#else
+#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A)
+#endif
+
+// ARRAYSIZE is more readable version of RTL_NUMBER_OF_V2
+// _ARRAYSIZE is a version useful for anonymous types
+#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A)
+#define _ARRAYSIZE(A) RTL_NUMBER_OF_V1(A)
+
+#endif // COMMONMACROS_H
+
diff --git a/external/vpc/public/tier0/dbg.h b/external/vpc/public/tier0/dbg.h
new file mode 100644
index 0000000..2e54a47
--- /dev/null
+++ b/external/vpc/public/tier0/dbg.h
@@ -0,0 +1,716 @@
+//===== Copyright (c) Valve Corporation, All rights reserved. ========//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//====================================================================//
+#ifndef DBG_H
+#define DBG_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#include "tier0/basetypes.h"
+#include "dbgflag.h"
+#include "logging.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+//-----------------------------------------------------------------------------
+// dll export stuff
+//-----------------------------------------------------------------------------
+
+class Color;
+
+
+//-----------------------------------------------------------------------------
+// Usage model for the Dbg library
+//
+// 1. Assertions.
+//
+// Assertions are used to detect and warn about invalid states
+//
+// To use an assertion, use
+//
+// Assert( (f == 5) );
+// AssertMsg( (f == 5), ("F needs to be %d here!\n", 5) );
+// AssertFunc( (f == 5), BadFunc() );
+// AssertEquals( f, 5 );
+// AssertFloatEquals( f, 5.0f, 1e-3 );
+//
+// The first will simply report that an assertion failed on a particular
+// code file and line. The second version will display a print-f formatted message
+// along with the file and line, the third will display a generic message and
+// will also cause the function BadFunc to be executed, and the last two
+// will report an error if f is not equal to 5 (the last one asserts within
+// a particular tolerance).
+//
+// 2. Code activation
+//
+// To cause code to be run only in debug builds, use DBG_CODE:
+// An example is below.
+//
+// DBG_CODE(
+// {
+// int x = 5;
+// ++x;
+// }
+// );
+//
+// Code can be activated based on the dynamic spew groups also. Use
+//
+// DBG_DCODE( "group", level,
+// { int x = 5; ++x; }
+// );
+//
+// 3. Breaking into the debugger.
+//
+// To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK
+//
+// DBG_BREAK();
+//
+// You can force a break in any build (release or debug) using
+//
+// DebuggerBreak();
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line );
+
+#if defined( DBGFLAG_STRINGS_STRIP )
+#define DbgFlagMacro_ExitOnFatalAssert( pFile, line ) _ExitOnFatalAssert( "", 0 )
+#else
+#define DbgFlagMacro_ExitOnFatalAssert( pFile, line ) _ExitOnFatalAssert( pFile, line )
+#endif
+
+PLATFORM_INTERFACE bool ShouldUseNewAssertDialog();
+
+PLATFORM_INTERFACE bool SetupWin32ConsoleIO();
+
+// Returns true if they want to break in the debugger.
+PLATFORM_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar *pExpression );
+
+#if defined( DBGFLAG_STRINGS_STRIP )
+#define DbgFlagMacro_DoNewAssertDialog( pFile, line, pExpression ) DoNewAssertDialog( "", 0, "" )
+#else
+#define DbgFlagMacro_DoNewAssertDialog( pFile, line, pExpression ) DoNewAssertDialog( pFile, line, pExpression )
+#endif
+
+/* Used to define macros, never use these directly. */
+
+#ifdef _PREFAST_
+ // When doing /analyze builds define the assert macros to be __analysis_assume. This tells
+ // the compiler to assume that the condition is true, which helps to suppress many
+ // warnings. This define is done in debug and release builds, but debug builds should be
+ // preferred for static analysis because some asserts are compiled out in release.
+ // The unfortunate !! is necessary because otherwise /analyze is incapable of evaluating
+ // all of the logical expressions that the regular compiler can handle.
+ #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) __analysis_assume( !!(_exp) )
+ #define _AssertMsgOnce( _exp, _msg, _bFatal ) __analysis_assume( !!(_exp) )
+ // Force asserts on for /analyze so that we get a __analysis_assume of all of the constraints.
+ #define DBGFLAG_ASSERT
+ #define DBGFLAG_ASSERTFATAL
+#else
+ #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) \
+ do { \
+ if (!(_exp)) \
+ { \
+ LoggingResponse_t ret = Log_Assert( "%s (%d) : %s\n", __TFILE__, __LINE__, _msg ); \
+ _executeExp; \
+ if ( ret == LR_DEBUGGER ) \
+ { \
+ if ( !ShouldUseNewAssertDialog() || DbgFlagMacro_DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \
+ DebuggerBreak(); \
+ if ( _bFatal ) \
+ DbgFlagMacro_ExitOnFatalAssert( __TFILE__, __LINE__ ); \
+ } \
+ } \
+ } while (0)
+
+ #define _AssertMsgOnce( _exp, _msg, _bFatal ) \
+ do { \
+ static bool fAsserted; \
+ if (!fAsserted ) \
+ { \
+ _AssertMsg( _exp, _msg, (fAsserted = true), _bFatal ); \
+ } \
+ } while (0)
+#endif
+
+/* Spew macros... */
+
+// AssertFatal macros
+// AssertFatal is used to detect an unrecoverable error condition.
+// If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger),
+// and always terminates the application
+
+#ifdef DBGFLAG_ASSERTFATAL
+
+#define AssertFatal( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), true )
+#define AssertFatalOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), true )
+#define AssertFatalMsg( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), true )
+#define AssertFatalMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, true )
+#define AssertFatalFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: " _T(#_exp), _f, true )
+#define AssertFatalEquals( _exp, _expectedValue ) AssertFatalMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
+#define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) AssertFatalMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
+#define VerifyFatal( _exp ) AssertFatal( _exp )
+#define VerifyEqualsFatal( _exp, _expectedValue ) AssertFatalEquals( _exp, _expectedValue )
+
+#define AssertFatalMsg1( _exp, _msg, a1 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1 )))
+#define AssertFatalMsg2( _exp, _msg, a1, a2 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2 )))
+#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3 )))
+#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4 )))
+#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5 )))
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )))
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )))
+#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7 )))
+#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8 )))
+#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 )))
+
+#else // DBGFLAG_ASSERTFATAL
+
+#define AssertFatal( _exp ) ((void)0)
+#define AssertFatalOnce( _exp ) ((void)0)
+#define AssertFatalMsg( _exp, _msg ) ((void)0)
+#define AssertFatalMsgOnce( _exp, _msg ) ((void)0)
+#define AssertFatalFunc( _exp, _f ) ((void)0)
+#define AssertFatalEquals( _exp, _expectedValue ) ((void)0)
+#define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
+#define VerifyFatal( _exp ) (_exp)
+#define VerifyEqualsFatal( _exp, _expectedValue ) (_exp)
+
+#define AssertFatalMsg1( _exp, _msg, a1 ) ((void)0)
+#define AssertFatalMsg2( _exp, _msg, a1, a2 ) ((void)0)
+#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
+#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
+#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
+#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
+#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
+
+#endif // DBGFLAG_ASSERTFATAL
+
+// lightweight assert macros: in theory, can be run in release without slowing it down
+#if defined(_CERT) || defined(_RETAIL)
+#define AssertAligned(PTR)
+#else
+# if defined( _X360 )
+# define AssertAligned(PTR) __twnei( intp(PTR) & 0xF, 0 ) // trap if not equal to immediate value; unsigned comparison
+# elif defined( DBGFLAG_ASSERT )
+# define AssertAligned( adr ) Assert( ( ( ( intp ) ( adr ) ) & 0xf ) == 0 )
+# else
+# define AssertAligned(PTR)
+# endif
+#endif
+
+// Assert macros
+// Assert is used to detect an important but survivable error.
+// It's only turned on when DBGFLAG_ASSERT is true.
+
+#ifdef DBGFLAG_ASSERT
+
+#define Assert( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
+#define AssertMsg_( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false )
+#define AssertOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), false )
+#define AssertMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, false )
+#define AssertFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), _f, false )
+#define AssertEquals( _exp, _expectedValue ) AssertMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
+#define AssertFloatEquals( _exp, _expectedValue, _tol ) AssertMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
+#define Verify( _exp ) Assert( _exp )
+#define VerifyEquals( _exp, _expectedValue ) AssertEquals( _exp, _expectedValue )
+
+#define AssertMsg( _exp, _msg ) AssertMsg_( _exp, _T( _msg ) )
+#define AssertMsg1( _exp, _msg, a1 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1 )) )
+#define AssertMsg2( _exp, _msg, a1, a2 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2 )) )
+#define AssertMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3 )) )
+#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4 )) )
+#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5 )) )
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6 )) )
+#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7 )) )
+#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7, a8 )) )
+#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7, a8, a9 )) )
+
+#else // DBGFLAG_ASSERT
+
+#define Assert( _exp ) ((void)0)
+#define AssertOnce( _exp ) ((void)0)
+#define AssertMsg( _exp, _msg ) ((void)0)
+#define AssertMsgOnce( _exp, _msg ) ((void)0)
+#define AssertFunc( _exp, _f ) ((void)0)
+#define AssertEquals( _exp, _expectedValue ) ((void)0)
+#define AssertFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
+#define Verify( _exp ) (_exp)
+#define VerifyEquals( _exp, _expectedValue ) (_exp)
+
+#define AssertMsg1( _exp, _msg, a1 ) ((void)0)
+#define AssertMsg2( _exp, _msg, a1, a2 ) ((void)0)
+#define AssertMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
+#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
+#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
+#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
+#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
+
+#endif // DBGFLAG_ASSERT
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+
+#define FILE_LINE_FUNCTION_STRING __FILE__ "(" STRINGIFY(__LINE__) "):" __FUNCTION__ ":"
+#define FILE_LINE_STRING __FILE__ "(" STRINGIFY(__LINE__) "):"
+#define FUNCTION_LINE_STRING __FUNCTION__ "(" STRINGIFY(__LINE__) "): "
+
+
+//////////////////////////////////////////////////////////////////////////
+// Legacy Logging System
+//////////////////////////////////////////////////////////////////////////
+
+// Channels which map the legacy logging system to the new system.
+
+// Channel for all default Msg/Warning/Error commands.
+DECLARE_LOGGING_CHANNEL( LOG_GENERAL );
+// Channel for all asserts.
+DECLARE_LOGGING_CHANNEL( LOG_ASSERT );
+// Channel for all ConMsg and ConColorMsg commands.
+DECLARE_LOGGING_CHANNEL( LOG_CONSOLE );
+// Channel for all DevMsg and DevWarning commands with level < 2.
+DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER );
+// Channel for ConDMsg commands.
+DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER_CONSOLE );
+// Channel for all DevMsg and DevWarning commands with level >= 2.
+DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER_VERBOSE );
+
+// Legacy logging functions
+
+PLATFORM_INTERFACE void Error( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_INTERFACE void Error_SpewCallStack( int iMaxCallStackLength, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+#if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
+
+#define Msg( ... ) ((void)0)
+#define Warning( ... ) ((void)0)
+#define Warning_SpewCallStack( ... ) ((void)0)
+#define DevMsg( ... ) ((void)0)
+#define DevWarning( ... ) ((void)0)
+#define ConColorMsg( ... ) ((void)0)
+#define ConMsg( ... ) ((void)0)
+#define ConDMsg( ... ) ((void)0)
+#define COM_TimestampedLog( ... ) ((void)0)
+
+#else // #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
+
+PLATFORM_INTERFACE void Msg( const tchar* pMsg, ... );
+PLATFORM_INTERFACE void Warning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_INTERFACE void Warning_SpewCallStack( int iMaxCallStackLength, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+#ifdef _PS3
+
+PLATFORM_OVERLOAD void DevMsg( int level, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_OVERLOAD void DevWarning( int level, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+PLATFORM_INTERFACE void DevMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_INTERFACE void DevWarning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+PLATFORM_INTERFACE void ConColorMsg( const Color& clr, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_INTERFACE void ConMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+#else // !_PS3
+
+PLATFORM_INTERFACE void DevMsg( int level, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_INTERFACE void DevWarning( int level, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+PLATFORM_OVERLOAD void DevMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_OVERLOAD void DevWarning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+PLATFORM_OVERLOAD void ConColorMsg( const Color& clr, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_OVERLOAD void ConMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+#endif // _PS3
+
+PLATFORM_INTERFACE void ConDMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+PLATFORM_INTERFACE void COM_TimestampedLog( char const *fmt, ... ) FMTFUNCTION( 1, 2 );
+
+#endif // #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
+
+// You can use this macro like a runtime assert macro.
+// If the condition fails, then Error is called with the message. This macro is called
+// like AssertMsg, where msg must be enclosed in parenthesis:
+//
+// ErrorIfNot( bCondition, ("a b c %d %d %d", 1, 2, 3) );
+#define ErrorIfNot( condition, msg ) \
+ if ( (condition) ) \
+ ; \
+ else \
+ { \
+ Error msg; \
+ }
+
+#ifdef _DEBUG
+#define DebugMsg(...) DevMsg(__VA_ARGS__)
+#else
+#define DebugMsg(...)
+#endif
+
+// @TODO: these callstack spew functions are currently disabled in the new logging system. Need to add support for these if desired.
+PLATFORM_INTERFACE void _Warning_AlwaysSpewCallStack_Enable( bool bEnable );
+PLATFORM_INTERFACE void _Warning_AlwaysSpewCallStack_Length( int iMaxCallStackLength );
+
+PLATFORM_INTERFACE void _Error_AlwaysSpewCallStack_Enable( bool bEnable );
+PLATFORM_INTERFACE void _Error_AlwaysSpewCallStack_Length( int iMaxCallStackLength );
+
+
+/* Code macros, debugger interface */
+
+#ifdef _DEBUG
+
+#define DBG_CODE( _code ) if (0) ; else { _code }
+#define DBG_CODE_NOSCOPE( _code ) _code
+#define DBG_DCODE( _g, _l, _code ) if (IsSpewActive( _g, _l )) { _code } else {}
+#define DBG_BREAK() DebuggerBreak() /* defined in platform.h */
+
+#else /* not _DEBUG */
+
+#define DBG_CODE( _code ) ((void)0)
+#define DBG_CODE_NOSCOPE( _code )
+#define DBG_DCODE( _g, _l, _code ) ((void)0)
+#define DBG_BREAK() ((void)0)
+
+#endif /* _DEBUG */
+
+//-----------------------------------------------------------------------------
+// Macro to assist in asserting constant invariants during compilation
+
+#ifdef _DEBUG
+#define COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
+#define ASSERT_INVARIANT( pred ) static void UNIQUE_ID() { COMPILE_TIME_ASSERT( pred ) }
+#else
+#define COMPILE_TIME_ASSERT( pred )
+#define ASSERT_INVARIANT( pred )
+#endif
+
+#ifdef _DEBUG
+template<typename DEST_POINTER_TYPE, typename SOURCE_POINTER_TYPE>
+inline DEST_POINTER_TYPE assert_cast(SOURCE_POINTER_TYPE* pSource)
+{
+ Assert( static_cast<DEST_POINTER_TYPE>(pSource) == dynamic_cast<DEST_POINTER_TYPE>(pSource) );
+ return static_cast<DEST_POINTER_TYPE>(pSource);
+}
+#else
+#define assert_cast static_cast
+#endif
+
+//-----------------------------------------------------------------------------
+// Templates to assist in validating pointers:
+
+// Have to use these stubs so we don't have to include windows.h here.
+PLATFORM_INTERFACE void _AssertValidReadPtr( void* ptr, int count = 1 );
+PLATFORM_INTERFACE void _AssertValidWritePtr( void* ptr, int count = 1 );
+PLATFORM_INTERFACE void _AssertValidReadWritePtr( void* ptr, int count = 1 );
+PLATFORM_INTERFACE void _AssertValidStringPtr( const tchar* ptr, int maxchar );
+
+#ifdef DBGFLAG_ASSERT
+inline void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ) { _AssertValidStringPtr( ptr, maxchar ); }
+template<class T> inline void AssertValidReadPtr( T* ptr, int count = 1 ) { _AssertValidReadPtr( (void*)ptr, count ); }
+template<class T> inline void AssertValidWritePtr( T* ptr, int count = 1 ) { _AssertValidWritePtr( (void*)ptr, count ); }
+template<class T> inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { _AssertValidReadWritePtr( (void*)ptr, count ); }
+#define AssertValidThis() AssertValidReadWritePtr(this,sizeof(*this))
+
+#else
+
+inline void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ) { }
+template<class T> inline void AssertValidReadPtr( T* ptr, int count = 1 ) { }
+template<class T> inline void AssertValidWritePtr( T* ptr, int count = 1 ) { }
+template<class T> inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { }
+#define AssertValidThis()
+#endif
+
+//-----------------------------------------------------------------------------
+// Macro to protect functions that are not reentrant
+
+#ifdef _DEBUG
+class CReentryGuard
+{
+public:
+ CReentryGuard(int *pSemaphore)
+ : m_pSemaphore(pSemaphore)
+ {
+ ++(*m_pSemaphore);
+ }
+
+ ~CReentryGuard()
+ {
+ --(*m_pSemaphore);
+ }
+
+private:
+ int *m_pSemaphore;
+};
+
+#define ASSERT_NO_REENTRY() \
+ static int fSemaphore##__LINE__; \
+ Assert( !fSemaphore##__LINE__ ); \
+ CReentryGuard ReentryGuard##__LINE__( &fSemaphore##__LINE__ )
+#else
+#define ASSERT_NO_REENTRY()
+#endif
+
+// Tier0 uses these for string functions since this abstraction is normally done in tier1.
+#ifdef POSIX
+ #define Tier0Internal_sntprintf snprintf
+ #define Tier0Internal_vsntprintf vsnprintf
+ #define Tier0Internal_vsnprintf vsnprintf
+#else
+ #define Tier0Internal_sntprintf _sntprintf
+ #define Tier0Internal_vsntprintf _vsntprintf
+ #define Tier0Internal_vsnprintf _vsnprintf
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Inline string formatter
+//
+
+#include "tier0/valve_off.h"
+class CDbgFmtMsg
+{
+public:
+ CDbgFmtMsg(const tchar *pszFormat, ...)
+ {
+ va_list arg_ptr;
+
+ va_start(arg_ptr, pszFormat);
+ Tier0Internal_vsntprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr);
+ va_end(arg_ptr);
+
+ m_szBuf[sizeof(m_szBuf)-1] = 0;
+ }
+
+ operator const tchar *() const
+ {
+ return m_szBuf;
+ }
+
+private:
+ tchar m_szBuf[256];
+};
+#include "tier0/valve_on.h"
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Embed debug info in each file.
+//
+#if defined( _WIN32 ) && !defined( _X360 )
+
+ #ifdef _DEBUG
+ #pragma comment(compiler)
+ #endif
+
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Wrap around a variable to create a simple place to put a breakpoint
+//
+
+#ifdef _DEBUG
+
+template< class Type >
+class CDataWatcher
+{
+public:
+ const Type& operator=( const Type &val )
+ {
+ return Set( val );
+ }
+
+ const Type& operator=( const CDataWatcher<Type> &val )
+ {
+ return Set( val.m_Value );
+ }
+
+ const Type& Set( const Type &val )
+ {
+ // Put your breakpoint here
+ m_Value = val;
+ return m_Value;
+ }
+
+ Type& GetForModify()
+ {
+ return m_Value;
+ }
+
+ const Type& operator+=( const Type &val )
+ {
+ return Set( m_Value + val );
+ }
+
+ const Type& operator-=( const Type &val )
+ {
+ return Set( m_Value - val );
+ }
+
+ const Type& operator/=( const Type &val )
+ {
+ return Set( m_Value / val );
+ }
+
+ const Type& operator*=( const Type &val )
+ {
+ return Set( m_Value * val );
+ }
+
+ const Type& operator^=( const Type &val )
+ {
+ return Set( m_Value ^ val );
+ }
+
+ const Type& operator|=( const Type &val )
+ {
+ return Set( m_Value | val );
+ }
+
+ const Type& operator++()
+ {
+ return (*this += 1);
+ }
+
+ Type operator--()
+ {
+ return (*this -= 1);
+ }
+
+ Type operator++( int ) // postfix version..
+ {
+ Type val = m_Value;
+ (*this += 1);
+ return val;
+ }
+
+ Type operator--( int ) // postfix version..
+ {
+ Type val = m_Value;
+ (*this -= 1);
+ return val;
+ }
+
+ // For some reason the compiler only generates type conversion warnings for this operator when used like
+ // CNetworkVarBase<unsigned tchar> = 0x1
+ // (it warns about converting from an int to an unsigned char).
+ template< class C >
+ const Type& operator&=( C val )
+ {
+ return Set( m_Value & val );
+ }
+
+ operator const Type&() const
+ {
+ return m_Value;
+ }
+
+ const Type& Get() const
+ {
+ return m_Value;
+ }
+
+ const Type* operator->() const
+ {
+ return &m_Value;
+ }
+
+ Type m_Value;
+
+};
+
+#else
+
+template< class Type >
+class CDataWatcher
+{
+private:
+ CDataWatcher(); // refuse to compile in non-debug builds
+};
+
+#endif
+
+// Code for programmatically setting/unsetting hardware breakpoints (there's probably a 360 and
+#ifdef IS_WINDOWS_PC
+
+typedef void * HardwareBreakpointHandle_t;
+
+enum EHardwareBreakpointType
+{
+ BREAKPOINT_EXECUTE = 0,
+ BREAKPOINT_WRITE,
+ BREAKPOINT_READWRITE,
+};
+
+enum EHardwareBreakpointSize
+{
+ BREAKPOINT_SIZE_1 = 1,
+ BREAKPOINT_SIZE_2 = 2,
+ BREAKPOINT_SIZE_4 = 4,
+ BREAKPOINT_SIZE_8 = 8,
+};
+
+PLATFORM_INTERFACE HardwareBreakpointHandle_t SetHardwareBreakpoint( EHardwareBreakpointType eType, EHardwareBreakpointSize eSize, const void *pvLocation );
+PLATFORM_INTERFACE bool ClearHardwareBreakpoint( HardwareBreakpointHandle_t handle );
+
+class CHardwareBreakPointScopeGuard
+{
+public:
+ CHardwareBreakPointScopeGuard( const void *pvLocation, size_t nLocationSize, EHardwareBreakpointType eType = BREAKPOINT_WRITE )
+ {
+ EHardwareBreakpointSize eSize = BREAKPOINT_SIZE_4;
+ switch ( nLocationSize )
+ {
+ case 1:
+ eSize = BREAKPOINT_SIZE_1;
+ break;
+ case 2:
+ eSize = BREAKPOINT_SIZE_2;
+ break;
+ case 4:
+ eSize = BREAKPOINT_SIZE_4;
+ break;
+ case 8:
+ eSize = BREAKPOINT_SIZE_8;
+ break;
+ default:
+ Warning( _T( "SetHardwareBreakpoint can only work with 1, 2, 4 or 8 byte data fields." ) );
+ break;
+ }
+
+ m_hBreakPoint = SetHardwareBreakpoint( eType, eSize, pvLocation );
+ m_bActive = m_hBreakPoint != (HardwareBreakpointHandle_t)0;
+ }
+
+ ~CHardwareBreakPointScopeGuard()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ if ( !m_bActive )
+ return;
+ ClearHardwareBreakpoint( m_hBreakPoint );
+ }
+
+private:
+ bool m_bActive;
+ HardwareBreakpointHandle_t m_hBreakPoint;
+};
+
+#endif // IS_WINDOWS_PC
+//-----------------------------------------------------------------------------
+
+#endif /* DBG_H */
diff --git a/external/vpc/public/tier0/dbgflag.h b/external/vpc/public/tier0/dbgflag.h
new file mode 100644
index 0000000..deee3e5
--- /dev/null
+++ b/external/vpc/public/tier0/dbgflag.h
@@ -0,0 +1,68 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This file sets all of our debugging flags. It should be
+// called before all other header files.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef DBGFLAG_H
+#define DBGFLAG_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+// Here are all the flags we support:
+// DBGFLAG_MEMORY: Enables our memory debugging system, which overrides malloc & free
+// DBGFLAG_MEMORY_NEWDEL: Enables new / delete tracking for memory debug system. Requires DBGFLAG_MEMORY to be enabled.
+// DBGFLAG_VALIDATE: Enables our recursive validation system for checking integrity and memory leaks
+// DBGFLAG_ASSERT: Turns Assert on or off (when off, it isn't compiled at all)
+// DBGFLAG_ASSERTFATAL: Turns AssertFatal on or off (when off, it isn't compiled at all)
+// DBGFLAG_ASSERTDLG: Turns assert dialogs on or off and debug breaks on or off when not under the debugger.
+// (Dialogs will always be on when process is being debugged.)
+// DBGFLAG_STRINGS: Turns on hardcore string validation (slow but safe)
+
+#undef DBGFLAG_MEMORY
+#undef DBGFLAG_MEMORY_NEWDEL
+#undef DBGFLAG_VALIDATE
+#undef DBGFLAG_ASSERT
+#undef DBGFLAG_ASSERTFATAL
+#undef DBGFLAG_ASSERTDLG
+#undef DBGFLAG_STRINGS
+
+//-----------------------------------------------------------------------------
+// Default flags for debug builds
+//-----------------------------------------------------------------------------
+#if defined( _DEBUG ) && !defined( PS3MEMOVERRIDEWRAP )
+
+#define DBGFLAG_MEMORY
+#ifdef _SERVER // only enable new & delete tracking for server; on client it conflicts with CRT mem leak tracking
+#define DBGFLAG_MEMORY_NEWDEL
+#endif
+#ifdef STEAM
+#define DBGFLAG_VALIDATE
+#endif
+#define DBGFLAG_ASSERT
+#define DBGFLAG_ASSERTFATAL
+#define DBGFLAG_ASSERTDLG
+#define DBGFLAG_STRINGS
+
+
+//-----------------------------------------------------------------------------
+// Default flags for release builds
+//-----------------------------------------------------------------------------
+#else // _DEBUG
+#ifdef STEAM
+#define DBGFLAG_ASSERT
+#endif
+#define DBGFLAG_ASSERTFATAL // note: fatal asserts are enabled in release builds
+#define DBGFLAG_ASSERTDLG
+
+#endif // _DEBUG
+
+#if defined( _CERT )
+#define DBGFLAG_STRINGS_STRIP
+#endif
+
+#endif // DBGFLAG_H
diff --git a/external/vpc/public/tier0/etwprof.h b/external/vpc/public/tier0/etwprof.h
new file mode 100644
index 0000000..ba9f8f5
--- /dev/null
+++ b/external/vpc/public/tier0/etwprof.h
@@ -0,0 +1,155 @@
+//============ Copyright (c) Valve Corporation, All rights reserved. ============
+//
+// ETW (Event Tracing for Windows) profiling helpers.
+// This allows easy insertion of Generic Event markers into ETW/xperf tracing
+// which then aids in analyzing the traces and finding performance problems.
+// The usage patterns are to use ETWBegin and ETWEnd (typically through the
+// convenience class CETWScope) to bracket time-consuming operations. In addition
+// ETWFrameMark marks the beginning of each frame, and ETWMark can be used to
+// mark other notable events. More event types and providers can be added as needed.
+// When recording xperf profiles add Valve-Main+Valve-FrameRate to the list of
+// user-mode providers and be sure to register the providers with this sequence
+// of commands:
+// xcopy /y game\bin\tier0.dll %temp%
+// wevtutil um src\tier0\ValveETWProvider.man
+// wevtutil im src\tier0\ValveETWProvider.man
+//
+//===============================================================================
+
+#ifndef ETWPROF_H
+#define ETWPROF_H
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+#ifdef IS_WINDOWS_PC
+// ETW support should be compiled in for all Windows PC platforms. It isn't
+// supported on Windows XP but that is determined at run-time.
+#if !defined(STANDALONE_VPC)
+#define ETW_MARKS_ENABLED
+#endif
+#endif
+
+#ifdef ETW_MARKS_ENABLED
+
+// Insert a single event to mark a point in an ETW trace. The return value is a 64-bit
+// time stamp.
+PLATFORM_INTERFACE int64 ETWMark( const char *pMessage );
+// Optionally do full printf formatting of the mark string. This will be more expensive,
+// but only when tracing is enabled.
+PLATFORM_INTERFACE int64 ETWMarkPrintf( PRINTF_FORMAT_STRING const char *pMessage, ... ) FMTFUNCTION( 1, 2 );
+// Optionally specify one to four floats. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+PLATFORM_INTERFACE void ETWMark1F( const char *pMessage, float data1 );
+PLATFORM_INTERFACE void ETWMark2F( const char *pMessage, float data1, float data2 );
+PLATFORM_INTERFACE void ETWMark3F( const char *pMessage, float data1, float data2, float data3 );
+PLATFORM_INTERFACE void ETWMark4F( const char *pMessage, float data1, float data2, float data3, float data4 );
+// Optionally specify one to four ints. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+PLATFORM_INTERFACE void ETWMark1I( const char *pMessage, int data1 );
+PLATFORM_INTERFACE void ETWMark2I( const char *pMessage, int data1, int data2 );
+PLATFORM_INTERFACE void ETWMark3I( const char *pMessage, int data1, int data2, int data3 );
+PLATFORM_INTERFACE void ETWMark4I( const char *pMessage, int data1, int data2, int data3, int data4 );
+// Optionally specify one to two strings. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+PLATFORM_INTERFACE void ETWMark1S( const char *pMessage, const char* data1 );
+PLATFORM_INTERFACE void ETWMark2S( const char *pMessage, const char* data1, const char* data2 );
+
+// Insert a begin event to mark the start of some work. The return value is a 64-bit
+// time stamp which should be passed to the corresponding ETWEnd function.
+PLATFORM_INTERFACE int64 ETWBegin( const char *pMessage );
+
+// Insert a paired end event to mark the end of some work.
+PLATFORM_INTERFACE int64 ETWEnd( const char *pMessage, int64 nStartTime );
+
+// Mark the start of the next render frame. bIsServerProcess must be passed
+// in consistently for a particular process.
+PLATFORM_INTERFACE void ETWRenderFrameMark( bool bIsServerProcess );
+// Mark the start of the next simulation frame. bIsServerProcess must be passed
+// in consistently for a particular process.
+PLATFORM_INTERFACE void ETWSimFrameMark( bool bIsServerProcess );
+// Return the frame number recorded in the ETW trace -- useful for synchronization
+// other profile information to the ETW trace.
+PLATFORM_INTERFACE int ETWGetRenderFrameNumber();
+
+PLATFORM_INTERFACE void ETWMouseDown( int nWhichButton, int nX, int nY );
+PLATFORM_INTERFACE void ETWMouseUp( int nWhichButton, int nX, int nY );
+PLATFORM_INTERFACE void ETWKeyDown( int nScanCode, int nVirtualCode, const char *pChar );
+
+PLATFORM_INTERFACE void ETWSendPacket( const char *pTo, int nWireSize, int nOutSequenceNR, int nOutSequenceNrAck );
+PLATFORM_INTERFACE void ETWThrottled();
+PLATFORM_INTERFACE void ETWReadPacket( const char *pFrom, int nWireSize, int nInSequenceNR, int nOutSequenceNRAck );
+
+// This class calls the ETW Begin and End functions in order to insert a
+// pair of events to bracket some work.
+class CETWScope
+{
+public:
+ CETWScope( const char *pMessage )
+ : m_pMessage( pMessage )
+ {
+ m_nStartTime = ETWBegin( pMessage );
+ }
+ ~CETWScope()
+ {
+ ETWEnd( m_pMessage, m_nStartTime );
+ }
+private:
+ // Private and unimplemented to disable copying.
+ CETWScope( const CETWScope& rhs );
+ CETWScope& operator=( const CETWScope& rhs );
+
+ const char* m_pMessage;
+ int64 m_nStartTime;
+};
+
+#else
+
+inline int64 ETWMark( const char* ) { return 0; }
+inline int64 ETWMarkPrintf( const char *, ... ) { return 0; }
+inline void ETWMark1F( const char *, float ) { }
+inline void ETWMark2F( const char *, float , float ) { }
+inline void ETWMark3F( const char *, float , float , float ) { }
+inline void ETWMark4F( const char *, float , float , float , float ) { }
+inline void ETWMark1I( const char *, int ) { }
+inline void ETWMark2I( const char *, int , int ) { }
+inline void ETWMark3I( const char *, int , int , int ) { }
+inline void ETWMark4I( const char *, int , int , int , int ) { }
+// Optionally specify one to two strings. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+inline void ETWMark1S( const char *, const char* ) { }
+inline void ETWMark2S( const char *, const char* , const char* ) { }
+
+inline int64 ETWBegin( const char* ) { return 0; }
+inline int64 ETWEnd( const char*, int64 ) { return 0; }
+inline void ETWRenderFrameMark( bool ) {}
+inline void ETWSimFrameMark( bool ) {}
+inline int ETWGetRenderFrameNumber() { return 0; }
+
+inline void ETWMouseDown( int nWhichButton, int nX, int nY ) {}
+inline void ETWMouseUp( int nWhichButton, int nX, int nY ) {}
+inline void ETWKeyDown( int nScanCode, int nVirtualCode, const char *pChar ) {}
+
+inline void ETWSendPacket( const char *pTo, int nWireSize, int nOutSequenceNR, int nOutSequenceNrAck ) {}
+inline void ETWThrottled() {}
+inline void ETWReadPacket( const char *pFrom, int nWireSize, int nInSequenceNR, int nOutSequenceNRAck ) {}
+
+// This class calls the ETW Begin and End functions in order to insert a
+// pair of events to bracket some work.
+class CETWScope
+{
+public:
+ CETWScope( const char* )
+ {
+ }
+private:
+ // Private and unimplemented to disable copying.
+ CETWScope( const CETWScope& rhs );
+ CETWScope& operator=( const CETWScope& rhs );
+};
+
+#endif
+
+#endif // ETWPROF_H
diff --git a/external/vpc/public/tier0/eventmasks.h b/external/vpc/public/tier0/eventmasks.h
new file mode 100644
index 0000000..4774809
--- /dev/null
+++ b/external/vpc/public/tier0/eventmasks.h
@@ -0,0 +1,480 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#pragma once
+
+typedef union EVENT_MASK(TC_deliver_mode)
+{
+ struct
+ {
+ uint16 DD:1; // both logical processors in deliver mode },
+ uint16 DB:1; // logical processor 0 in deliver mode, 1 in build mode },
+ uint16 DI:1; // logical processor 0 in deliver mode, 1 is inactive },
+ uint16 BD:1; // logical processor 0 in build mode, 1 in deliver mode },
+ uint16 BB:1; // both logical processors in build mode },
+ uint16 BI:1; // logical processor 0 in build mode, 1 is inactive },
+ uint16 ID:1; // logical processor 0 is inactive, 1 in deliver mode },
+ uint16 IB:1; // logical processor 0 is inactive, 1 in build mode }
+ };
+ uint16 flat;
+} EVENT_MASK(TC_deliver_mode);
+
+typedef union EVENT_MASK(BPU_fetch_request)
+{
+
+ struct
+ {
+ uint16 TCMISS:1; // Trace cache lookup miss },
+ };
+ uint16 flat;
+} EVENT_MASK(BPU_fetch_request);
+
+
+typedef union EVENT_MASK(ITLB_reference)
+{
+ struct
+ {
+ uint16 HIT : 1; //ITLB hit },
+ uint16 MISS : 1;//ITLB miss },
+ uint16 HIT_UC :1; // Uncacheable ITLB hit }
+ };
+ uint16 flat;
+} EVENT_MASK(ITLB_reference);
+
+typedef union EVENT_MASK(memory_cancel)
+{
+ struct
+ {
+ uint16 dummy : 2;
+
+ uint16 ST_RB_FULL:1; //Replayed because no store request buffer is available },
+ uint16 _64K_CONF:1; //Conflicts due to 64K aliasing }
+ };
+ uint16 flat;
+}EVENT_MASK(memory_cancel);
+
+typedef union EVENT_MASK(memory_complete)
+{
+ struct
+ {
+ uint16 LSC:1; // Load split completed, excluding UC/WC loads },
+ uint16 SSC:1; //Any split stores completed } }
+ };
+ uint16 flat;
+} EVENT_MASK(memory_complete);
+
+typedef union EVENT_MASK(load_port_replay)
+{
+ struct
+ {
+ uint16 dummy:1;
+ uint16 SPLIT_LD:1; //Split load } }
+ };
+ uint16 flat;
+} EVENT_MASK(load_port_replay);
+
+typedef union EVENT_MASK(store_port_replay)
+{
+ struct
+ {
+ uint16 dummy0:1;
+ uint16 SPLIT_ST:1; //Split store } }
+
+ };
+ uint16 flat;
+} EVENT_MASK(store_port_replay);
+
+typedef union EVENT_MASK(MOB_load_replay)
+{
+ struct
+ {
+ uint16 dummy0:1;
+
+ uint16 NO_STA:1; //Replayed because of unknown store address },
+
+ uint16 dummy2:1;
+
+ uint16 NO_STD:1; //Replayed because of unknown store data },
+ uint16 PARTIAL_DATA:1; //Replayed because of partially overlapped data access between the load and store operations },
+ uint16 UNALGN_ADDR:1; //Replayed because the lower 4 bits of the linear address do not match between the load and store operations } }
+ };
+ uint16 flat;
+}EVENT_MASK(MOB_load_replay);
+
+typedef union EVENT_MASK(page_walk_type)
+{
+ struct
+ {
+ uint16 DTMISS:1; // Page walk for a data TLB miss },
+ uint16 ITMISS:1; // Page walk for an instruction TLB miss } }
+ };
+ uint16 flat;
+}EVENT_MASK(page_walk_type);
+
+
+typedef union EVENT_MASK(BSQ_cache_reference)
+{
+ struct
+ {
+ uint16 RD_2ndL_HITS:1; // Read 2nd level cache hit Shared },
+ uint16 RD_2ndL_HITE:1; // Read 2nd level cache hit Exclusive },
+ uint16 RD_2ndL_HITM:1; // Read 2nd level cache hit Modified },
+ uint16 RD_3rdL_HITS:1; // Read 3rd level cache hit Shared },
+ uint16 RD_3rdL_HITE:1; // Read 3rd level cache hit Exclusive },
+ uint16 RD_3rdL_HITM:1; // Read 3rd level cache hit Modified },
+ uint16 dummy6:1;
+ uint16 dummy7:1;
+ uint16 RD_2ndL_MISS:1; // Read 2nd level cache miss },
+ uint16 RD_3rdL_MISS:1; // Read 3rd level cache miss },
+ uint16 WR_2ndL_MISS:1; // Writeback lookup from DAC misses the 2nd level cache } }
+ };
+ uint16 flat;
+} EVENT_MASK(BSQ_cache_reference) ;
+
+typedef union EVENT_MASK(IOQ)
+{
+ struct
+ {
+ uint16 bit0:1; // bus request type (use 00001 for invalid or default)
+ uint16 bit1:1; //
+ uint16 bit2:1; //
+ uint16 bit3:1; //
+ uint16 bit4:1; //
+ uint16 ALL_READ:1; // Count read entries },
+ uint16 ALL_WRITE:1; // Count write entries },
+ uint16 MEM_UC:1; // Count UC memory access entries },
+ uint16 MEM_WC:1; // Count WC memory access entries },
+ uint16 MEM_WT:1; // Count WT memory access entries },
+ uint16 MEM_WP:1; // Count WP memory access entries },
+ uint16 MEM_WB:1; // Count WB memory access entries },
+ uint16 dummy12:1;
+
+ uint16 OWN:1; // Count own store requests },
+ uint16 OTHER:1; // Count other and DMA store requests },
+ uint16 PREFETCH:1; // Include HW and SW prefetch requests } }
+ };
+ uint16 flat;
+} EVENT_MASK(IOQ) ;
+
+typedef union EVENT_MASK(FSB_data_activity)
+{
+ struct
+ {
+ /* DRDY_OWN is mutually exclusive with DRDY_OTHER */
+ /* DBSY_OWN is mutually exclusive with DBSY_OTHER */
+ uint16 DRDY_DRV:1; // Count when this processor drives data onto the bus },
+ uint16 DRDY_OWN:1; // Count when this processor reads data from the bus },
+ uint16 DRDY_OTHER:1; // Count when data is on the bus but not being sampled by the processor },
+ uint16 DBSY_DRV:1; // Count when this processor reserves the bus for driving data },
+ uint16 DBSY_OWN:1; // Count when this processor reserves the bus for sampling data },
+ uint16 DBSY_OTHER:1; // Count when the bus is reserved for driving data this processor will not sample } }
+ };
+ uint16 flat;
+}EVENT_MASK(FSB_data_activity);
+
+typedef union EVENT_MASK(BSQ)
+{
+ struct
+ {
+ uint16 REQ_TYPE0:1; // Request type encoding bit 0 },
+ uint16 REQ_TYPE1:1; // Request type encoding bit 1 },
+ uint16 REQ_LEN0:1; // Request length encoding bit 0 },
+ uint16 REQ_LEN1:1; // Request length encoding bit 1 },
+ uint16 dummy4: 1;
+ uint16 REQ_IO_TYPE:1; // Request type is input or output },
+ uint16 REQ_LOCK_TYPE:1; // Request type is bus lock },
+ uint16 REQ_CACHE_TYPE:1; // Request type is cacheable },
+ uint16 REQ_SPLIT_TYPE:1; // Request type is a bus 8-byte chunk split across 8-byte boundary },
+ uint16 REQ_DEM_TYPE:1; // Request type is a demand (1) or prefetch (0) },
+ uint16 REQ_ORD_TYPE:1; // Request is an ordered type },
+ uint16 MEM_TYPE0:1; // Memory type encoding bit 0 },
+ uint16 MEM_TYPE1:1; // Memory type encoding bit 1 },
+ uint16 MEM_TYPE2:1; // Memory type encoding bit 2 } }
+ };
+ uint16 flat;
+} EVENT_MASK(BSQ);
+
+typedef union EVENT_MASK(firm_uop)
+{
+ struct
+ {
+ uint16 dummy15 : 15;
+ uint16 ALL:1; // count all uops of this type } }
+ };
+ uint16 flat;
+} EVENT_MASK(firm_uop);
+
+
+
+typedef union EVENT_MASK(TC_misc)
+{
+ struct
+ {
+ uint16 dymmy4 : 4;
+ uint16 FLUSH:1; // Number of flushes } }
+ };
+ uint16 flat;
+} EVENT_MASK(TC_misc);
+
+typedef union EVENT_MASK(global_power_events)
+{
+ struct
+ {
+ uint16 Running:1; // The processor is active } }
+ };
+ uint16 flat;
+} EVENT_MASK(global_power_events);
+
+typedef union EVENT_MASK(tc_ms_xfer)
+{
+ struct
+ {
+ uint16 CISC:1; // A TC to MS transfer ocurred } }
+ };
+ uint16 flat;
+}EVENT_MASK(tc_ms_xfer);
+
+
+
+typedef union EVENT_MASK(uop_queue_writes)
+{
+ struct
+ {
+ uint16 FROM_TC_BUILD:1; // uops written from TC build mode
+ uint16 FROM_TC_DELIVER:1; // uops written from TC deliver mode
+ uint16 FROM_ROM:1; // uops written from microcode ROM } }
+ };
+ uint16 flat;
+} EVENT_MASK(uop_queue_writes);
+
+typedef union EVENT_MASK(branch_type)
+{
+ struct
+ {
+ uint16 dummy : 1;
+ uint16 CONDITIONAL:1; // Conditional jumps
+ uint16 CALL:1; // Direct or indirect call
+ uint16 RETURN:1; // Return branches
+ uint16 INDIRECT:1; // Returns, indirect calls, or indirect jumps
+ };
+ uint16 flat;
+} EVENT_MASK(branch_type);
+
+
+
+typedef union EVENT_MASK(resource_stall)
+{
+ struct
+ {
+ uint16 dummy1 : 5;
+ uint16 SBFULL:1; // A Stall due to lack of store buffers } }
+ };
+ uint16 flat;
+} EVENT_MASK(resource_stall);
+
+
+
+
+typedef union EVENT_MASK(WC_Buffer)
+{
+ struct
+ {
+ uint16 WCB_EVICTS : 1; // all causes },
+ uint16 WCB_FULL_EVICT : 1; // no WC buffer is available },
+ /* XXX: 245472-011 no longer lists bit 2, but that looks like
+ a table formatting error. Keeping it for now. */
+ uint16 WCB_HITM_EVICT : 1; // store encountered a Hit Modified condition } }
+ };
+ uint16 flat;
+} EVENT_MASK(WC_Buffer);
+
+
+typedef union EVENT_MASK(b2b_cycles)
+{
+ struct
+ {
+ uint16 dummy0 : 1;
+ uint16 bit1 : 1; //
+ uint16 bit2 : 1; //
+ uint16 bit3 : 1; //
+ uint16 bit4 : 1; //
+ uint16 bit5 : 1; //
+ uint16 bit6 : 1; //
+
+ };
+ uint16 flat;
+} EVENT_MASK(b2b_cycles);
+
+typedef union EVENT_MASK(bnr)
+{
+ struct
+ {
+ uint16 bit0:1; //
+ uint16 bit1:1; //
+ uint16 bit2:1; //
+ };
+ uint16 flat;
+} EVENT_MASK(bnr);
+
+
+typedef union EVENT_MASK(snoop)
+{
+ struct
+ {
+ uint16 dummy0 : 1;
+ uint16 dummy1 : 1;
+
+ uint16 bit2:1; //
+ uint16 dummy3:1; //
+ uint16 dummy4:1; //
+ uint16 dummy5:1; //
+ uint16 bit6:1; //
+ uint16 bit7:1; //
+ };
+ uint16 flat;
+} EVENT_MASK(snoop);
+
+
+typedef union EVENT_MASK(response)
+{
+ struct
+ {
+ uint16 dummy0:1; //
+ uint16 bit1:1; //
+ uint16 bit2:1; //
+ uint16 dummy3:1; //
+ uint16 dummy4:1; //
+ uint16 dummy5:1; //
+ uint16 dummy6:1; //
+ uint16 dummy7:1; //
+ uint16 bit8:1; //
+ uint16 bit9:1; //
+ };
+ uint16 flat;
+} EVENT_MASK(response);
+
+
+typedef union EVENT_MASK(nbogus_bogus)
+{
+ struct
+ {
+ uint16 NBOGUS:1; // The marked uops are not bogus
+ uint16 BOGUS:1; // The marked uops are bogus
+ };
+ uint16 flat;
+} EVENT_MASK(nbogus_bogus);
+
+
+typedef union EVENT_MASK(execution_event)
+{
+ struct
+ {
+ uint16 NBOGUS0:1; // non-bogus uops with tag bit 0 set },
+ uint16 NBOGUS1:1; // non-bogus uops with tag bit 1 set },
+ uint16 NBOGUS2:1; // non-bogus uops with tag bit 2 set },
+ uint16 NBOGUS3:1; // non-bogus uops with tag bit 3 set },
+ uint16 BOGUS0:1; // bogus uops with tag bit 0 set },
+ uint16 BOGUS1:1; // bogus uops with tag bit 1 set },
+ uint16 BOGUS2:1; // bogus uops with tag bit 2 set },
+ uint16 BOGUS3:1; // bogus uops with tag bit 3 set } }
+ };
+ uint16 flat;
+}EVENT_MASK(execution_event);
+
+typedef union EVENT_MASK(instr_retired)
+{
+ struct
+ {
+ uint16 NBOGUSNTAG:1; // Non-bogus instructions that are not tagged },
+ uint16 NBOGUSTAG:1; // Non-bogus instructions that are tagged },
+ uint16 BOGUSNTAG:1; // Bogus instructions that are not tagged },
+ uint16 BOGUSTAG:1; // Bogus instructions that are tagged } }
+ };
+ uint16 flat;
+} EVENT_MASK(instr_retired);
+
+
+typedef union EVENT_MASK(uop_type)
+{
+ struct
+ {
+ uint16 dummy0 : 1;
+ uint16 TAGLOADS:1; // The uop is a load operation },
+ uint16 TAGSTORES:1; // The uop is a store operation } }
+ };
+ uint16 flat;
+} EVENT_MASK(uop_type);
+
+typedef union EVENT_MASK(branch_retired)
+{
+ struct
+ {
+ uint16 MMNP:1; // Branch Not-taken Predicted
+ uint16 MMNM:1; // Branch Not-taken Mispredicted
+ uint16 MMTP:1; // Branch Taken Predicted
+ uint16 MMTM:1; // Branch Taken Mispredicted
+ };
+ uint16 flat;
+} EVENT_MASK(branch_retired);
+
+typedef union EVENT_MASK(mispred_branch_retired)
+{
+ struct
+ {
+ uint16 NBOGUS:1; // The retired branch is not bogus } }
+ };
+ uint16 flat;
+} EVENT_MASK(mispred_branch_retired);
+
+
+typedef union EVENT_MASK(x87_assist)
+{
+ struct
+ {
+ uint16 FPSU:1; // FP stack underflow },
+ uint16 FPSO:1; // FP stack overflow },
+ uint16 POAO:1; // x87 output overflow },
+ uint16 POAU:1; // x87 output underflow },
+ uint16 PREA:1; // x87 input assist } }
+ };
+ uint16 flat;
+}EVENT_MASK(x87_assist);
+
+typedef union EVENT_MASK(machine_clear)
+{
+ struct
+ {
+ uint16 CLEAR:1; // Count a portion of the cycles when the machine is cleared },
+ uint16 dummy1: 1;
+ uint16 MOCLEAR:1; // Count clears due to memory ordering issues },
+ uint16 dummy3: 1;
+ uint16 dummy4: 1;
+ uint16 dummy5: 1;
+
+ uint16 SMCLEAR:1;// Count clears due to self-modifying code issues } }
+ };
+ uint16 flat;
+} EVENT_MASK(machine_clear);
+
+
+typedef union EVENT_MASK(x87_SIMD_moves_uop)
+{
+ struct
+ {
+ uint16 dummy3:3;
+ uint16 ALLP0:1; // Count all x87/SIMD store/move uops },
+ uint16 ALLP2:1; // count all x87/SIMD load uops } }
+ };
+ uint16 flat;
+} EVENT_MASK(x87_SIMD_moves_uop);
+
+
+
+
+
+
+
diff --git a/external/vpc/public/tier0/eventmodes.h b/external/vpc/public/tier0/eventmodes.h
new file mode 100644
index 0000000..05e5b21
--- /dev/null
+++ b/external/vpc/public/tier0/eventmodes.h
@@ -0,0 +1,1787 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef EVENTMODES_H
+#define EVENTMODES_H
+
+
+#pragma once
+
+/*
+
+
+
+ Event Modes to choose from:
+
+ P4Event_TC_deliver_mode
+
+ P4Event_BPU_fetch_request
+
+ P4Event_ITLB_reference
+
+ P4Event_memory_cancel
+
+ P4Event_memory_complete
+
+ P4Event_load_port_replay
+
+ P4Event_store_port_replay
+
+ P4Event_MOB_load_replay
+
+ P4Event_page_walk_type
+
+ P4Event_BSQ_cache_reference
+
+ P4Event_IOQ_allocation
+
+ P4Event_IOQ_active_entries
+
+ P4Event_FSB_data_activity
+
+ P4Event_BSQ_allocation
+
+ P4Event_BSQ_active_entries
+
+ P4Event_SSE_input_assist
+
+ P4Event_packed_SP_uop
+
+ P4Event_packed_DP_uop
+
+ P4Event_scalar_SP_uop
+
+ P4Event_scalar_DP_uop
+
+ P4Event_64bit_MMX_uop
+
+ P4Event_128bit_MMX_uop
+
+ P4Event_x87_FP_uop
+
+ P4Event_x87_SIMD_moves_uop
+
+ P4Event_TC_misc
+
+ P4Event_global_power_events
+
+ P4Event_tc_ms_xfer
+
+ P4Event_uop_queue_writes
+
+ P4Event_retired_mispred_branch_type
+
+ P4Event_retired_branch_type
+
+ P4Event_resource_stall
+
+ P4Event_WC_Buffer
+
+ P4Event_b2b_cycles
+
+ P4Event_bnr
+
+ P4Event_snoop
+
+ P4Event_response
+
+ P4Event_front_end_event
+
+ P4Event_execution_event
+
+ P4Event_replay_event
+
+ P4Event_instr_retired
+
+ P4Event_uops_retired
+
+ P4Event_uop_type
+
+ P4Event_branch_retired
+
+ P4Event_mispred_branch_retired
+
+ P4Event_x87_assist
+
+ P4Event_machine_clear
+
+
+*/
+
+
+
+class P4P4Event_TC_deliver_mode: public P4BaseEvent
+{
+public:
+ EVENT_MASK(TC_deliver_mode) * eventMask;
+
+ P4P4Event_TC_deliver_mode()
+ {
+ eventMask = (EVENT_MASK(TC_deliver_mode) *)&m_eventMask;
+
+ escr.ESCREventSelect = 0x01;
+ cccr.CCCRSelect = 0x01;
+ //// eventType = EVENT_TYPE(TC_deliver_mode);
+ description = _T("TC_deliver_mode");
+ UseCounter4();
+ }
+
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+
+class P4P4Event_BPU_fetch_request: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BPU_fetch_request)* eventMask;
+
+ P4P4Event_BPU_fetch_request()
+ {
+ eventMask = (EVENT_MASK(BPU_fetch_request) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x00;
+ // eventType = EVENT_TYPE(BPU_fetch_request);
+ description=_T("BPU_fetch_request");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+
+};
+class P4P4Event_ITLB_reference: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(ITLB_reference) * eventMask;
+
+ P4P4Event_ITLB_reference()
+ {
+ eventMask = (EVENT_MASK(ITLB_reference) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x18;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(ITLB_reference);
+ description=_T("ITLB_reference");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_memory_cancel: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(memory_cancel) * eventMask;
+
+ P4Event_memory_cancel()
+ {
+ eventMask = (EVENT_MASK(memory_cancel) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(memory_cancel);
+ description=_T("memory_cancel");
+ UseCounter8();
+ }
+
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_memory_complete: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(memory_complete) * eventMask;
+
+ P4Event_memory_complete()
+ {
+ eventMask = (EVENT_MASK(memory_complete) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(memory_complete);
+ description=_T("memory_complete");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_load_port_replay: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(load_port_replay) * eventMask;
+
+ P4Event_load_port_replay()
+ {
+ eventMask = (EVENT_MASK(load_port_replay) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(load_port_replay);
+ description=_T("load_port_replay");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_store_port_replay: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(store_port_replay) * eventMask;
+
+ P4Event_store_port_replay()
+ {
+ eventMask = (EVENT_MASK(store_port_replay) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(store_port_replay);
+ description=_T("store_port_replay");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_MOB_load_replay: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(MOB_load_replay) * eventMask;
+
+ P4Event_MOB_load_replay()
+ {
+ eventMask = (EVENT_MASK(MOB_load_replay) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(MOB_load_replay);
+ description=_T("MOB_load_replay");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_page_walk_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(page_walk_type) * eventMask;
+
+ P4Event_page_walk_type()
+ {
+ eventMask = (EVENT_MASK(page_walk_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x01;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(page_walk_type);
+ description=_T("page_walk_type");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_BSQ_cache_reference: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BSQ_cache_reference) * eventMask;
+
+ P4Event_BSQ_cache_reference()
+ {
+ eventMask = (EVENT_MASK(BSQ_cache_reference) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0C;
+ cccr.CCCRSelect= 0x07;
+ // eventType=EVENT_TYPE(BSQ_cache_reference);
+ description=_T("BSQ_cache_reference");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_IOQ_allocation: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(IOQ) * eventMask;
+
+ P4Event_IOQ_allocation()
+ {
+ eventMask = (EVENT_MASK(IOQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(IOQ);
+ description=_T("IOQ_allocation");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_IOQ_active_entries: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(IOQ) * eventMask;
+
+ P4Event_IOQ_active_entries()
+ {
+ eventMask = (EVENT_MASK(IOQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x1A;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(IOQ);
+ description=_T("IOQ_active_entries");
+ UseCounter2();
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_FSB_data_activity: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(FSB_data_activity) * eventMask;
+
+ P4Event_FSB_data_activity()
+ {
+ eventMask = (EVENT_MASK(FSB_data_activity) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x17;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(FSB_data_activity);
+ description=_T("FSB_data_activity");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_BSQ_allocation: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BSQ) * eventMask;
+
+ P4Event_BSQ_allocation()
+ {
+ eventMask = (EVENT_MASK(BSQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x07;
+ // eventType=EVENT_TYPE(BSQ);
+ description=_T("BSQ_allocation");
+ UseCounter0();
+ }
+
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+
+ }
+};
+class P4Event_BSQ_active_entries: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BSQ) * eventMask;
+
+ P4Event_BSQ_active_entries()
+ {
+ eventMask = (EVENT_MASK(BSQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x07;
+ // eventType=EVENT_TYPE(BSQ);
+ description=_T("bsq_active_entries");
+ UseCounter2();
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_SSE_input_assist: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_SSE_input_assist()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x34;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("SSE_input_assist");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_packed_SP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_packed_SP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("packed_SP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_packed_DP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_packed_DP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0C;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("packed_DP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_scalar_SP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_scalar_SP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0A;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("scalar_SP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_scalar_DP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_scalar_DP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0E;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("scalar_DP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_64bit_MMX_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_64bit_MMX_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("64bit_MMX_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_128bit_MMX_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_128bit_MMX_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x1A;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("128bit_MMX_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_x87_FP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_x87_FP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("x87_FP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_x87_SIMD_moves_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(x87_SIMD_moves_uop) * eventMask;
+
+ P4Event_x87_SIMD_moves_uop()
+ {
+ eventMask = (EVENT_MASK(x87_SIMD_moves_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x2E;
+ cccr.CCCRSelect= 0;
+ // eventType=EVENT_TYPE(x87_SIMD_moves_uop);
+ description=_T("x87_SIMD_moves_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_TC_misc: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(TC_misc) * eventMask;
+
+ P4Event_TC_misc()
+ {
+ eventMask = (EVENT_MASK(TC_misc) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(TC_misc);
+ description=_T("TC_misc");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_global_power_events: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(global_power_events) * eventMask;
+
+ P4Event_global_power_events()
+ {
+ eventMask = (EVENT_MASK(global_power_events) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x13;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(global_power_events);
+ description=_T("global_power_events");
+ UseCounter0();
+ }
+
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_tc_ms_xfer: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(tc_ms_xfer) * eventMask;
+
+ P4Event_tc_ms_xfer()
+ {
+ eventMask = (EVENT_MASK(tc_ms_xfer) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x00;
+ // eventType=EVENT_TYPE(tc_ms_xfer);
+ description=_T("tc_ms_xfer");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_uop_queue_writes: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(uop_queue_writes) * eventMask;
+
+ P4Event_uop_queue_writes()
+ {
+ eventMask = (EVENT_MASK(uop_queue_writes) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x09;
+ cccr.CCCRSelect= 0x00;
+ // eventType=EVENT_TYPE(uop_queue_writes);
+ description=_T("uop_queue_writes");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_retired_mispred_branch_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(branch_type) * eventMask;
+
+ P4Event_retired_mispred_branch_type()
+ {
+ eventMask = (EVENT_MASK(branch_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(branch_type);
+ description=_T("retired_mispred_branch_type");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_retired_branch_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(branch_type) * eventMask;
+
+ P4Event_retired_branch_type()
+ {
+ eventMask = (EVENT_MASK(branch_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(branch_type);
+ description=_T("retired_branch_type");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_resource_stall: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(resource_stall) * eventMask;
+
+ P4Event_resource_stall()
+ {
+ eventMask = (EVENT_MASK(resource_stall) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x01;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(resource_stall);
+ description=_T("resource_stall");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+
+};
+class P4Event_WC_Buffer: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(WC_Buffer) * eventMask;
+
+ P4Event_WC_Buffer()
+ {
+ eventMask = (EVENT_MASK(WC_Buffer) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(WC_Buffer);
+ description=_T("WC_Buffer");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_b2b_cycles: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(b2b_cycles) * eventMask;
+
+ P4Event_b2b_cycles()
+ {
+ eventMask = (EVENT_MASK(b2b_cycles) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x16;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(b2b_cycles);
+ description=_T("b2b_cycles");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_bnr: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(bnr) * eventMask;
+
+ P4Event_bnr()
+ {
+ eventMask = (EVENT_MASK(bnr) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(bnr);
+ description=_T("bnr");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_snoop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(snoop) * eventMask;
+
+ P4Event_snoop()
+ {
+ eventMask = (EVENT_MASK(snoop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(snoop);
+ description=_T("snoop");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_response: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(response) * eventMask;
+
+ P4Event_response()
+ {
+ eventMask = (EVENT_MASK(response) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(response);
+ description=_T("response");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_front_end_event: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(nbogus_bogus) * eventMask;
+
+ P4Event_front_end_event()
+ {
+ eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(nbogus_bogus);
+ description=_T("front_end_event");
+ UseCounter12();
+ }
+
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_execution_event: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(execution_event) * eventMask;
+
+ P4Event_execution_event()
+ {
+ eventMask = (EVENT_MASK(execution_event) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0C;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(execution_event);
+ description=_T("execution_event");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_replay_event: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(nbogus_bogus) * eventMask;
+
+ P4Event_replay_event()
+ {
+ eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x09;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(nbogus_bogus);
+ description=_T("replay_event");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_instr_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(instr_retired) * eventMask;
+
+ P4Event_instr_retired()
+ {
+ eventMask = (EVENT_MASK(instr_retired) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(instr_retired);
+ description=_T("instr_retired");
+ UseCounter12();
+ }
+
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_uops_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(nbogus_bogus) * eventMask;
+
+ P4Event_uops_retired()
+ {
+ eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x01;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(nbogus_bogus);
+ description=_T("uops_retired");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_uop_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(uop_type) * eventMask;
+
+ P4Event_uop_type()
+ {
+ eventMask = (EVENT_MASK(uop_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(uop_type);
+ description=_T("uop_type");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_branch_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(branch_retired) * eventMask;
+
+ P4Event_branch_retired()
+ {
+ eventMask = (EVENT_MASK(branch_retired) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(branch_retired);
+ description=_T("branch_retired");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_mispred_branch_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(mispred_branch_retired) * eventMask;
+
+ P4Event_mispred_branch_retired()
+ {
+ eventMask = (EVENT_MASK(mispred_branch_retired) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(mispred_branch_retired);
+ description=_T("mispred_branch_retired");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_x87_assist: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(x87_assist) * eventMask;
+
+ P4Event_x87_assist()
+ {
+ eventMask = (EVENT_MASK(x87_assist) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(x87_assist);
+ description=_T("x87_assist");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_machine_clear: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(machine_clear) * eventMask;
+
+ P4Event_machine_clear()
+ {
+ eventMask = (EVENT_MASK(machine_clear) *)&m_eventMask;
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(machine_clear);
+ description=_T("machine_clear");
+ UseCounter12();
+ }
+
+
+
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+
+};
+
+#endif // EVENTMODES_H
diff --git a/external/vpc/public/tier0/fasttimer.h b/external/vpc/public/tier0/fasttimer.h
new file mode 100644
index 0000000..a820a60
--- /dev/null
+++ b/external/vpc/public/tier0/fasttimer.h
@@ -0,0 +1,625 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef FASTTIMER_H
+#define FASTTIMER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <assert.h>
+#include "tier0/platform.h"
+#ifdef _PS3
+#include "sys/sys_time.h"
+#else
+inline uint64 sys_time_get_timebase_frequency()
+{
+ DebuggerBreak(); // Error("sys_time_get_timebase_frequency called on non-PS3 platform.");
+ return 1; // this function should never ever be called.
+}
+#endif
+
+PLATFORM_INTERFACE uint64 g_ClockSpeed;
+PLATFORM_INTERFACE unsigned long g_dwClockSpeed;
+
+PLATFORM_INTERFACE double g_ClockSpeedMicrosecondsMultiplier;
+PLATFORM_INTERFACE double g_ClockSpeedMillisecondsMultiplier;
+PLATFORM_INTERFACE double g_ClockSpeedSecondsMultiplier;
+
+#ifdef COMPILER_MSVC64
+extern "C"
+{
+ unsigned __int64 __rdtsc();
+}
+
+#pragma intrinsic(__rdtsc)
+#endif
+
+class CCycleCount
+{
+ friend class CFastTimer;
+
+public:
+ CCycleCount();
+ CCycleCount( uint64 cycles );
+
+ void Sample(); // Sample the clock. This takes about 34 clocks to execute (or 26,000 calls per millisecond on a P900).
+
+ void Init(); // Set to zero.
+ void Init( float initTimeMsec );
+ void Init( double initTimeMsec ) { Init( (float)initTimeMsec ); }
+ void Init( uint64 cycles );
+ bool IsLessThan( CCycleCount const &other ) const; // Compare two counts.
+
+ // Convert to other time representations. These functions are slow, so it's preferable to call them
+ // during display rather than inside a timing block.
+ unsigned long GetCycles() const;
+ uint64 GetLongCycles() const;
+
+ unsigned long GetMicroseconds() const;
+ uint64 GetUlMicroseconds() const;
+ double GetMicrosecondsF() const;
+ void SetMicroseconds( unsigned long nMicroseconds );
+
+ unsigned long GetMilliseconds() const;
+ double GetMillisecondsF() const;
+
+ double GetSeconds() const;
+
+ CCycleCount& operator+=( CCycleCount const &other );
+
+ // dest = rSrc1 + rSrc2
+ static void Add( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together.
+
+ // dest = rSrc1 - rSrc2
+ static void Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together.
+
+ static uint64 GetTimestamp();
+
+ uint64 m_Int64;
+};
+
+class CClockSpeedInit
+{
+public:
+ CClockSpeedInit()
+ {
+ Init();
+ }
+
+ static void Init()
+ {
+ const CPUInformation& pi = GetCPUInformation();
+
+ if ( IsX360() )
+ {
+ // cycle counter runs as doc'd at 1/64 Xbox 3.2GHz clock speed, thus 50 Mhz
+ g_ClockSpeed = pi.m_Speed / 64L;
+ }
+ else if ( IsPS3() )
+ {
+ g_ClockSpeed = sys_time_get_timebase_frequency(); // CPU clock rate is totally unrelated to time base register frequency on PS3
+ }
+ else
+ {
+ g_ClockSpeed = pi.m_Speed;
+ }
+ g_dwClockSpeed = (unsigned long)g_ClockSpeed;
+
+ g_ClockSpeedMicrosecondsMultiplier = 1000000.0 / (double)g_ClockSpeed;
+ g_ClockSpeedMillisecondsMultiplier = 1000.0 / (double)g_ClockSpeed;
+ g_ClockSpeedSecondsMultiplier = 1.0f / (double)g_ClockSpeed;
+ }
+};
+
+class CFastTimer
+{
+public:
+ // These functions are fast to call and should be called from your sampling code.
+ void Start();
+ void End();
+
+ const CCycleCount & GetDuration() const; // Get the elapsed time between Start and End calls.
+ CCycleCount GetDurationInProgress() const; // Call without ending. Not that cheap.
+
+ // Return number of cycles per second on this processor.
+ static inline unsigned long GetClockSpeed();
+
+private:
+ CCycleCount m_Duration;
+#ifdef DEBUG_FASTTIMER
+ bool m_bRunning; // Are we currently running?
+#endif
+};
+
+
+// This is a helper class that times whatever block of code it's in
+class CTimeScope
+{
+public:
+ CTimeScope( CFastTimer *pTimer );
+ ~CTimeScope();
+
+private:
+ CFastTimer *m_pTimer;
+};
+
+inline CTimeScope::CTimeScope( CFastTimer *pTotal )
+{
+ m_pTimer = pTotal;
+ m_pTimer->Start();
+}
+
+inline CTimeScope::~CTimeScope()
+{
+ m_pTimer->End();
+}
+
+// This is a helper class that times whatever block of code it's in and
+// adds the total (int microseconds) to a global counter.
+class CTimeAdder
+{
+public:
+ CTimeAdder( CCycleCount *pTotal );
+ ~CTimeAdder();
+
+ void End();
+
+private:
+ CCycleCount *m_pTotal;
+ CFastTimer m_Timer;
+};
+
+inline CTimeAdder::CTimeAdder( CCycleCount *pTotal )
+{
+ m_pTotal = pTotal;
+ m_Timer.Start();
+}
+
+inline CTimeAdder::~CTimeAdder()
+{
+ End();
+}
+
+inline void CTimeAdder::End()
+{
+ if( m_pTotal )
+ {
+ m_Timer.End();
+ *m_pTotal += m_Timer.GetDuration();
+ m_pTotal = 0;
+ }
+}
+
+
+
+// -------------------------------------------------------------------------- //
+// Simple tool to support timing a block of code, and reporting the results on
+// program exit or at each iteration
+//
+// Macros used because dbg.h uses this header, thus Msg() is unavailable
+// -------------------------------------------------------------------------- //
+
+#define PROFILE_SCOPE(name) \
+ class C##name##ACC : public CAverageCycleCounter \
+ { \
+ public: \
+ ~C##name##ACC() \
+ { \
+ Msg("%-48s: %6.3f avg (%8.1f total, %7.3f peak, %5d iters)\n", \
+ #name, \
+ GetAverageMilliseconds(), \
+ GetTotalMilliseconds(), \
+ GetPeakMilliseconds(), \
+ GetIters() ); \
+ } \
+ }; \
+ static C##name##ACC name##_ACC; \
+ CAverageTimeMarker name##_ATM( &name##_ACC )
+
+#define TIME_SCOPE(name) \
+ class CTimeScopeMsg_##name \
+ { \
+ public: \
+ CTimeScopeMsg_##name() { m_Timer.Start(); } \
+ ~CTimeScopeMsg_##name() \
+ { \
+ m_Timer.End(); \
+ Msg( #name "time: %.4fms\n", m_Timer.GetDuration().GetMillisecondsF() ); \
+ } \
+ private: \
+ CFastTimer m_Timer; \
+ } name##_TSM;
+
+
+// -------------------------------------------------------------------------- //
+
+class CAverageCycleCounter
+{
+public:
+ CAverageCycleCounter();
+
+ void Init();
+ void MarkIter( const CCycleCount &duration );
+
+ unsigned GetIters() const;
+
+ double GetAverageMilliseconds() const;
+ double GetTotalMilliseconds() const;
+ double GetPeakMilliseconds() const;
+
+private:
+ unsigned m_nIters;
+ CCycleCount m_Total;
+ CCycleCount m_Peak;
+ bool m_fReport;
+ const tchar *m_pszName;
+};
+
+// -------------------------------------------------------------------------- //
+
+class CAverageTimeMarker
+{
+public:
+ CAverageTimeMarker( CAverageCycleCounter *pCounter );
+ ~CAverageTimeMarker();
+
+private:
+ CAverageCycleCounter *m_pCounter;
+ CFastTimer m_Timer;
+};
+
+
+// -------------------------------------------------------------------------- //
+// CCycleCount inlines.
+// -------------------------------------------------------------------------- //
+
+inline CCycleCount::CCycleCount()
+{
+ Init( (uint64)0 );
+}
+
+inline CCycleCount::CCycleCount( uint64 cycles )
+{
+ Init( cycles );
+}
+
+inline void CCycleCount::Init()
+{
+ Init( (uint64)0 );
+}
+
+inline void CCycleCount::Init( float initTimeMsec )
+{
+ if ( g_ClockSpeedMillisecondsMultiplier > 0 )
+ Init( (uint64)(initTimeMsec / g_ClockSpeedMillisecondsMultiplier) );
+ else
+ Init( (uint64)0 );
+}
+
+inline void CCycleCount::Init( uint64 cycles )
+{
+ m_Int64 = cycles;
+}
+
+#if !COMPILER_GCC
+#pragma warning(push)
+#pragma warning(disable : 4189) // warning C4189: local variable is initialized but not referenced
+#endif
+
+inline void CCycleCount::Sample()
+{
+#ifdef COMPILER_MSVC64
+ unsigned __int64* pSample = (unsigned __int64*)&m_Int64;
+ *pSample = __rdtsc();
+ // Msg( "Sample = %I64x", pSample );
+#elif defined( _X360 )
+ // only need lower 32 bits, avoids doc'd read bug and 32 bit rollover is in 85 seconds
+ m_Int64 = (uint64)__mftb32();
+ // scale back up, needs to be viewed as 1 cycle/clock
+#elif defined( _PS3 )
+ // only need lower 32 bits, avoids doc'd read bug and 32 bit rollover is in 85 seconds
+ m_Int64 = (uint64)__mftb();
+ // scale back up, needs to be viewed as 1 cycle/clock
+#elif defined( __GNUC__ )
+ union
+ {
+ unsigned long* pSample;
+ uint64 * pInt64;
+ } tmp;
+ tmp.pInt64 = &m_Int64;
+ __asm__ __volatile__ (
+ "rdtsc\n\t"
+ "movl %%eax, (%0)\n\t"
+ "movl %%edx, 4(%0)\n\t"
+ : /* no output regs */
+ : "D" (tmp.pSample)
+ : "%eax", "%edx" );
+#elif defined( _WIN32 )
+ unsigned long* pSample = (unsigned long *)&m_Int64;
+ __asm
+ {
+ // force the cpu to synchronize the instruction queue
+ // NJS: CPUID can really impact performance in tight loops.
+ //cpuid
+ //cpuid
+ //cpuid
+ mov ecx, pSample
+ rdtsc
+ mov [ecx], eax
+ mov [ecx+4], edx
+ }
+#elif defined( POSIX )
+ unsigned long* pSample = (unsigned long *)&m_Int64;
+ __asm__ __volatile__ (
+ "rdtsc\n\t"
+ "movl %%eax, (%0)\n\t"
+ "movl %%edx, 4(%0)\n\t"
+ : /* no output regs */
+ : "D" (pSample)
+ : "%eax", "%edx" );
+#endif
+}
+
+#if !COMPILER_GCC
+#pragma warning(pop)
+#endif
+
+inline CCycleCount& CCycleCount::operator+=( CCycleCount const &other )
+{
+ m_Int64 += other.m_Int64;
+ return *this;
+}
+
+
+inline void CCycleCount::Add( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest )
+{
+ dest.m_Int64 = rSrc1.m_Int64 + rSrc2.m_Int64;
+}
+
+inline void CCycleCount::Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest )
+{
+ dest.m_Int64 = rSrc1.m_Int64 - rSrc2.m_Int64;
+}
+
+inline uint64 CCycleCount::GetTimestamp()
+{
+ CCycleCount c;
+ c.Sample();
+ return c.GetLongCycles();
+}
+
+inline bool CCycleCount::IsLessThan(CCycleCount const &other) const
+{
+ return m_Int64 < other.m_Int64;
+}
+
+
+inline unsigned long CCycleCount::GetCycles() const
+{
+ return (unsigned long)m_Int64;
+}
+
+inline uint64 CCycleCount::GetLongCycles() const
+{
+ return m_Int64;
+}
+
+inline unsigned long CCycleCount::GetMicroseconds() const
+{
+ return (unsigned long)((m_Int64 * 1000000) / g_ClockSpeed);
+}
+
+inline uint64 CCycleCount::GetUlMicroseconds() const
+{
+ return ((m_Int64 * 1000000) / g_ClockSpeed);
+}
+
+
+inline double CCycleCount::GetMicrosecondsF() const
+{
+ return (double)( m_Int64 * g_ClockSpeedMicrosecondsMultiplier );
+}
+
+
+inline void CCycleCount::SetMicroseconds( unsigned long nMicroseconds )
+{
+ m_Int64 = ((uint64)nMicroseconds * g_ClockSpeed) / 1000000;
+}
+
+
+inline unsigned long CCycleCount::GetMilliseconds() const
+{
+ return (unsigned long)((m_Int64 * 1000) / g_ClockSpeed);
+}
+
+
+inline double CCycleCount::GetMillisecondsF() const
+{
+ return (double)( m_Int64 * g_ClockSpeedMillisecondsMultiplier );
+}
+
+
+inline double CCycleCount::GetSeconds() const
+{
+ return (double)( m_Int64 * g_ClockSpeedSecondsMultiplier );
+}
+
+
+// -------------------------------------------------------------------------- //
+// CFastTimer inlines.
+// -------------------------------------------------------------------------- //
+inline void CFastTimer::Start()
+{
+ m_Duration.Sample();
+#ifdef DEBUG_FASTTIMER
+ m_bRunning = true;
+#endif
+}
+
+
+inline void CFastTimer::End()
+{
+ CCycleCount cnt;
+ cnt.Sample();
+ if ( IsX360() )
+ {
+ // have to handle rollover, hires timer is only accurate to 32 bits
+ // more than one overflow should not have occurred, otherwise caller should use a slower timer
+ if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 )
+ {
+ // rollover occurred
+ cnt.m_Int64 += 0x100000000LL;
+ }
+ }
+
+ m_Duration.m_Int64 = cnt.m_Int64 - m_Duration.m_Int64;
+
+#ifdef DEBUG_FASTTIMER
+ m_bRunning = false;
+#endif
+}
+
+inline CCycleCount CFastTimer::GetDurationInProgress() const
+{
+ CCycleCount cnt;
+ cnt.Sample();
+ if ( IsX360() )
+ {
+ // have to handle rollover, hires timer is only accurate to 32 bits
+ // more than one overflow should not have occurred, otherwise caller should use a slower timer
+ if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 )
+ {
+ // rollover occurred
+ cnt.m_Int64 += 0x100000000LL;
+ }
+ }
+
+ CCycleCount result;
+ result.m_Int64 = cnt.m_Int64 - m_Duration.m_Int64;
+
+ return result;
+}
+
+
+inline unsigned long CFastTimer::GetClockSpeed()
+{
+ return g_dwClockSpeed;
+}
+
+
+inline CCycleCount const& CFastTimer::GetDuration() const
+{
+#ifdef DEBUG_FASTTIMER
+ assert( !m_bRunning );
+#endif
+ return m_Duration;
+}
+
+
+// -------------------------------------------------------------------------- //
+// CAverageCycleCounter inlines
+
+inline CAverageCycleCounter::CAverageCycleCounter()
+ : m_nIters( 0 )
+{
+}
+
+inline void CAverageCycleCounter::Init()
+{
+ m_Total.Init();
+ m_Peak.Init();
+ m_nIters = 0;
+}
+
+inline void CAverageCycleCounter::MarkIter( const CCycleCount &duration )
+{
+ ++m_nIters;
+ m_Total += duration;
+ if ( m_Peak.IsLessThan( duration ) )
+ m_Peak = duration;
+}
+
+inline unsigned CAverageCycleCounter::GetIters() const
+{
+ return m_nIters;
+}
+
+inline double CAverageCycleCounter::GetAverageMilliseconds() const
+{
+ if ( m_nIters )
+ return (m_Total.GetMillisecondsF() / (double)m_nIters);
+ else
+ return 0;
+}
+
+inline double CAverageCycleCounter::GetTotalMilliseconds() const
+{
+ return m_Total.GetMillisecondsF();
+}
+
+inline double CAverageCycleCounter::GetPeakMilliseconds() const
+{
+ return m_Peak.GetMillisecondsF();
+}
+
+// -------------------------------------------------------------------------- //
+
+inline CAverageTimeMarker::CAverageTimeMarker( CAverageCycleCounter *pCounter )
+{
+ m_pCounter = pCounter;
+ m_Timer.Start();
+}
+
+inline CAverageTimeMarker::~CAverageTimeMarker()
+{
+ m_Timer.End();
+ m_pCounter->MarkIter( m_Timer.GetDuration() );
+}
+
+
+// CLimitTimer
+// Use this to time whether a desired interval of time has passed. It's extremely fast
+// to check while running.
+class CLimitTimer
+{
+public:
+ void SetLimit( uint64 m_cMicroSecDuration );
+ bool BLimitReached( void );
+
+private:
+ uint64 m_lCycleLimit;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Initializes the limit timer with a period of time to measure.
+// Input : cMicroSecDuration - How long a time period to measure
+//-----------------------------------------------------------------------------
+inline void CLimitTimer::SetLimit( uint64 m_cMicroSecDuration )
+{
+ uint64 dlCycles = ( ( uint64 ) m_cMicroSecDuration * ( uint64 ) g_dwClockSpeed ) / ( uint64 ) 1000000L;
+ CCycleCount cycleCount;
+ cycleCount.Sample( );
+ m_lCycleLimit = cycleCount.GetLongCycles( ) + dlCycles;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Determines whether our specified time period has passed
+// Output: true if at least the specified time period has passed
+//-----------------------------------------------------------------------------
+inline bool CLimitTimer::BLimitReached( )
+{
+ CCycleCount cycleCount;
+ cycleCount.Sample( );
+ return ( cycleCount.GetLongCycles( ) >= m_lCycleLimit );
+}
+
+
+
+#endif // FASTTIMER_H
diff --git a/external/vpc/public/tier0/ia32detect.h b/external/vpc/public/tier0/ia32detect.h
new file mode 100644
index 0000000..e4a63a7
--- /dev/null
+++ b/external/vpc/public/tier0/ia32detect.h
@@ -0,0 +1,383 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+#ifndef IA32DETECT_H
+#define IA32DETECT_H
+
+#ifdef COMPILER_MSVC64
+extern "C" void __cpuid(int* CPUInfo, int InfoType);
+#pragma intrinsic (__cpuid)
+#endif
+/*
+ This section from http://iss.cs.cornell.edu/ia32.htm
+
+
+ */
+typedef unsigned bit;
+
+enum CPUVendor
+{
+ INTEL,
+ AMD,
+ UNKNOWN_VENDOR
+};
+class ia32detect
+{
+public:
+
+ enum type_t
+ {
+ type_OEM,
+ type_OverDrive,
+ type_Dual,
+ type_reserved
+ };
+
+ enum brand_t
+ {
+ brand_na,
+ brand_Celeron,
+ brand_PentiumIII,
+ brand_PentiumIIIXeon,
+ brand_reserved1,
+ brand_reserved2,
+ brand_PentiumIIIMobile,
+ brand_reserved3,
+ brand_Pentium4,
+ brand_invalid
+ };
+
+# pragma pack(push, 1)
+
+ struct version_t
+ {
+ bit Stepping : 4;
+ bit Model : 4;
+ bit Family : 4;
+ bit Type : 2;
+ bit Reserved1 : 2;
+ bit XModel : 4;
+ bit XFamily : 8;
+ bit Reserved2 : 4;
+ };
+
+ struct misc_t
+ {
+ byte Brand;
+ byte CLFLUSH;
+ byte Reserved;
+ byte APICId;
+ };
+
+ struct feature_t
+ {
+ bit FPU : 1; // Floating Point Unit On-Chip
+ bit VME : 1; // Virtual 8086 Mode Enhancements
+ bit DE : 1; // Debugging Extensions
+ bit PSE : 1; // Page Size Extensions
+ bit TSC : 1; // Time Stamp Counter
+ bit MSR : 1; // Model Specific Registers
+ bit PAE : 1; // Physical Address Extension
+ bit MCE : 1; // Machine Check Exception
+ bit CX8 : 1; // CMPXCHG8 Instruction
+ bit APIC : 1; // APIC On-Chip
+ bit Reserved1 : 1;
+ bit SEP : 1; // SYSENTER and SYSEXIT instructions
+ bit MTRR : 1; // Memory Type Range Registers
+ bit PGE : 1; // PTE Global Bit
+ bit MCA : 1; // Machine Check Architecture
+ bit CMOV : 1; // Conditional Move Instructions
+ bit PAT : 1; // Page Attribute Table
+ bit PSE36 : 1; // 32-bit Page Size Extension
+ bit PSN : 1; // Processor Serial Number
+ bit CLFSH : 1; // CLFLUSH Instruction
+ bit Reserved2 : 1;
+ bit DS : 1; // Debug Store
+ bit ACPI : 1; // Thermal Monitor and Software Controlled Clock Facilities
+ bit MMX : 1; // Intel MMX Technology
+ bit FXSR : 1; // FXSAVE and FXRSTOR Instructions
+ bit SSE : 1; // Intel SSE Technology
+ bit SSE2 : 1; // Intel SSE2 Technology
+ bit SS : 1; // Self Snoop
+ bit HTT : 1; // Hyper Threading
+ bit TM : 1; // Thermal Monitor
+ bit Reserved3 : 1;
+ bit PBE : 1; // Pending Brk. EN.
+ };
+
+# pragma pack(pop)
+
+ tstring vendor_name;
+ CPUVendor vendor;
+ tstring brand;
+ version_t version;
+ misc_t misc;
+ feature_t feature;
+ byte *cache;
+
+ ia32detect ()
+ {
+
+ cache = 0;
+ uint32 m = init0();
+
+ uint32 *d = new uint32[m * 4];
+
+ for (uint32 i = 1; i <= m; i++)
+ {
+
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) (d + (i-1) * 4), i);
+
+#else
+ uint32 *t = d + (i - 1) * 4;
+ __asm
+ {
+ mov eax, i;
+ mov esi, t;
+
+ cpuid;
+
+ mov dword ptr [esi + 0x0], eax;
+ mov dword ptr [esi + 0x4], ebx;
+ mov dword ptr [esi + 0x8], ecx;
+ mov dword ptr [esi + 0xC], edx;
+ }
+#endif
+ }
+
+ if (m >= 1)
+ init1(d);
+
+ if (m >= 2)
+ init2(d[4] & 0xFF);
+
+ delete [] d;
+
+ init0x80000000();
+
+
+ //-----------------------------------------------------------------------
+ // Get the vendor of the processor
+ //-----------------------------------------------------------------------
+ if (_tcscmp(vendor_name.c_str(), _T("GenuineIntel")) == 0)
+ {
+ vendor = INTEL;
+
+ }
+ else if (_tcscmp(vendor_name.c_str(), _T("AuthenticAMD")) == 0)
+ {
+ vendor = AMD;
+
+ }
+ else
+ {
+ vendor = UNKNOWN_VENDOR;
+ }
+ }
+
+ const tstring version_text () const
+ {
+ tchar b[128];
+
+ _stprintf(b, _T("%d.%d.%d %s XVersion(%d.%d)"),
+ version.Family, version.Model, version.Stepping, type_text(), version.XFamily, version.XModel);
+
+ return tstring(b);
+ }
+
+protected:
+
+ const tchar * type_text () const
+ {
+ static const tchar *text[] =
+ {
+ _T("Intel OEM Processor"),
+ _T("Intel OverDrive(R) Processor"),
+ _T("Intel Dual Processor"),
+ _T("reserved")
+ };
+
+ return text[version.Type];
+ }
+
+ const tstring brand_text () const
+ {
+ static const tchar *text[] =
+ {
+ _T("n/a"),
+ _T("Celeron"),
+ _T("Pentium III"),
+ _T("Pentium III Xeon"),
+ _T("reserved (4)"),
+ _T("reserved (5)"),
+ _T("Pentium III Mobile"),
+ _T("reserved (7)"),
+ _T("Pentium 4")
+ };
+
+ if (misc.Brand < brand_invalid)
+ return tstring(text[misc.Brand]);
+ else
+ {
+ tchar b[32];
+
+ _stprintf(b, _T("Brand %d (Update)"), misc.Brand);
+
+ return tstring(b);
+ }
+ }
+
+private:
+
+ uint32 init0 ()
+ {
+ uint32 m;
+
+#ifdef COMPILER_MSVC64
+ int data[4];
+ tchar * s1;
+
+ s1 = (tchar *) &data[1];
+ s1[12] = '\0';
+ __cpuid(data, 0);
+ m = data[0];
+ vendor_name = s1;
+#else
+ tchar s1[13];
+
+ s1[12] = '\0';
+ __asm
+ {
+ xor eax, eax;
+ cpuid;
+ mov m, eax;
+ mov dword ptr s1 + 0, ebx;
+ mov dword ptr s1 + 4, edx;
+ mov dword ptr s1 + 8, ecx;
+ }
+ vendor_name = s1;
+#endif
+ return m;
+ }
+
+ void init1 (uint32 *d)
+ {
+ version = *(version_t *)&d[0];
+ misc = *(misc_t *)&d[1];
+ feature = *(feature_t *)&d[3];
+ }
+
+ void process2 (uint32 d, bool c[])
+ {
+ if ((d & 0x80000000) == 0)
+ for (int i = 0; i < 32; i += 8)
+ c[(d >> i) & 0xFF] = true;
+ }
+
+ void init2 (byte count)
+ {
+ uint32 d[4];
+ bool c[256];
+
+ for (int ci1 = 0; ci1 < 256; ci1++)
+ c[ci1] = false;
+
+ for (int i = 0; i < count; i++)
+ {
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) d, 2);
+#else
+ __asm
+ {
+ mov eax, 2;
+ lea esi, d;
+ cpuid;
+ mov [esi + 0x0], eax;
+ mov [esi + 0x4], ebx;
+ mov [esi + 0x8], ecx;
+ mov [esi + 0xC], edx;
+ }
+#endif
+
+ if (i == 0)
+ d[0] &= 0xFFFFFF00;
+
+ process2(d[0], c);
+ process2(d[1], c);
+ process2(d[2], c);
+ process2(d[3], c);
+ }
+
+ int m = 0;
+
+ for (int ci2 = 0; ci2 < 256; ci2++)
+ if (c[ci2])
+ m++;
+
+ cache = new byte[m];
+
+ m = 0;
+
+ for (int ci3 = 1; ci3 < 256; ci3++)
+ if (c[ci3])
+ cache[m++] = ci3;
+
+ cache[m] = 0;
+ }
+
+ void init0x80000000 ()
+ {
+ uint32 m;
+
+#ifdef COMPILER_MSVC64
+ int data[4];
+ __cpuid(data, 0x80000000);
+ m = data[0];
+#else
+ __asm
+ {
+ mov eax, 0x80000000;
+ cpuid;
+ mov m, eax
+ }
+#endif
+
+ if ((m & 0x80000000) != 0)
+ {
+ uint32 *d = new uint32[(m - 0x80000000) * 4];
+
+ for (uint32 i = 0x80000001; i <= m; i++)
+ {
+ uint32 *t = d + (i - 0x80000001) * 4;
+
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) (d + (i - 0x80000001) * 4), i);
+#else
+ __asm
+ {
+ mov eax, i;
+ mov esi, t;
+ cpuid;
+ mov dword ptr [esi + 0x0], eax;
+ mov dword ptr [esi + 0x4], ebx;
+ mov dword ptr [esi + 0x8], ecx;
+ mov dword ptr [esi + 0xC], edx;
+ }
+#endif
+ }
+
+ if (m >= 0x80000002)
+ brand = (tchar *)(d + 4);
+
+ // note the assignment to brand above does a copy, we need to delete
+ delete[] d;
+ }
+ }
+};
+
+#endif // IA32DETECT_H
diff --git a/external/vpc/public/tier0/icommandline.h b/external/vpc/public/tier0/icommandline.h
new file mode 100644
index 0000000..d56d5a3
--- /dev/null
+++ b/external/vpc/public/tier0/icommandline.h
@@ -0,0 +1,65 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef TIER0_ICOMMANDLINE_H
+#define TIER0_ICOMMANDLINE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Interface to engine command line
+//-----------------------------------------------------------------------------
+abstract_class ICommandLine
+{
+public:
+ virtual void CreateCmdLine( const char *commandline ) = 0;
+ virtual void CreateCmdLine( int argc, char **argv ) = 0;
+ virtual const char *GetCmdLine( void ) const = 0;
+
+ // Check whether a particular parameter exists
+ virtual const char *CheckParm( const char *psz, const char **ppszValue = 0 ) const = 0;
+ virtual void RemoveParm( const char *parm ) = 0;
+ virtual void AppendParm( const char *pszParm, const char *pszValues ) = 0;
+
+ // Returns the argument after the one specified, or the default if not found
+ virtual const char *ParmValue( const char *psz, const char *pDefaultVal = 0 ) const = 0;
+ virtual int ParmValue( const char *psz, int nDefaultVal ) const = 0;
+ virtual float ParmValue( const char *psz, float flDefaultVal ) const = 0;
+
+ // Gets at particular parameters
+ virtual int ParmCount() const = 0;
+ virtual int FindParm( const char *psz ) const = 0; // Returns 0 if not found.
+ virtual const char* GetParm( int nIndex ) const = 0;
+
+ // copies the string passwed
+ virtual void SetParm( int nIndex, char const *pNewParm ) =0;
+};
+
+//-----------------------------------------------------------------------------
+// Gets a singleton to the commandline interface
+// NOTE: The #define trickery here is necessary for backwards compat:
+// this interface used to lie in the vstdlib library.
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE ICommandLine *CommandLine();
+
+
+//-----------------------------------------------------------------------------
+// Process related functions
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE const tchar *Plat_GetCommandLine();
+#ifndef _WIN32
+// helper function for OS's that don't have a ::GetCommandLine() call
+PLATFORM_INTERFACE void Plat_SetCommandLine( const char *cmdLine );
+#endif
+PLATFORM_INTERFACE const char *Plat_GetCommandLineA();
+
+
+#endif // TIER0_ICOMMANDLINE_H
+
diff --git a/external/vpc/public/tier0/ioctlcodes.h b/external/vpc/public/tier0/ioctlcodes.h
new file mode 100644
index 0000000..7fc8efb
--- /dev/null
+++ b/external/vpc/public/tier0/ioctlcodes.h
@@ -0,0 +1,29 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef IOCTLCODES_H
+#define IOCTLCODES_H
+#pragma once
+
+// Define the IOCTL codes we will use. The IOCTL code contains a command
+// identifier, plus other information about the device, the type of access
+// with which the file must have been opened, and the type of buffering.
+
+// Device type -- in the "User Defined" range."
+#define DEVICE_FILE_TYPE 40000
+
+
+// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
+
+#define IOCTL_WRITE_MSR \
+ CTL_CODE( DEVICE_FILE_TYPE, 0x900, METHOD_BUFFERED, FILE_READ_ACCESS )
+
+#define IOCTL_READ_MSR \
+ CTL_CODE( DEVICE_FILE_TYPE, 0x901, METHOD_BUFFERED, FILE_READ_ACCESS )
+
+
+#endif IOCTLCODES_H
diff --git a/external/vpc/public/tier0/k8performancecounters.h b/external/vpc/public/tier0/k8performancecounters.h
new file mode 100644
index 0000000..d405a8d
--- /dev/null
+++ b/external/vpc/public/tier0/k8performancecounters.h
@@ -0,0 +1,2040 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+#ifndef K8PERFORMANCECOUNTERS_H
+#define K8PERFORMANCECOUNTERS_H
+
+/*
+ * AMD K8 events.
+ *
+ */
+
+#ifdef COMPILER_MSVC64
+extern "C"
+{
+ unsigned __int64 __readpmc(unsigned long);
+}
+
+#pragma intrinsic(__readpmc)
+#endif
+
+
+typedef union EVENT_MASK(NULL_MASK)
+{
+ // no tests defined
+ uint16 flat;
+} EVENT_MASK(NULL_MASK);
+
+
+#define MSR_K8_EVNTSEL0 0xC0010000 /* .. 0xC0010003 */
+#define MSR_K8_PERFCTR0 0xC0010004 /* .. 0xC0010007 */
+
+# pragma pack(push, 1)
+
+
+
+// access to these bits is through the methods
+typedef union PerfEvtSel
+{
+ struct
+ {
+ uint64 EventMask : 8;
+
+ uint64 UnitMask : 8;
+ uint64 USR : 1;
+ uint64 OS : 1;
+ uint64 Edge : 1;
+ uint64 PC : 1;
+ uint64 INTAPIC : 1;
+ uint64 Reserved21 : 1;
+ uint64 Enable : 1;
+ uint64 Complement : 1; // aka INV
+ uint64 Threshold : 8; // aka CounterMask
+ uint64 Reserver32 : 32;
+ };
+ uint64 flat;
+
+} PerfEvtSel;
+
+
+enum UnitEncode
+{
+ FP,
+ LS,
+ DC,
+ BU,
+ IC,
+ UE_Unknown,
+ FR,
+ NB
+};
+
+# pragma pack(pop)
+
+// Turn off the no return value warning in ReadCounter.
+#pragma warning( disable : 4035 )
+#define k8NUM_COUNTERS 4
+class k8BaseEvent
+{
+public:
+
+ PME * pme;
+
+ PerfEvtSel eventSelect[k8NUM_COUNTERS];
+
+ unsigned short m_eventMask;
+ int event_id;
+ tchar * name;
+ tchar revRequired;
+ int eventSelectNum;
+ UnitEncode unitEncode;
+
+
+ void SetCounter(int n)
+ {
+ if (n < 0)
+ n = 0;
+ else if (n > 3)
+ n = 3;
+ eventSelectNum = n;
+
+ }
+ k8BaseEvent()
+ {
+ pme = PME::Instance();
+
+ for(int i = 0; i< k8NUM_COUNTERS; i++)
+ {
+ eventSelect[i].flat = 0;
+
+ }
+ eventSelectNum = 0;
+
+ m_eventMask = 0;
+ event_id = 0;
+ name = 0;
+ revRequired = 'A';
+
+
+ }
+
+ void SetCaptureMode(PrivilegeCapture priv)
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+ StopCounter();
+
+ switch (priv)
+ {
+ case OS_Only:
+ select.USR = 0;
+ select.OS = 1;
+ break;
+
+ case USR_Only:
+ select.USR = 1;
+ select.OS = 0;
+ break;
+
+ case OS_and_USR:
+ select.USR = 1;
+ select.OS = 1;
+ break;
+ }
+
+
+ select.UnitMask = m_eventMask;
+ select.EventMask = event_id;
+
+
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+ pme->WriteMSR(selectPort, select.flat);
+ }
+
+
+ void SetFiltering(CompareState compareEnable,
+ CompareMethod compareMethod,
+ uint8 threshold,
+ EdgeState edgeEnable)
+ {
+
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ StopCounter();
+
+ if (compareEnable == CompareDisable)
+ select.Threshold = 0;
+ else
+ select.Threshold = threshold;
+
+ select.Complement = compareMethod;
+
+ select.Edge = edgeEnable;
+
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+ pme->WriteMSR(selectPort, select.flat);
+
+
+ }
+
+
+ void StartCounter()
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ select.Enable = 1;
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+
+ pme->WriteMSR(selectPort, select.flat);
+
+ }
+ void StopCounter()
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+ select.Enable = 0;
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+
+ pme->WriteMSR(selectPort, select.flat);
+ }
+
+
+
+ void ClearCounter()
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ int counterPort = MSR_K8_PERFCTR0 + eventSelectNum;
+
+ pme->WriteMSR(counterPort, 0ui64 ); // clear
+ }
+
+ void WriteCounter(int64 value)
+ {
+
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ int counterPort = MSR_K8_PERFCTR0 + eventSelectNum;
+ pme->WriteMSR(counterPort, value); // clear
+ }
+
+ int64 ReadCounter()
+ {
+
+#if PME_DEBUG
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ if (select.USR == 0 && select.OS == 0)
+ return -1; // no area to collect, use SetCaptureMode
+
+ if (select.EventMask == 0)
+ return -2; // no event mask set
+
+ if (eventSelectNum < 0 || eventSelectNum > 3)
+ return -3; // counter not legal
+
+ // check revision
+
+#endif
+
+ // ReadMSR should work here too, but RDPMC should be faster
+ //ReadMSR(counterPort, int64);
+
+ // we need to copy this into a temp for some reason
+#ifdef COMPILER_MSVC64
+ return __readpmc((unsigned long) eventSelectNum);
+#else
+ int temp = eventSelectNum;
+ _asm
+ {
+ mov ecx, temp
+ RDPMC
+ }
+#endif
+
+ }
+
+
+};
+#pragma warning( default : 4035 )
+
+
+
+
+typedef union EVENT_MASK(k8_dispatched_fpu_ops)
+{
+ // event 0
+ struct
+ {
+ uint16 AddPipeOps:1; // Add pipe ops excluding junk ops" },
+ uint16 MulPipeOps:1; // Multiply pipe ops excluding junk ops" },,
+ uint16 StoreOps:1; // Store pipe ops excluding junk ops" },
+ uint16 AndPipeOpsJunk:1; // Add pipe junk ops" },,
+ uint16 MulPipeOpsJunk:1; // Multiply pipe junk ops" },
+ uint16 StoreOpsJunk:1; // Store pipe junk ops" } }
+ };
+ uint16 flat;
+} EVENT_MASK(k8_dispatched_fpu_ops);
+
+class k8Event_DISPATCHED_FPU_OPS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCHED_FPU_OPS()
+ {
+ eventMask = (EVENT_MASK(k8_dispatched_fpu_ops) *)&m_eventMask;
+
+ event_id = 0x00;
+ unitEncode = FP;
+ name = _T("Dispatched FPU ops");
+ revRequired = 'B';
+ }
+ EVENT_MASK(k8_dispatched_fpu_ops) * eventMask;
+
+};
+
+//////////////////////////////////////////////////////////
+
+
+
+class k8Event_NO_FPU_OPS : public k8BaseEvent
+{
+public:
+
+ k8Event_NO_FPU_OPS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x01;
+ unitEncode = FP;
+
+ name = _T("Cycles with no FPU ops retired");
+ revRequired = 'B';
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+//////////////////////////////////////////////////////////
+
+class k8Event_FAST_FPU_OPS : public k8BaseEvent
+{
+public:
+
+ k8Event_FAST_FPU_OPS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x02;
+ unitEncode = FP;
+
+ name = _T("Dispatched FPU ops that use the fast flag interface");
+ revRequired = 'B';
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+//////////////////////////////////////////////////////////
+
+
+typedef union EVENT_MASK(k8_segment_register_load)
+{
+
+ struct
+ {
+ uint16 ES:1;
+ uint16 CS:1;
+ uint16 SS:1;
+ uint16 DS:1;
+ uint16 FS:1;
+ uint16 GS:1;
+ uint16 HS:1;
+ };
+ uint16 flat;
+} EVENT_MASK(k8_segment_register_load);
+
+
+class k8Event_SEG_REG_LOAD : public k8BaseEvent
+{
+public:
+
+ k8Event_SEG_REG_LOAD()
+ {
+ eventMask = (EVENT_MASK(k8_segment_register_load) *)&m_eventMask;
+ name = _T("Segment register load");
+ event_id = 0x20;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(k8_segment_register_load) * eventMask;
+
+};
+
+
+class k8Event_SELF_MODIFY_RESYNC : public k8BaseEvent
+{
+public:
+
+ k8Event_SELF_MODIFY_RESYNC()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural resync caused by self modifying code");
+ event_id = 0x21;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+class k8Event_LS_RESYNC_BY_SNOOP : public k8BaseEvent
+{
+public:
+
+ k8Event_LS_RESYNC_BY_SNOOP()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x22;
+ unitEncode = LS;
+
+ name = _T("Microarchitectural resync caused by snoop");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+class k8Event_LS_BUFFER_FULL : public k8BaseEvent
+{
+public:
+
+ k8Event_LS_BUFFER_FULL()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("LS Buffer 2 Full");
+ event_id = 0x23;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+typedef union EVENT_MASK(k8_locked_op)
+{
+
+
+ struct
+ {
+ uint16 NumLockInstr : 1; //Number of lock instructions executed
+ uint16 NumCyclesInRequestGrant : 1; //Number of cycles spent in the lock request/grant stage
+
+ uint16 NumCyclesForLock:1;
+ /*Number of cycles a lock takes to complete once it is
+ non-speculative and is the oldest load/store operation
+ (non-speculative cycles in Ls2 entry 0)*/
+
+
+ };
+ uint16 flat;
+
+
+} EVENT_MASK(k8_locked_op);
+
+
+
+class k8Event_LOCKED_OP : public k8BaseEvent
+{
+public:
+
+ EVENT_MASK(k8_locked_op) * eventMask;
+
+ k8Event_LOCKED_OP()
+ {
+ eventMask = (EVENT_MASK(k8_locked_op) *)&m_eventMask;
+ name = _T("Locked operation");
+ event_id = 0x24;
+ unitEncode = LS;
+
+ revRequired = 'C';
+ }
+
+
+};
+
+class k8Event_OP_LATE_CANCEL : public k8BaseEvent
+{
+public:
+
+ k8Event_OP_LATE_CANCEL()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural late cancel of an operation");
+ event_id = 0x25;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("OP_LATE_CANCEL");
+
+
+};
+class k8Event_CFLUSH_RETIRED : public k8BaseEvent
+{
+public:
+
+ k8Event_CFLUSH_RETIRED()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired CFLUSH instructions");
+ event_id = 0x26;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("CFLUSH_RETIRED");
+
+
+};
+class k8Event_CPUID_RETIRED : public k8BaseEvent
+{
+public:
+
+ k8Event_CPUID_RETIRED()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired CPUID instructions");
+ event_id = 0x27;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("CPUID_RETIRED");
+
+
+};
+
+typedef union EVENT_MASK( k8_cache)
+{
+
+ struct
+ {
+ uint16 Invalid:1;
+ uint16 Exclusive:1;
+ uint16 Shared:1;
+ uint16 Owner:1;
+ uint16 Modified:1;
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_cache);
+ /* 0x40-0x47: from K7 official event set */
+
+
+class k8Event_DATA_CACHE_ACCESSES : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_ACCESSES()
+ {
+
+ event_id = 0x40;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //_T("DATA_CACHE_ACCESSES"),
+ name = _T("Data cache accesses");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+class k8Event_DATA_CACHE_MISSES : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_MISSES()
+ {
+
+ event_id = 0x41;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //_T("DATA_CACHE_MISSES"),
+ name = _T("Data cache misses");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+
+class k8Event_DATA_CACHE_REFILLS_FROM_L2 : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_REFILLS_FROM_L2()
+ {
+
+ event_id = 0x42;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+
+
+ name = _T("Data cache refills from L2");
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+
+};
+
+class k8Event_DATA_CACHE_REFILLS_FROM_SYSTEM : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_REFILLS_FROM_SYSTEM()
+ {
+
+ event_id = 0x43;
+ unitEncode = DC;
+
+
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+
+ //UM(k7_um_moesi),
+ //_T("DATA_CACHE_REFILLS_FROM_SYSTEM"),
+ name = _T("Data cache refills from system");
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+
+};
+
+class k8Event_DATA_CACHE_WRITEBACKS : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_WRITEBACKS()
+ {
+
+ event_id = 0x44;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+
+ //UM(k7_um_moesi),
+ //_T("DATA_CACHE_WRITEBACKS"),
+ name = _T("Data cache writebacks");
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+
+
+};
+
+class k8Event_L1_DTLB_MISSES_AND_L2_DTLB_HITS : public k8BaseEvent
+{
+ k8Event_L1_DTLB_MISSES_AND_L2_DTLB_HITS()
+ {
+
+ event_id = 0x45;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ name = _T("L1 DTLB misses and L2 DTLB hits");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+
+class k8Event_L1_AND_L2_DTLB_MISSES : public k8BaseEvent
+{
+ k8Event_L1_AND_L2_DTLB_MISSES()
+ {
+
+ event_id = 0x46;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ name = _T("L1 and L2 DTLB misses") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+class k8Event_MISALIGNED_DATA_REFERENCES : public k8BaseEvent
+{
+ k8Event_MISALIGNED_DATA_REFERENCES()
+ {
+
+ event_id = 0x47;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //NULL, _T("MISALIGNED_DATA_REFERENCES"),
+ name = _T("Misaligned data references");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+
+class k8Event_ACCESS_CANCEL_LATE : public k8BaseEvent
+{
+public:
+
+ k8Event_ACCESS_CANCEL_LATE()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural late cancel of an access");
+ event_id = 0x48;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("ACCESS_CANCEL_LATE");
+
+
+};
+class k8Event_ACCESS_CANCEL_EARLY : public k8BaseEvent
+{
+public:
+
+ k8Event_ACCESS_CANCEL_EARLY()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural early cancel of an access");
+ event_id = 0x49;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("ACCESS_CANCEL_EARLY");
+
+
+};
+typedef union EVENT_MASK( k8_ecc)
+{
+ struct
+ {
+ uint16 ScrubberError : 1; // Scrubber error" },
+ uint16 PiggybackScrubberErrors : 1; // Piggyback scrubber errors" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_ecc);
+
+
+class k8Event_ECC_BIT_ERR : public k8BaseEvent
+{
+public:
+
+ k8Event_ECC_BIT_ERR()
+ {
+ eventMask = (EVENT_MASK(k8_ecc) *)&m_eventMask;
+ name = _T("One bit ECC error recorded found by scrubber");
+ event_id = 0x4A;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(k8_ecc) * eventMask;
+ // name = _T("ECC_BIT_ERR");
+
+
+};
+
+// 4B
+typedef union EVENT_MASK( k8_distpatch_prefetch_instructions)
+{
+ struct
+ {
+ uint16 Load : 1;
+ uint16 Store : 1;
+ uint16 NTA : 1;
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_distpatch_prefetch_instructions);
+
+class k8Event_DISPATCHED_PRE_INSTRS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCHED_PRE_INSTRS()
+ {
+ eventMask = (EVENT_MASK(k8_distpatch_prefetch_instructions) *)&m_eventMask;
+ name = _T("Dispatched prefetch instructions");
+ event_id = 0x4B;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(k8_distpatch_prefetch_instructions) * eventMask;
+ // name = _T("DISPATCHED_PRE_INSTRS");
+
+ /* 0x4C: added in Revision C */
+
+};
+
+
+
+typedef union EVENT_MASK( k8_lock_accesses)
+{
+ struct
+ {
+ uint16 DcacheAccesses:1; // Number of dcache accesses by lock instructions" },
+ uint16 DcacheMisses:1; // Number of dcache misses by lock instructions" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_lock_accesses);
+
+
+
+class k8Event_LOCK_ACCESSES : public k8BaseEvent
+{
+public:
+
+ k8Event_LOCK_ACCESSES()
+ {
+ eventMask = (EVENT_MASK(k8_lock_accesses) *)&m_eventMask;
+ name = _T("DCACHE accesses by locks") ;
+ event_id = 0x4C;
+ unitEncode = DC;
+
+ revRequired = 'C';
+ }
+ EVENT_MASK(k8_lock_accesses) * eventMask;
+
+
+};
+
+
+class k8Event_CYCLES_PROCESSOR_IS_RUNNING : public k8BaseEvent
+{
+public:
+
+ k8Event_CYCLES_PROCESSOR_IS_RUNNING()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Cycles processor is running (not in HLT or STPCLK)");
+ event_id = 0x76;
+ unitEncode = BU;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("CYCLES_PROCESSOR_IS_RUNNING"); /* undocumented *;
+
+
+};
+
+
+typedef union EVENT_MASK( k8_internal_L2_request)
+{
+ struct
+ {
+ uint16 ICFill:1; // IC fill" },
+ uint16 DCFill:1; // DC fill" },
+ uint16 TLBReload:1; // TLB reload" },
+ uint16 TagSnoopRequest:1; // Tag snoop request" },
+ uint16 CancelledRequest:1; // Cancelled request" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_internal_L2_request);
+
+class k8Event_BU_INT_L2_REQ : public k8BaseEvent
+{
+public:
+
+ k8Event_BU_INT_L2_REQ()
+ {
+ eventMask = (EVENT_MASK(k8_internal_L2_request) *)&m_eventMask;
+ name = _T("Internal L2 request");
+ unitEncode = BU;
+ event_id = 0x7D;
+ }
+
+ EVENT_MASK(k8_internal_L2_request) * eventMask;
+} ;
+
+ // name = _T("BU_INT_L2_REQ");
+
+
+
+// 7E
+typedef union EVENT_MASK( k8_fill_request_missed_L2)
+{
+
+ struct
+ {
+ uint16 ICFill:1; // IC fill" },
+ uint16 DCFill:1; // DC fill" },
+ uint16 TLBReload:1; // TLB reload" },
+ };
+ uint16 flat;
+
+} EVENT_MASK( k8_fill_request_missed_L2);
+
+
+class k8Event_BU_FILL_REQ : public k8BaseEvent
+{
+public:
+
+ k8Event_BU_FILL_REQ()
+ {
+ eventMask = (EVENT_MASK(k8_fill_request_missed_L2) *)&m_eventMask;
+ name = _T("Fill request that missed in L2");
+ event_id = 0x7E;
+ unitEncode = BU;
+
+ }
+ EVENT_MASK(k8_fill_request_missed_L2) * eventMask;
+ // name = _T("BU_FILL_REQ");
+
+
+
+};
+
+
+
+
+// 7F
+typedef union EVENT_MASK( k8_fill_into_L2)
+{
+
+ struct
+ {
+ uint16 DirtyL2Victim:1; // Dirty L2 victim
+ uint16 VictimFromL2:1; // Victim from L2
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_fill_into_L2);
+
+class k8Event_BU_FILL_L2 : public k8BaseEvent
+{
+public:
+
+ k8Event_BU_FILL_L2()
+ {
+ eventMask = (EVENT_MASK(k8_fill_into_L2) *)&m_eventMask;
+ name = _T("Fill into L2");
+ event_id = 0x7F;
+ unitEncode = BU;
+
+ }
+ EVENT_MASK(k8_fill_into_L2) * eventMask;
+ // name = _T("BU_FILL_L2");
+
+
+};
+
+class k8Event_INSTRUCTION_CACHE_FETCHES : public k8BaseEvent
+{
+public:
+ k8Event_INSTRUCTION_CACHE_FETCHES()
+ {
+ event_id = 0x80;
+ unitEncode = IC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ name = _T("Instruction cache fetches");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+class k8Event_INSTRUCTION_CACHE_MISSES : public k8BaseEvent
+{
+public:
+ k8Event_INSTRUCTION_CACHE_MISSES()
+ {
+ event_id = 0x81;
+ unitEncode = IC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //0xF, NULL, _T("INSTRUCTION_CACHE_MISSES"),
+ name = _T("Instruction cache misses");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+class k8Event_IC_REFILL_FROM_L2 : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_REFILL_FROM_L2()
+ {
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+ name = _T("Refill from L2");
+ event_id = 0x82;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+ // name = _T("IC_REFILL_FROM_L2");
+
+
+
+};
+class k8Event_IC_REFILL_FROM_SYS : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_REFILL_FROM_SYS()
+ {
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+ name = _T("Refill from system");
+ event_id = 0x83;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+ // name = _T("IC_REFILL_FROM_SYS");
+
+
+
+};
+class k8Event_L1_ITLB_MISSES_AND_L2_ITLB_HITS : public k8BaseEvent
+{
+public:
+ k8Event_L1_ITLB_MISSES_AND_L2_ITLB_HITS()
+ {
+
+ event_id = 0x84;
+ unitEncode = IC;
+
+ name = _T("L1 ITLB misses (and L2 ITLB hits)");
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+
+class k8Event_L1_AND_L2_ITLB_MISSES : public k8BaseEvent
+{
+public:
+ k8Event_L1_AND_L2_ITLB_MISSES()
+ {
+ event_id = 0x85;
+ unitEncode = IC;
+
+ name = _T("(L1 and) L2 ITLB misses");
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+
+
+class k8Event_IC_RESYNC_BY_SNOOP : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_RESYNC_BY_SNOOP()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x86;
+ unitEncode = IC;
+
+ name = _T("Microarchitectural resync caused by snoop");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_RESYNC_BY_SNOOP");
+ /* similar to 0x22; but IC unit instead of LS unit */
+
+
+
+};
+class k8Event_IC_FETCH_STALL : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_FETCH_STALL()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Instruction fetch stall");
+ event_id = 0x87;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_FETCH_STALL");
+
+
+
+};
+class k8Event_IC_STACK_HIT : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_STACK_HIT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Return stack hit");
+ event_id = 0x88;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_STACK_HIT");
+
+
+
+};
+class k8Event_IC_STACK_OVERFLOW : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_STACK_OVERFLOW()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Return stack overflow");
+ event_id = 0x89;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_STACK_OVERFLOW");
+
+
+
+
+};
+
+ /* 0xC0-0xC7: from K7 official event set */
+class k8Event_RETIRED_INSTRUCTIONS : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_INSTRUCTIONS()
+ {
+ event_id = 0xC0;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //0xF, NULL, _T("RETIRED_INSTRUCTIONS"),
+ name = _T("Retired instructions (includes exceptions, interrupts, resyncs)");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+
+class k8Event_RETIRED_OPS : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_OPS()
+ {
+ event_id = 0xC1;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_OPS"),
+ name = _T("Retired Ops") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_BRANCHES : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_BRANCHES()
+ {
+ event_id = 0xC2;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_BRANCHES"),
+ name = _T("Retired branches (conditional, unconditional, exceptions, interrupts)") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_BRANCHES_MISPREDICTED : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_BRANCHES_MISPREDICTED()
+ {
+ event_id = 0xC3;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_BRANCHES_MISPREDICTED"),
+ name = _T("Retired branches mispredicted") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_TAKEN_BRANCHES : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_TAKEN_BRANCHES()
+ {
+ event_id = 0xC4;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_TAKEN_BRANCHES"),
+ name = _T("Retired taken branches") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_TAKEN_BRANCHES_MISPREDICTED : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_TAKEN_BRANCHES_MISPREDICTED()
+ {
+ event_id = 0xC5;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_TAKEN_BRANCHES_MISPREDICTED"),
+ name = _T("Retired taken branches mispredicted") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_FAR_CONTROL_TRANSFERS : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_FAR_CONTROL_TRANSFERS()
+ {
+ event_id = 0xC6;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_FAR_CONTROL_TRANSFERS"),
+ name = _T("Retired far control transfers") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_RESYNC_BRANCHES : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_RESYNC_BRANCHES()
+ {
+ event_id = 0xC7;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_RESYNC_BRANCHES"),
+ name = _T("Retired resync branches (only non-control transfer branches counted)") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+
+class k8Event_RETIRED_NEAR_RETURNS : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_NEAR_RETURNS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired near returns");
+ event_id = 0xC8;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+
+};
+class k8Event_RETIRED_RETURNS_MISPREDICT : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_RETURNS_MISPREDICT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired near returns mispredicted");
+ event_id = 0xC9;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("RETIRED_RETURNS_MISPREDICT");
+
+
+};
+class k8Event_RETIRED_BRANCH_MISCOMPARE : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_BRANCH_MISCOMPARE()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired taken branches mispredicted due to address miscompare");
+ event_id = 0xCA;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("RETIRED_BRANCH_MISCOMPARE");
+
+
+};
+
+
+ /* Revision B and later */
+
+typedef union EVENT_MASK( k8_retired_fpu_instr)
+{
+ struct
+ {
+ uint16 DirtyL2Victim:1; // x87 instructions
+ uint16 CombinedMMX_3DNow:1; // Combined MMX & 3DNow! instructions" },
+ uint16 CombinedPackedSSE_SSE2:1; // Combined packed SSE and SSE2 instructions" },
+ uint16 CombinedScalarSSE_SSE2:1; // Combined scalar SSE and SSE2 instructions" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_retired_fpu_instr);
+
+
+class k8Event_RETIRED_FPU_INSTRS : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_FPU_INSTRS()
+ {
+ eventMask = (EVENT_MASK(k8_retired_fpu_instr) *)&m_eventMask;
+ event_id = 0xCB;
+ unitEncode = FR;
+
+ name = _T("Retired FPU instructions");
+ revRequired = 'B';
+ }
+ EVENT_MASK(k8_retired_fpu_instr) * eventMask;
+ /* Revision B and later */
+
+
+
+};
+
+// CC
+typedef union EVENT_MASK( k8_retired_fastpath_double_op_instr )
+{
+
+ struct
+ {
+ uint16 LowOpPosition0:1; // With low op in position 0" },
+ uint16 LowOpPosition1:1; // With low op in position 1" },
+ uint16 LowOpPosition2:1; // With low op in position 2" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_retired_fastpath_double_op_instr);
+
+class k8Event_RETIRED_FASTPATH_INSTRS : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_FASTPATH_INSTRS()
+ {
+ eventMask = (EVENT_MASK(k8_retired_fastpath_double_op_instr) *)&m_eventMask;
+ event_id = 0xCC;
+ unitEncode = FR;
+
+ name = _T("Retired fastpath double op instructions");
+ revRequired = 'B';
+
+ }
+ EVENT_MASK(k8_retired_fastpath_double_op_instr) * eventMask;
+
+
+};
+
+class k8Event_INTERRUPTS_MASKED_CYCLES : public k8BaseEvent
+{
+public:
+ k8Event_INTERRUPTS_MASKED_CYCLES()
+ {
+ event_id = 0xCD;
+ unitEncode = FR;
+
+ //0xF, NULL, _T("INTERRUPTS_MASKED_CYCLES"),
+ name = _T("Interrupts masked cycles (IF=0)") ;
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+class k8Event_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES : public k8BaseEvent
+{
+public:
+ k8Event_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES()
+ {
+ event_id = 0xCE;
+ unitEncode = FR;
+
+ //0xF, NULL, _T("INTERRUPTS_MASKED_WHILE_PENDING_CYCLES"),
+ name = _T("Interrupts masked while pending cycles (INTR while IF=0)") ;
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+class k8Event_NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS : public k8BaseEvent
+{
+public:
+ k8Event_NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS()
+ {
+ event_id = 0xCF;
+ unitEncode = FR;
+
+ //0xF, NULL, _T("NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS"),
+ name = _T("Number of taken hardware interrupts") ;
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+class k8Event_DECODER_EMPTY : public k8BaseEvent
+{
+public:
+
+ k8Event_DECODER_EMPTY()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Nothing to dispatch (decoder empty)");
+ event_id = 0xD0;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DECODER_EMPTY");
+
+
+};
+class k8Event_DISPATCH_STALLS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALLS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stalls (events 0xD2-0xDA combined)");
+ event_id = 0xD1;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALLS");
+
+
+
+};
+class k8Event_DISPATCH_STALL_FROM_BRANCH_ABORT : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_FROM_BRANCH_ABORT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall from branch abort to retire");
+ event_id = 0xD2;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_FROM_BRANCH_ABORT");
+
+
+
+};
+class k8Event_DISPATCH_STALL_SERIALIZATION : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_SERIALIZATION()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall for serialization");
+ event_id = 0xD3;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_SERIALIZATION");
+
+
+};
+class k8Event_DISPATCH_STALL_SEG_LOAD : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_SEG_LOAD()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall for segment load");
+ event_id = 0xD4;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_SEG_LOAD");
+
+
+
+};
+class k8Event_DISPATCH_STALL_REORDER_BUFFER : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_REORDER_BUFFER()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when reorder buffer is full");
+ event_id = 0xD5;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_REORDER_BUFFER");
+
+
+};
+class k8Event_DISPATCH_STALL_RESERVE_STATIONS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_RESERVE_STATIONS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when reservation stations are full");
+ event_id = 0xD6;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_RESERVE_STATIONS");
+
+
+};
+class k8Event_DISPATCH_STALL_FPU : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_FPU()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when FPU is full");
+ event_id = 0xD7;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_FPU");
+
+
+};
+class k8Event_DISPATCH_STALL_LS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_LS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when LS is full");
+ event_id = 0xD8;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_LS");
+
+
+};
+class k8Event_DISPATCH_STALL_QUIET_WAIT : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_QUIET_WAIT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when waiting for all to be quiet");
+ event_id = 0xD9;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_QUIET_WAIT");
+
+
+
+};
+class k8Event_DISPATCH_STALL_PENDING : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_PENDING()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when far control transfer or resync branch is pending");
+ event_id = 0xDA;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_PENDING");
+
+
+
+};
+
+
+typedef union EVENT_MASK( k8_fpu_exceptions)
+{
+
+
+
+ struct
+ {
+ uint16 x87ReclassMicrofaults:1; // x87 reclass microfaults" },
+ uint16 SSERetypeMicrofaults:1; // SSE retype microfaults" },
+ uint16 SSEReclassMicrofaults:1; // SSE reclass microfaults" },
+ uint16 SSE_x87Microtraps:1; // SSE and x87 microtraps" } }
+ };
+ uint16 flat;
+
+
+
+}EVENT_MASK( k8_fpu_exceptions);
+
+class k8Event_FPU_EXCEPTIONS : public k8BaseEvent
+{
+public:
+
+ k8Event_FPU_EXCEPTIONS()
+ {
+ eventMask = (EVENT_MASK(k8_fpu_exceptions) *)&m_eventMask;
+ event_id = 0xDB;
+ unitEncode = FR;
+
+ name = _T("FPU exceptions");
+ revRequired = 'B';
+
+ }
+ EVENT_MASK(k8_fpu_exceptions) * eventMask;
+ // name = _T("FPU_EXCEPTIONS");
+ /* Revision B and later */
+
+
+
+};
+class k8Event_DR0_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR0_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR0");
+ event_id = 0xDC;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR0_BREAKPOINTS");
+
+
+
+};
+class k8Event_DR1_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR1_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR1");
+ event_id = 0xDD;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR1_BREAKPOINTS");
+
+
+
+};
+class k8Event_DR2_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR2_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR2");
+ event_id = 0xDE;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR2_BREAKPOINTS");
+
+
+};
+class k8Event_DR3_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR3_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR3");
+ event_id = 0xDF;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR3_BREAKPOINTS");
+
+
+};
+
+
+
+// E0
+typedef union EVENT_MASK( k8_page_access_event)
+{
+ struct
+ {
+ uint16 PageHit:1; // Page hit" },
+ uint16 PageMiss:1; // Page miss" },
+ uint16 PageConflict:1; // Page conflict" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_page_access_event);
+
+class k8Event_MEM_PAGE_ACCESS : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_PAGE_ACCESS()
+ {
+ eventMask = (EVENT_MASK(k8_page_access_event) *)&m_eventMask;
+ name = _T("Memory controller page access");
+ event_id = 0xE0;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_page_access_event) * eventMask;
+ // name = _T("MEM_PAGE_ACCESS");
+
+
+};
+class k8Event_MEM_PAGE_TBL_OVERFLOW : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_PAGE_TBL_OVERFLOW()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Memory controller page table overflow");
+ event_id = 0xE1;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("MEM_PAGE_TBL_OVERFLOW");
+
+
+};
+class k8Event_DRAM_SLOTS_MISSED : public k8BaseEvent
+{
+public:
+
+ k8Event_DRAM_SLOTS_MISSED()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Memory controller DRAM command slots missed (in MemClks)");
+ event_id = 0xE2;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DRAM_SLOTS_MISSED");
+
+
+};
+
+
+// e3
+typedef union EVENT_MASK( k8_turnaround)
+{
+
+ struct
+ {
+ uint16 DIMMTurnaround:1; //DIMM turnaround" },
+ uint16 ReadToWriteTurnaround:1; //Read to write turnaround" },
+ uint16 WriteToReadTurnaround:1; //Write to read turnaround" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_turnaround);
+
+class k8Event_MEM_TURNAROUND : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_TURNAROUND()
+ {
+ eventMask = (EVENT_MASK(k8_turnaround) *)&m_eventMask;
+ name = _T("Memory controller turnaround");
+ event_id = 0xE3;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_turnaround) * eventMask;
+ // name = _T("MEM_TURNAROUND");
+
+
+};
+
+
+
+
+// E4
+typedef union EVENT_MASK( k8_bypass_counter_saturation)
+{
+ struct
+ {
+ uint16 MEM_HighPriorityBypass:1; // Memory controller high priority bypass" },
+ uint16 MEM_LowPriorityBypass:1; // Memory controller low priority bypass" },
+ uint16 DRAM_InterfaceBypass:1; // DRAM controller interface bypass" },
+ uint16 DRAM_QueueBypass:1; // DRAM controller queue bypass" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_bypass_counter_saturation);
+
+class k8Event_MEM_BYPASS_SAT : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_BYPASS_SAT()
+ {
+ eventMask = (EVENT_MASK(k8_bypass_counter_saturation) *)&m_eventMask;
+ name = _T("Memory controller bypass counter saturation");
+ event_id = 0xE4;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_bypass_counter_saturation) * eventMask;
+ // name = _T("MEM_BYPASS_SAT");
+
+
+};
+
+
+
+//EB
+typedef union EVENT_MASK( k8_sized_commands)
+{
+
+ struct
+ {
+ uint16 NonPostWrSzByte:1; // NonPostWrSzByte" },
+ uint16 NonPostWrSzDword:1; // NonPostWrSzDword" },
+ uint16 PostWrSzByte:1; // PostWrSzByte" },
+ uint16 PostWrSzDword:1; // PostWrSzDword" },
+ uint16 RdSzByte:1; // RdSzByte" },
+ uint16 RdSzDword:1; // RdSzDword" },
+ uint16 RdModWr:1; // RdModWr" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_sized_commands);
+
+
+class k8Event_SIZED_COMMANDS : public k8BaseEvent
+{
+public:
+
+ k8Event_SIZED_COMMANDS()
+ {
+ eventMask = (EVENT_MASK(k8_sized_commands) *)&m_eventMask;
+ name = _T("Sized commands");
+ event_id = 0xEB;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_sized_commands) * eventMask;
+ // name = _T("SIZED_COMMANDS");
+
+
+};
+
+typedef union EVENT_MASK( k8_probe_result)
+{
+ struct
+ {
+ uint16 ProbeMiss:1; // Probe miss" },
+ uint16 ProbeHit:1; // Probe hit" },
+ uint16 ProbeHitDirtyWithoutMemoryCancel:1; // Probe hit dirty without memory cancel" },
+ uint16 ProbeHitDirtyWithMemoryCancel:1; // Probe hit dirty with memory cancel" } }
+ uint16 UpstreamDisplayRefreshReads:1; // Rev D and later
+ uint16 UpstreamNonDisplayRefreshReads:1; // Rev D and later
+ uint16 UpstreamWrites:1; // Rev D and later
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_probe_result);
+
+
+class k8Event_PROBE_RESULT : public k8BaseEvent
+{
+public:
+
+ k8Event_PROBE_RESULT()
+ {
+ eventMask = (EVENT_MASK(k8_probe_result) *)&m_eventMask;
+ name = _T("Probe result");
+ event_id = 0xEC;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_probe_result) * eventMask;
+ // name = _T("PROBE_RESULT");
+
+
+};
+
+typedef union EVENT_MASK( k8_ht)
+{
+
+ struct
+ {
+ uint16 CommandSent:1; //Command sent" },
+ uint16 DataSent:1; //Data sent" },
+ uint16 BufferReleaseSent:1; //Buffer release sent"
+ uint16 NopSent:1; //Nop sent" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_ht);
+
+
+class k8Event_HYPERTRANSPORT_BUS0_WIDTH : public k8BaseEvent
+{
+public:
+
+ k8Event_HYPERTRANSPORT_BUS0_WIDTH()
+ {
+ eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask;
+ name = _T("Hypertransport (tm) bus 0 bandwidth");
+ event_id = 0xF6;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_ht) * eventMask;
+ // name = _T("HYPERTRANSPORT_BUS0_WIDTH");
+
+
+};
+class k8Event_HYPERTRANSPORT_BUS1_WIDTH : public k8BaseEvent
+{
+public:
+
+ k8Event_HYPERTRANSPORT_BUS1_WIDTH()
+ {
+ eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask;
+ name = _T("Hypertransport (tm) bus 1 bandwidth");
+ event_id = 0xF7;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_ht) * eventMask;
+ // name = _T("HYPERTRANSPORT_BUS1_WIDTH");
+
+
+};
+class k8Event_HYPERTRANSPORT_BUS2_WIDTH : public k8BaseEvent
+{
+public:
+
+ k8Event_HYPERTRANSPORT_BUS2_WIDTH()
+ {
+ eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask;
+ name = _T("Hypertransport (tm) bus 2 bandwidth");
+ event_id = 0xF8;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_ht) * eventMask;
+ // name = _T("HYPERTRANSPORT_BUS2_WIDTH");
+
+};
+
+//
+//typedef union EVENT_MASK( perfctr_event_set k8_common_event_set)
+//{
+//
+// .cpu_type = PERFCTR_X86_AMD_K8,
+// .event_prefix = _T("K8_"),
+// .include = &k7_official_event_set,
+// .nevents = ARRAY_SIZE(k8_common_events),
+// .events = k8_common_events,
+//}EVENT_MASK( perfctr_event_set k8_common_event_set);
+//
+//typedef union EVENT_MASK( perfctr_event k8_events[])
+//{
+//
+// { 0x24, 0xF, UM(NULL), _T("LOCKED_OP"), /* unit mask changed in Rev. C */
+// _T("Locked operation") },
+//}EVENT_MASK( perfctr_event k8_events[]);
+
+
+
+
+//const struct perfctr_event_set perfctr_k8_event_set)
+//{
+//
+// .cpu_type = PERFCTR_X86_AMD_K8,
+// .event_prefix = _T("K8_"),
+// .include = &k8_common_event_set,
+// .nevents = ARRAY_SIZE(k8_events),
+// .events = k8_events,
+//};
+//
+/*
+ * K8 Revision C. Starts at CPUID 0xF58 for Opteron/Athlon64FX and
+ * CPUID 0xF48 for Athlon64. (CPUID 0xF51 is Opteron Revision B3.)
+ */
+
+
+
+
+
+
+
+
+//
+//typedef union EVENT_MASK( k8_lock_accesses)
+//{
+// struct
+// {
+// uint16 DcacheAccesses:1; // Number of dcache accesses by lock instructions" },
+// uint16 DcacheMisses:1; // Number of dcache misses by lock instructions" } }
+// };
+// uint16 flat;
+//
+//}EVENT_MASK( k8_lock_accesses);
+//
+
+#endif // K8PERFORMANCECOUNTERS_H
diff --git a/external/vpc/public/tier0/l2cache.h b/external/vpc/public/tier0/l2cache.h
new file mode 100644
index 0000000..db54695
--- /dev/null
+++ b/external/vpc/public/tier0/l2cache.h
@@ -0,0 +1,47 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+#ifndef CL2CACHE_H
+#define CL2CACHE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+class P4Event_BSQ_cache_reference;
+
+class CL2Cache
+{
+public:
+
+ CL2Cache();
+ ~CL2Cache();
+
+ void Start( void );
+ void End( void );
+
+ //-------------------------------------------------------------------------
+ // GetL2CacheMisses
+ //-------------------------------------------------------------------------
+ int GetL2CacheMisses( void )
+ {
+ return m_iL2CacheMissCount;
+ }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+private:
+
+ int m_nID;
+
+ P4Event_BSQ_cache_reference *m_pL2CacheEvent;
+ int64 m_i64Start;
+ int64 m_i64End;
+ int m_iL2CacheMissCount;
+};
+
+#endif // CL2CACHE_H
+
diff --git a/external/vpc/public/tier0/logging.h b/external/vpc/public/tier0/logging.h
new file mode 100644
index 0000000..42b10c4
--- /dev/null
+++ b/external/vpc/public/tier0/logging.h
@@ -0,0 +1,767 @@
+//============ Copyright (c) Valve Corporation, All rights reserved. ============
+//
+// Logging system declarations.
+//
+// The logging system is a channel-based output mechanism which allows
+// subsystems to route their text/diagnostic output to various listeners
+//
+//===============================================================================
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+#include "color.h"
+#include "icommandline.h"
+#include <stdio.h>
+
+// For XBX_** functions
+#if defined( _X360 )
+#include "xbox/xbox_console.h"
+#endif
+
+// Used by CColorizedLoggingListener
+#if defined( _WIN32 ) || (defined(POSIX) && !defined(_GAMECONSOLE))
+#include "tier0/win32consoleio.h"
+#endif
+
+/*
+ ---- Logging System ----
+
+ The logging system is a channel-based mechanism for all code (engine,
+ mod, tool) across all platforms to output information, warnings,
+ errors, etc.
+
+ This system supersedes the existing Msg(), Warning(), Error(), DevMsg(), ConMsg() etc. functions.
+ There are channels defined in the new system through which all old messages are routed;
+ see LOG_GENERAL, LOG_CONSOLE, LOG_DEVELOPER, etc.
+
+ To use the system, simply call one of the predefined macros:
+
+ Log_Msg( ChannelID, [Color], Message, ... )
+ Log_Warning( ChannelID, [Color], Message, ... )
+ Log_Error( ChannelID, [Color], Message, ... )
+
+ A ChannelID is typically created by defining a logging channel with the
+ log channel macros:
+
+ DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
+
+ or
+
+ BEGIN_DEFINE_LOGGING_CHANNEL( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
+ ADD_LOGGING_CHANNEL_TAG( "Tag1" );
+ ADD_LOGGING_CHANNEL_TAG( "Tag2" );
+ END_DEFINE_LOGGING_CHANNEL();
+
+ These macros create a global channel ID variable with the name specified
+ by the first parameter (in this example, LOG_ChannelName). This channel ID
+ can be used by various LoggingSystem_** functions to manipulate the channel settings.
+
+ The optional [Flags] parameter is an OR'd together set of LoggingChannelFlags_t
+ values (default: 0).
+
+ The optional [MinimumSeverity] parameter is the lowest threshold
+ above which messages will be processed (inclusive). The default is LS_MESSAGE,
+ which results in all messages, warnings, and errors being logged.
+ Variadic parameters to the Log_** functions will be ignored if a channel
+ is not enabled for a given severity (for performance reasons).
+
+ Logging channels can have their minimum severity modified by name, ID, or tag.
+
+ Logging channels are not hierarchical since there are situations in which
+ a channel needs to belong to multiple hierarchies. Use tags to create
+ categories or shallow hierarchies.
+
+ @TODO (Feature wishlist):
+ 1) Callstack logging support
+ 2) Registering dynamic channels and unregistering channels at runtime
+ 3) Sentient robot to clean up the thousands of places using the old/legacy logging system.
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Constants, Types, Forward Declares
+//////////////////////////////////////////////////////////////////////////
+
+class CLoggingSystem;
+class CThreadFastMutex;
+
+//-----------------------------------------------------------------------------
+// Maximum length of a sprintf'ed logging message.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_MESSAGE_LENGTH = 2048;
+
+//-----------------------------------------------------------------------------
+// Maximum length of a channel or tag name.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_IDENTIFIER_LENGTH = 32;
+
+//-----------------------------------------------------------------------------
+// Maximum number of logging channels. Increase if needed.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_CHANNEL_COUNT = 256;
+
+//-----------------------------------------------------------------------------
+// Maximum number of logging tags across all channels. Increase if needed.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_TAG_COUNT = 1024;
+
+//-----------------------------------------------------------------------------
+// Maximum number of characters across all logging tags. Increase if needed.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_TAG_CHARACTER_COUNT = 8192;
+
+//-----------------------------------------------------------------------------
+// Maximum number of concurrent logging listeners in a given logging state.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_LISTENER_COUNT = 16;
+
+//-----------------------------------------------------------------------------
+// An invalid color set on a channel to imply that it should use
+// a device-dependent default color where applicable.
+//-----------------------------------------------------------------------------
+const Color UNSPECIFIED_LOGGING_COLOR( 0, 0, 0, 0 );
+
+//-----------------------------------------------------------------------------
+// An ID returned by the logging system to refer to a logging channel.
+//-----------------------------------------------------------------------------
+typedef int LoggingChannelID_t;
+
+//-----------------------------------------------------------------------------
+// A sentinel value indicating an invalid logging channel ID.
+//-----------------------------------------------------------------------------
+const LoggingChannelID_t INVALID_LOGGING_CHANNEL_ID = -1;
+
+//-----------------------------------------------------------------------------
+// The severity of a logging operation.
+//-----------------------------------------------------------------------------
+enum LoggingSeverity_t
+{
+ //-----------------------------------------------------------------------------
+ // An informative logging message.
+ //-----------------------------------------------------------------------------
+ LS_MESSAGE = 0,
+
+ //-----------------------------------------------------------------------------
+ // A warning, typically non-fatal
+ //-----------------------------------------------------------------------------
+ LS_WARNING = 1,
+
+ //-----------------------------------------------------------------------------
+ // A message caused by an Assert**() operation.
+ //-----------------------------------------------------------------------------
+ LS_ASSERT = 2,
+
+ //-----------------------------------------------------------------------------
+ // An error, typically fatal/unrecoverable.
+ //-----------------------------------------------------------------------------
+ LS_ERROR = 3,
+
+ //-----------------------------------------------------------------------------
+ // A placeholder level, higher than any legal value.
+ // Not a real severity value!
+ //-----------------------------------------------------------------------------
+ LS_HIGHEST_SEVERITY = 4,
+};
+
+//-----------------------------------------------------------------------------
+// Action which should be taken by logging system as a result of
+// a given logged message.
+//
+// The logging system invokes ILoggingResponsePolicy::OnLog() on
+// the specified policy object, which returns a LoggingResponse_t.
+//-----------------------------------------------------------------------------
+enum LoggingResponse_t
+{
+ LR_CONTINUE,
+ LR_DEBUGGER,
+ LR_ABORT,
+};
+
+//-----------------------------------------------------------------------------
+// Logging channel behavior flags, set on channel creation.
+//-----------------------------------------------------------------------------
+enum LoggingChannelFlags_t
+{
+ //-----------------------------------------------------------------------------
+ // Indicates that the spew is only relevant to interactive consoles.
+ //-----------------------------------------------------------------------------
+ LCF_CONSOLE_ONLY = 0x00000001,
+
+ //-----------------------------------------------------------------------------
+ // Indicates that spew should not be echoed to any output devices.
+ // A suitable logging listener must be registered which respects this flag
+ // (e.g. a file logger).
+ //-----------------------------------------------------------------------------
+ LCF_DO_NOT_ECHO = 0x00000002,
+};
+
+//-----------------------------------------------------------------------------
+// A callback function used to register tags on a logging channel
+// during initialization.
+//-----------------------------------------------------------------------------
+typedef void ( *RegisterTagsFunc )();
+
+//-----------------------------------------------------------------------------
+// A context structure passed to logging listeners and response policy classes.
+//-----------------------------------------------------------------------------
+struct LoggingContext_t
+{
+ // ID of the channel being logged to.
+ LoggingChannelID_t m_ChannelID;
+ // Flags associated with the channel.
+ LoggingChannelFlags_t m_Flags;
+ // Severity of the logging event.
+ LoggingSeverity_t m_Severity;
+ // Color of logging message if one was specified to Log_****() macro.
+ // If not specified, falls back to channel color.
+ // If channel color is not specified, this value is UNSPECIFIED_LOGGING_COLOR
+ // and indicates that a suitable default should be chosen.
+ Color m_Color;
+};
+
+//-----------------------------------------------------------------------------
+// Interface for classes to handle logging output.
+//
+// The Log() function of this class is called synchronously and serially
+// by the logging system on all registered instances of ILoggingListener
+// in the current "logging state".
+//
+// Derived classes may do whatever they want with the message (write to disk,
+// write to console, send over the network, drop on the floor, etc.).
+//
+// In general, derived classes should do one, simple thing with the output
+// to allow callers to register multiple, orthogonal logging listener classes.
+//-----------------------------------------------------------------------------
+class ILoggingListener
+{
+public:
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Interface for policy classes which determine how to behave when a
+// message is logged.
+//
+// Can return:
+// LR_CONTINUE (continue execution)
+// LR_DEBUGGER (break into debugger if one is present, otherwise continue)
+// LR_ABORT (terminate process immediately with a failure code of 1)
+//-----------------------------------------------------------------------------
+class ILoggingResponsePolicy
+{
+public:
+ virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext ) = 0;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Common Logging Listeners & Logging Response Policies
+//////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+// A basic logging listener which prints to stdout and the debug channel.
+//-----------------------------------------------------------------------------
+class CSimpleLoggingListener : public ILoggingListener
+{
+public:
+ CSimpleLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) :
+ m_bQuietPrintf( bQuietPrintf ),
+ m_bQuietDebugger( bQuietDebugger )
+ {
+ }
+
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
+ {
+#ifdef _X360
+ if ( !m_bQuietDebugger && XBX_IsConsoleConnected() )
+ {
+ // send to console
+ XBX_DebugString( XMAKECOLOR( 0,0,0 ), pMessage );
+ }
+ else
+#endif
+ {
+#if !defined( _CERT ) && !defined( DBGFLAG_STRINGS_STRIP )
+ if ( !m_bQuietPrintf )
+ {
+ _tprintf( _T("%s"), pMessage );
+ }
+#endif
+
+#ifdef _WIN32
+ if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
+ {
+ Plat_DebugString( pMessage );
+ }
+#endif
+ }
+ }
+
+ // If set to true, does not print anything to stdout.
+ bool m_bQuietPrintf;
+ // If set to true, does not print anything to debugger.
+ bool m_bQuietDebugger;
+};
+
+//-----------------------------------------------------------------------------
+// A basic logging listener for GUI applications
+//-----------------------------------------------------------------------------
+class CSimpleWindowsLoggingListener : public ILoggingListener
+{
+public:
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
+ {
+ if ( Plat_IsInDebugSession() )
+ {
+ Plat_DebugString( pMessage );
+ }
+ if ( pContext->m_Severity == LS_ERROR )
+ {
+ if ( Plat_IsInDebugSession() )
+ DebuggerBreak();
+
+ Plat_MessageBox( "Error", pMessage );
+ }
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// ** NOTE FOR INTEGRATION **
+// This was copied over from source 2 rather than integrated because
+// source 2 has more significantly refactored tier0 logging.
+//
+// A logging listener with Win32 console API color support which which prints
+// to stdout and the debug channel.
+//-----------------------------------------------------------------------------
+#if !defined(_GAMECONSOLE)
+class CColorizedLoggingListener : public CSimpleLoggingListener
+{
+public:
+ CColorizedLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) : CSimpleLoggingListener( bQuietPrintf, bQuietDebugger )
+ {
+ InitWin32ConsoleColorContext( &m_ColorContext );
+ }
+
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
+ {
+ if ( !m_bQuietPrintf )
+ {
+ int nPrevColor = -1;
+
+ if ( pContext->m_Color != UNSPECIFIED_LOGGING_COLOR )
+ {
+ nPrevColor = SetWin32ConsoleColor( &m_ColorContext,
+ pContext->m_Color.r(), pContext->m_Color.g(), pContext->m_Color.b(),
+ MAX( MAX( pContext->m_Color.r(), pContext->m_Color.g() ), pContext->m_Color.b() ) > 128 );
+ }
+
+ _tprintf( _T("%s"), pMessage );
+
+ if ( nPrevColor >= 0 )
+ {
+ RestoreWin32ConsoleColor( &m_ColorContext, nPrevColor );
+ }
+ }
+
+#ifdef _WIN32
+ if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
+ {
+ Plat_DebugString( pMessage );
+ }
+#endif
+ }
+
+ Win32ConsoleColorContext_t m_ColorContext;
+};
+#endif // !_GAMECONSOLE
+
+
+//-----------------------------------------------------------------------------
+// Default logging response policy used when one is not specified.
+//-----------------------------------------------------------------------------
+class CDefaultLoggingResponsePolicy : public ILoggingResponsePolicy
+{
+public:
+ virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
+ {
+ if ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) )
+ {
+ return LR_DEBUGGER;
+ }
+ else if ( pContext->m_Severity == LS_ERROR )
+ {
+ return LR_ABORT;
+ }
+ else
+ {
+ return LR_CONTINUE;
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+// A logging response policy which never terminates the process, even on error.
+//-----------------------------------------------------------------------------
+class CNonFatalLoggingResponsePolicy : public ILoggingResponsePolicy
+{
+public:
+ virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
+ {
+ if ( ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) ) || pContext->m_Severity == LS_ERROR )
+ {
+ return LR_DEBUGGER;
+ }
+ else
+ {
+ return LR_CONTINUE;
+ }
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Central Logging System
+//////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+// The central logging system.
+//
+// Multiple instances can exist, though all exported tier0 functionality
+// specifically works with a single global instance
+// (via GetGlobalLoggingSystem()).
+//-----------------------------------------------------------------------------
+class CLoggingSystem
+{
+public:
+ struct LoggingChannel_t;
+
+ CLoggingSystem();
+ ~CLoggingSystem();
+
+ //-----------------------------------------------------------------------------
+ // Register a logging channel with the logging system.
+ // The same channel can be registered multiple times, but the parameters
+ // in each call to RegisterLoggingChannel must either match across all calls
+ // or be set to defaults on any given call
+ //
+ // This function is not thread-safe and should generally only be called
+ // by a single thread. Using the logging channel definition macros ensures
+ // that this is called on the static initialization thread.
+ //-----------------------------------------------------------------------------
+ LoggingChannelID_t RegisterLoggingChannel( const char *pChannelName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t minimumSeverity = LS_MESSAGE, Color spewColor = UNSPECIFIED_LOGGING_COLOR );
+
+ //-----------------------------------------------------------------------------
+ // Gets a channel ID from a string name.
+ // Performs a simple linear search; cache the value whenever possible
+ // or re-register the logging channel to get a global ID.
+ //-----------------------------------------------------------------------------
+ LoggingChannelID_t FindChannel( const char *pChannelName ) const;
+
+ int GetChannelCount() const { return m_nChannelCount; }
+
+ //-----------------------------------------------------------------------------
+ // Gets a pointer to the logging channel description.
+ //-----------------------------------------------------------------------------
+ LoggingChannel_t *GetChannel( LoggingChannelID_t channelID );
+ const LoggingChannel_t *GetChannel( LoggingChannelID_t channelID ) const;
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the given channel has the specified tag.
+ //-----------------------------------------------------------------------------
+ bool HasTag( LoggingChannelID_t channelID, const char *pTag ) const { return GetChannel( channelID )->HasTag( pTag ); }
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the given channel has been initialized.
+ // The main purpose is catching m_nChannelCount being zero because no channels have been registered.
+ //-----------------------------------------------------------------------------
+ bool IsValidChannelID( LoggingChannelID_t channelID ) const { return ( channelID >= 0 ) && ( channelID < m_nChannelCount ); }
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the given channel will spew at the given severity level.
+ //-----------------------------------------------------------------------------
+ bool IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity ) const { return IsValidChannelID( channelID ) && GetChannel( channelID )->IsEnabled( severity ); }
+
+ //-----------------------------------------------------------------------------
+ // Functions to set the spew level of a channel either directly by ID or
+ // string name, or for all channels with a given tag.
+ //
+ // These functions are not technically thread-safe but calling them across
+ // multiple threads should cause no significant problems
+ // (the underlying data types being changed are 32-bit/atomic).
+ //-----------------------------------------------------------------------------
+ void SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
+ void SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
+ void SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
+
+ //-----------------------------------------------------------------------------
+ // Gets or sets the color of a logging channel.
+ // (The functions are not thread-safe, but the consequences are not
+ // significant.)
+ //-----------------------------------------------------------------------------
+ Color GetChannelColor( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_SpewColor; }
+ void SetChannelColor( LoggingChannelID_t channelID, Color color ) { GetChannel( channelID )->m_SpewColor = color; }
+
+ //-----------------------------------------------------------------------------
+ // Gets or sets the flags on a logging channel.
+ // (The functions are not thread-safe, but the consequences are not
+ // significant.)
+ //-----------------------------------------------------------------------------
+ LoggingChannelFlags_t GetChannelFlags( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_Flags; }
+ void SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags ) { GetChannel( channelID )->m_Flags = flags; }
+
+ //-----------------------------------------------------------------------------
+ // Adds a string tag to a channel.
+ // This is not thread-safe and should only be called by a RegisterTagsFunc
+ // callback passed in to RegisterLoggingChannel (via the
+ // channel definition macros).
+ //-----------------------------------------------------------------------------
+ void AddTagToCurrentChannel( const char *pTagName );
+
+ //-----------------------------------------------------------------------------
+ // Functions to save/restore the current logging state.
+ // Set bThreadLocal to true on a matching Push/Pop call if the intent
+ // is to override the logging listeners on the current thread only.
+ //
+ // Pushing the current logging state onto the state stack results
+ // in the current state being cleared by default (no listeners, default logging response policy).
+ // Set bClearState to false to copy the existing listener pointers to the new state.
+ //
+ // These functions which mutate logging state ARE thread-safe and are
+ // guarded by m_StateMutex.
+ //-----------------------------------------------------------------------------
+ void PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
+ void PopLoggingState( bool bThreadLocal = false );
+
+ //-----------------------------------------------------------------------------
+ // Registers a logging listener (a class which handles logged messages).
+ //-----------------------------------------------------------------------------
+ void RegisterLoggingListener( ILoggingListener *pListener );
+
+ //-----------------------------------------------------------------------------
+ // Removes a logging listener from the registered list
+ //-----------------------------------------------------------------------------
+ void UnregisterLoggingListener( ILoggingListener *pListener );
+
+ //-----------------------------------------------------------------------------
+ // Returns whether the specified logging listener is registered.
+ //-----------------------------------------------------------------------------
+ bool IsListenerRegistered( ILoggingListener *pListener );
+
+ //-----------------------------------------------------------------------------
+ // Clears out all of the current logging state (removes all listeners,
+ // sets the response policy to the default).
+ //-----------------------------------------------------------------------------
+ void ResetCurrentLoggingState();
+
+ //-----------------------------------------------------------------------------
+ // Sets a policy class to decide what should happen when messages of a
+ // particular severity are logged
+ // (e.g. exit on error, break into debugger).
+ // If pLoggingResponse is NULL, uses the default response policy class.
+ //-----------------------------------------------------------------------------
+ void SetLoggingResponsePolicy( ILoggingResponsePolicy *pLoggingResponse );
+
+ //-----------------------------------------------------------------------------
+ // Logs a message to the specified channel using a given severity and
+ // spew color. Passing in UNSPECIFIED_LOGGING_COLOR for 'color' allows
+ // the logging listeners to provide a default.
+ // NOTE: test 'IsChannelEnabled(channelID,severity)' before calling this!
+ //-----------------------------------------------------------------------------
+ LoggingResponse_t LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar *pMessage );
+
+ // Internal data to represent a logging tag
+ struct LoggingTag_t
+ {
+ const char *m_pTagName;
+ LoggingTag_t *m_pNextTag;
+ };
+
+ // Internal data to represent a logging channel.
+ struct LoggingChannel_t
+ {
+ bool HasTag( const char *pTag ) const
+ {
+ LoggingTag_t *pCurrentTag = m_pFirstTag;
+ while( pCurrentTag != NULL )
+ {
+ if ( stricmp( pCurrentTag->m_pTagName, pTag ) == 0 )
+ {
+ return true;
+ }
+ pCurrentTag = pCurrentTag->m_pNextTag;
+ }
+ return false;
+ }
+ bool IsEnabled( LoggingSeverity_t severity ) const { return severity >= m_MinimumSeverity; }
+ void SetSpewLevel( LoggingSeverity_t severity ) { m_MinimumSeverity = severity; }
+
+ LoggingChannelID_t m_ID;
+ LoggingChannelFlags_t m_Flags; // an OR'd combination of LoggingChannelFlags_t
+ LoggingSeverity_t m_MinimumSeverity; // The minimum severity level required to activate this channel.
+ Color m_SpewColor;
+ char m_Name[MAX_LOGGING_IDENTIFIER_LENGTH];
+ LoggingTag_t *m_pFirstTag;
+ };
+
+private:
+ // Represents the current state of the logger (registered listeners, response policy class, etc.) and can
+ // vary from thread-to-thread. It can also be pushed/popped to save/restore listener/response state.
+ struct LoggingState_t
+ {
+ // Index of the previous entry on the listener set stack.
+ int m_nPreviousStackEntry;
+
+ // Number of active listeners in this set. Cannot exceed MAX_LOGGING_LISTENER_COUNT.
+ // If set to -1, implies that this state structure is not in use.
+ int m_nListenerCount;
+ // Array of registered logging listener objects.
+ ILoggingListener *m_RegisteredListeners[MAX_LOGGING_LISTENER_COUNT];
+
+ // Specific policy class to determine behavior of logging system under specific message types.
+ ILoggingResponsePolicy *m_pLoggingResponse;
+ };
+
+ // These state functions to assume the caller has already grabbed the mutex.
+ LoggingState_t *GetCurrentState();
+ const LoggingState_t *GetCurrentState() const;
+
+ int FindUnusedStateIndex();
+ LoggingTag_t *AllocTag( const char *pTagName );
+
+ int m_nChannelCount;
+ LoggingChannel_t m_RegisteredChannels[MAX_LOGGING_CHANNEL_COUNT];
+
+ int m_nChannelTagCount;
+ LoggingTag_t m_ChannelTags[MAX_LOGGING_TAG_COUNT];
+
+ // Index to first free character in name pool.
+ int m_nTagNamePoolIndex;
+ // Pool of character data used for tag names.
+ char m_TagNamePool[MAX_LOGGING_TAG_CHARACTER_COUNT];
+
+ // Protects all data in this class except the registered channels
+ // (which are supposed to be registered using the macros at static/global init time).
+ // It is assumed that this mutex is reentrant safe on all platforms.
+ CThreadFastMutex *m_pStateMutex;
+
+ // The index of the current "global" state of the logging system. By default, all threads use this state
+ // for logging unless a given thread has pushed the logging state with bThreadLocal == true.
+ // If a thread-local state has been pushed, g_nThreadLocalStateIndex (a global thread-local integer) will be non-zero.
+ // By default, g_nThreadLocalStateIndex is 0 for all threads.
+ int m_nGlobalStateIndex;
+
+ // A pool of logging states used to store a stack (potentially per-thread).
+ static const int MAX_LOGGING_STATE_COUNT = 16;
+ LoggingState_t m_LoggingStates[MAX_LOGGING_STATE_COUNT];
+
+ // Default policy class which determines behavior.
+ CDefaultLoggingResponsePolicy m_DefaultLoggingResponse;
+
+ // Default spew function.
+ CSimpleLoggingListener m_DefaultLoggingListener;
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Logging Macros
+//////////////////////////////////////////////////////////////////////////
+
+// This macro will resolve to the most appropriate overload of LoggingSystem_Log() depending on the number of parameters passed in.
+#ifdef DBGFLAG_STRINGS_STRIP
+#define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( Severity == LS_ERROR && LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
+#else
+#define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
+#endif
+
+//-----------------------------------------------------------------------------
+// New macros, use these!
+//
+// The macros take an optional Color parameter followed by the message
+// and the message formatting.
+// We rely on the variadic macro (__VA_ARGS__) operator to paste in the
+// extra parameters and resolve to the appropriate overload.
+//-----------------------------------------------------------------------------
+#define Log_Msg( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_MESSAGE, /* [Color], Message, */ ##__VA_ARGS__ )
+#define Log_Warning( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_WARNING, /* [Color], Message, */ ##__VA_ARGS__ )
+#define Log_Error( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_ERROR, /* [Color], Message, */ ##__VA_ARGS__ )
+#ifdef DBGFLAG_STRINGS_STRIP
+#define Log_Assert( ... ) LR_CONTINUE
+#else
+#define Log_Assert( Message, ... ) LoggingSystem_LogAssert( Message, ##__VA_ARGS__ )
+#endif
+
+
+#define DECLARE_LOGGING_CHANNEL( Channel ) extern LoggingChannelID_t Channel
+
+#define DEFINE_LOGGING_CHANNEL_NO_TAGS( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
+ LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, NULL, ##__VA_ARGS__ )
+
+#define BEGIN_DEFINE_LOGGING_CHANNEL( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
+ static void Register_##Channel##_Tags(); \
+ LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, Register_##Channel##_Tags, ##__VA_ARGS__ ); \
+ void Register_##Channel##_Tags() \
+ {
+
+#define ADD_LOGGING_CHANNEL_TAG( Tag ) LoggingSystem_AddTagToCurrentChannel( Tag )
+
+#define END_DEFINE_LOGGING_CHANNEL() \
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// DLL Exports
+//////////////////////////////////////////////////////////////////////////
+
+// For documentation on these functions, please look at the corresponding function
+// in CLoggingSystem (unless otherwise specified).
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_RegisterLoggingChannel( const char *pName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t severity = LS_MESSAGE, Color color = UNSPECIFIED_LOGGING_COLOR );
+
+PLATFORM_INTERFACE void LoggingSystem_RegisterLoggingListener( ILoggingListener *pListener );
+PLATFORM_INTERFACE void LoggingSystem_UnregisterLoggingListener( ILoggingListener *pListener );
+PLATFORM_INTERFACE void LoggingSystem_ResetCurrentLoggingState();
+PLATFORM_INTERFACE void LoggingSystem_SetLoggingResponsePolicy( ILoggingResponsePolicy *pResponsePolicy );
+// NOTE: PushLoggingState() saves the current logging state on a stack and results in a new clear state
+// (no listeners, default logging response policy).
+PLATFORM_INTERFACE void LoggingSystem_PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
+PLATFORM_INTERFACE void LoggingSystem_PopLoggingState( bool bThreadLocal = false );
+
+PLATFORM_INTERFACE void LoggingSystem_AddTagToCurrentChannel( const char *pTagName );
+
+// Returns INVALID_LOGGING_CHANNEL_ID if not found
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_FindChannel( const char *pChannelName );
+PLATFORM_INTERFACE int LoggingSystem_GetChannelCount();
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetFirstChannelID();
+// Returns INVALID_LOGGING_CHANNEL_ID when there are no channels remaining.
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetNextChannelID( LoggingChannelID_t channelID );
+PLATFORM_INTERFACE const CLoggingSystem::LoggingChannel_t *LoggingSystem_GetChannel( LoggingChannelID_t channelID );
+
+PLATFORM_INTERFACE bool LoggingSystem_HasTag( LoggingChannelID_t channelID, const char *pTag );
+
+PLATFORM_INTERFACE bool LoggingSystem_IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
+
+// Color is represented as an int32 due to C-linkage restrictions
+PLATFORM_INTERFACE int32 LoggingSystem_GetChannelColor( LoggingChannelID_t channelID );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelColor( LoggingChannelID_t channelID, int color );
+
+PLATFORM_INTERFACE LoggingChannelFlags_t LoggingSystem_GetChannelFlags( LoggingChannelID_t channelID );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags );
+
+//-----------------------------------------------------------------------------
+// Logs a variable-argument to a given channel with the specified severity.
+// NOTE: if adding overloads to this function, remember that the Log_***
+// macros simply pass their variadic parameters through to LoggingSystem_Log().
+// Therefore, you need to ensure that the parameters are in the same general
+// order and that there are no ambiguities with the overload.
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, const char *pMessageFormat, ... ) FMTFUNCTION( 3, 4 );
+PLATFORM_OVERLOAD LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessageFormat, ... ) FMTFUNCTION( 4, 5 );
+
+PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessage );
+PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogAssert( const char *pMessageFormat, ... ) FMTFUNCTION( 1, 2 );
+
+#endif // LOGGING_H \ No newline at end of file
diff --git a/external/vpc/public/tier0/mem.h b/external/vpc/public/tier0/mem.h
new file mode 100644
index 0000000..ffb590b
--- /dev/null
+++ b/external/vpc/public/tier0/mem.h
@@ -0,0 +1,50 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Memory allocation!
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_MEM_H
+#define TIER0_MEM_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <stddef.h>
+
+
+#include "tier0/platform.h"
+
+#if !defined(STATIC_TIER0) && !defined(_STATIC_LINKED)
+
+#ifdef TIER0_DLL_EXPORT
+# define MEM_INTERFACE DLL_EXPORT
+#else
+# define MEM_INTERFACE DLL_IMPORT
+#endif
+
+#else // BUILD_AS_DLL
+
+#define MEM_INTERFACE extern
+
+#endif // BUILD_AS_DLL
+
+
+
+//-----------------------------------------------------------------------------
+// DLL-exported methods for particular kinds of memory
+//-----------------------------------------------------------------------------
+MEM_INTERFACE void *MemAllocScratch( int nMemSize );
+MEM_INTERFACE void MemFreeScratch();
+
+#if defined( POSIX )
+MEM_INTERFACE void ZeroMemory( void *mem, size_t length );
+#endif
+
+//Only works with USE_MEM_DEBUG and memory allocation call stack tracking enabled.
+MEM_INTERFACE int GetAllocationCallStack( void *mem, void **pCallStackOut, int iMaxEntriesOut );
+
+
+#endif /* TIER0_MEM_H */
diff --git a/external/vpc/public/tier0/memalloc.h b/external/vpc/public/tier0/memalloc.h
new file mode 100644
index 0000000..4254e74
--- /dev/null
+++ b/external/vpc/public/tier0/memalloc.h
@@ -0,0 +1,701 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This header should never be used directly from leaf code!!!
+// Instead, just add the file memoverride.cpp into your project and all this
+// will automagically be used
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_MEMALLOC_H
+#define TIER0_MEMALLOC_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// These memory debugging switches aren't relevant under Linux builds since memoverride.cpp
+// isn't built into Linux projects
+#ifndef LINUX
+// Define this in release to get memory tracking even in release builds
+//#define USE_MEM_DEBUG 1
+
+// Define this in release to get light memory debugging
+//#define USE_LIGHT_MEM_DEBUG
+
+// Define this to require -uselmd to turn light memory debugging on
+//#define LIGHT_MEM_DEBUG_REQUIRES_CMD_LINE_SWITCH
+#endif
+
+#if defined( _MEMTEST )
+#if defined( _WIN32 ) || defined( _PS3 )
+#define USE_MEM_DEBUG 1
+#endif
+#endif
+
+
+#if defined( _PS3 )
+// Define STEAM_SHARES_GAME_ALLOCATOR to make Steam use the game's tier0 memory allocator.
+// This adds some memory to the game's Small Block Heap and Medium Block Heap, to compensate.
+// This configuration was disabled for Portal 2, as we could not sufficiently test it before ship.
+//#define STEAM_SHARES_GAME_ALLOCATOR
+#endif
+
+#if defined( STEAM_SHARES_GAME_ALLOCATOR )
+#define MBYTES_STEAM_SBH_USAGE 2
+#define MBYTES_STEAM_MBH_USAGE 4
+#else // STEAM_SHARES_GAME_ALLOCATOR
+#define MBYTES_STEAM_SBH_USAGE 0
+#define MBYTES_STEAM_MBH_USAGE 0
+#endif // STEAM_SHARES_GAME_ALLOCATOR
+
+// Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
+#define MEM_DEBUG_CLASSNAME 1
+
+#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
+
+#include <stddef.h>
+#ifdef LINUX
+#undef offsetof
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+#endif
+
+#ifdef _PS3
+#define MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS 1
+#endif
+
+#include "tier0/mem.h"
+
+struct _CrtMemState;
+
+#define MEMALLOC_VERSION 1
+
+typedef size_t (*MemAllocFailHandler_t)( size_t );
+
+struct GenericMemoryStat_t
+{
+ const char *name;
+ int value;
+};
+
+
+// Virtual memory interface
+#include "tier0/memvirt.h"
+
+
+//-----------------------------------------------------------------------------
+// NOTE! This should never be called directly from leaf code
+// Just use new,delete,malloc,free etc. They will call into this eventually
+//-----------------------------------------------------------------------------
+abstract_class IMemAlloc
+{
+public:
+ // Release versions
+ virtual void *Alloc( size_t nSize ) = 0;
+public:
+ virtual void *Realloc( void *pMem, size_t nSize ) = 0;
+
+ virtual void Free( void *pMem ) = 0;
+ virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize ) = 0;
+
+ // Debug versions
+ virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ) = 0;
+public:
+ virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
+ virtual void Free( void *pMem, const char *pFileName, int nLine ) = 0;
+ virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+ virtual void *AllocAlign( size_t nSize, size_t align ) = 0;
+ virtual void *AllocAlign( size_t nSize, size_t align, const char *pFileName, int nLine ) = 0;
+ virtual void *ReallocAlign( void *pMem, size_t nSize, size_t align ) = 0;
+#endif
+
+ inline void *IndirectAlloc( size_t nSize ) { return Alloc( nSize ); }
+ inline void *IndirectAlloc( size_t nSize, const char *pFileName, int nLine ) { return Alloc( nSize, pFileName, nLine ); }
+
+ // Returns the size of a particular allocation (NOTE: may be larger than the size requested!)
+ virtual size_t GetSize( void *pMem ) = 0;
+
+ // Force file + line information for an allocation
+ virtual void PushAllocDbgInfo( const char *pFileName, int nLine ) = 0;
+ virtual void PopAllocDbgInfo() = 0;
+
+ // FIXME: Remove when we have our own allocator
+ // these methods of the Crt debug code is used in our codebase currently
+ virtual int32 CrtSetBreakAlloc( int32 lNewBreakAlloc ) = 0;
+ virtual int CrtSetReportMode( int nReportType, int nReportMode ) = 0;
+ virtual int CrtIsValidHeapPointer( const void *pMem ) = 0;
+ virtual int CrtIsValidPointer( const void *pMem, unsigned int size, int access ) = 0;
+ virtual int CrtCheckMemory( void ) = 0;
+ virtual int CrtSetDbgFlag( int nNewFlag ) = 0;
+ virtual void CrtMemCheckpoint( _CrtMemState *pState ) = 0;
+
+ // FIXME: Make a better stats interface
+ virtual void DumpStats() = 0;
+ virtual void DumpStatsFileBase( char const *pchFileBase ) = 0;
+ virtual size_t ComputeMemoryUsedBy( char const *pchSubStr ) = 0;
+
+ // FIXME: Remove when we have our own allocator
+ virtual void* CrtSetReportFile( int nRptType, void* hFile ) = 0;
+ virtual void* CrtSetReportHook( void* pfnNewHook ) = 0;
+ virtual int CrtDbgReport( int nRptType, const char * szFile,
+ int nLine, const char * szModule, const char * pMsg ) = 0;
+
+ virtual int heapchk() = 0;
+
+ virtual bool IsDebugHeap() = 0;
+
+ virtual void GetActualDbgInfo( const char *&pFileName, int &nLine ) = 0;
+ virtual void RegisterAllocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
+ virtual void RegisterDeallocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
+
+ virtual int GetVersion() = 0;
+
+ virtual void CompactHeap() = 0;
+
+ // Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread)
+ virtual MemAllocFailHandler_t SetAllocFailHandler( MemAllocFailHandler_t pfnMemAllocFailHandler ) = 0;
+
+ virtual void DumpBlockStats( void * ) = 0;
+
+ virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0;
+
+ // Returns 0 if no failure, otherwise the size_t of the last requested chunk
+ virtual size_t MemoryAllocFailed() = 0;
+
+ virtual void CompactIncremental() = 0;
+
+ virtual void OutOfMemory( size_t nBytesAttempted = 0 ) = 0;
+
+ // Region-based allocations
+ virtual void *RegionAlloc( int region, size_t nSize ) = 0;
+ virtual void *RegionAlloc( int region, size_t nSize, const char *pFileName, int nLine ) = 0;
+
+ // Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
+ virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;
+
+ // Obtain virtual memory manager interface
+ virtual IVirtualMemorySection * AllocateVirtualMemorySection( size_t numMaxBytes ) = 0;
+
+ // Request 'generic' memory stats (returns a list of N named values; caller should assume this list will change over time)
+ virtual int GetGenericMemoryStats( GenericMemoryStat_t **ppMemoryStats ) = 0;
+
+ virtual ~IMemAlloc() { };
+
+ // handles storing allocation info for coroutines
+ virtual uint32 GetDebugInfoSize() = 0;
+ virtual void SaveDebugInfo( void *pvDebugInfo ) = 0;
+ virtual void RestoreDebugInfo( const void *pvDebugInfo ) = 0;
+ virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Singleton interface
+//-----------------------------------------------------------------------------
+#ifdef _PS3
+
+PLATFORM_INTERFACE IMemAlloc * g_pMemAllocInternalPS3;
+#ifndef PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
+#define g_pMemAlloc g_pMemAllocInternalPS3
+#else
+#define g_pMemAlloc PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
+#endif
+
+#else // !_PS3
+
+MEM_INTERFACE IMemAlloc *g_pMemAlloc;
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifdef MEMALLOC_REGIONS
+#ifndef MEMALLOC_REGION
+#define MEMALLOC_REGION 0
+#endif
+inline void *MemAlloc_Alloc( size_t nSize )
+{
+ return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize );
+}
+
+inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize, pFileName, nLine );
+}
+#else
+#undef MEMALLOC_REGION
+inline void *MemAlloc_Alloc( size_t nSize )
+{
+ return g_pMemAlloc->IndirectAlloc( nSize );
+}
+
+inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine );
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifdef MEMALLOC_REGIONS
+#else
+#endif
+
+
+inline bool ValueIsPowerOfTwo( size_t value ) // don't clash with mathlib definition
+{
+ return (value & ( value - 1 )) == 0;
+}
+
+
+inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
+{
+#ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ unsigned char *pAlloc, *pResult;
+
+#endif
+
+ if (!ValueIsPowerOfTwo(align))
+ return NULL;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->AllocAlign( size, align );
+
+#else
+
+ align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
+
+ if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL)
+ return NULL;
+
+ pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
+ ((unsigned char**)(pResult))[-1] = pAlloc;
+
+ return (void *)pResult;
+
+#endif
+}
+
+inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
+{
+#ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ unsigned char *pAlloc, *pResult;
+
+#endif
+
+ if (!ValueIsPowerOfTwo(align))
+ return NULL;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->AllocAlign( size, align, pszFile, nLine );
+
+#else
+
+ align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
+
+ if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL)
+ return NULL;
+
+ pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
+ ((unsigned char**)(pResult))[-1] = pAlloc;
+
+ return (void *)pResult;
+
+#endif
+}
+
+#ifdef USE_MEM_DEBUG
+#define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
+#elif defined(USE_LIGHT_MEM_DEBUG)
+extern const char *g_pszModule;
+#define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
+#else
+#define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedUnattributed( s, a )
+#endif
+
+
+inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
+{
+ if ( !ValueIsPowerOfTwo( align ) )
+ return NULL;
+
+ // Don't change alignment between allocation + reallocation.
+ if ( ( (size_t)ptr & ( align - 1 ) ) != 0 )
+ return NULL;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->ReallocAlign( ptr, size, align );
+
+#else
+
+ if ( !ptr )
+ return MemAlloc_AllocAligned( size, align );
+
+ void *pAlloc, *pResult;
+
+ // Figure out the actual allocation point
+ pAlloc = ptr;
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+ pAlloc = *( (void **)pAlloc );
+
+ // See if we have enough space
+ size_t nOffset = (size_t)ptr - (size_t)pAlloc;
+ size_t nOldSize = g_pMemAlloc->GetSize( pAlloc );
+ if ( nOldSize >= size + nOffset )
+ return ptr;
+
+ pResult = MemAlloc_AllocAligned( size, align );
+ memcpy( pResult, ptr, nOldSize - nOffset );
+ g_pMemAlloc->Free( pAlloc );
+ return pResult;
+
+#endif
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock )
+{
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ g_pMemAlloc->Free( pMemBlock );
+
+#else
+
+ void *pAlloc;
+
+ if ( pMemBlock == NULL )
+ return;
+
+ pAlloc = pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+
+ // pAlloc is the pointer to the start of memory block
+ pAlloc = *( (void **)pAlloc );
+
+ g_pMemAlloc->Free( pAlloc );
+
+#endif
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
+{
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ g_pMemAlloc->Free( pMemBlock, pszFile, nLine );
+
+#else
+
+ void *pAlloc;
+
+ if ( pMemBlock == NULL )
+ return;
+
+ pAlloc = pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+
+ // pAlloc is the pointer to the start of memory block
+ pAlloc = *( (void **)pAlloc );
+ g_pMemAlloc->Free( pAlloc, pszFile, nLine );
+
+#endif
+}
+
+inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
+{
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->GetSize( pMemBlock );
+
+#else
+
+ void *pAlloc;
+
+ if ( pMemBlock == NULL )
+ return 0;
+
+ pAlloc = pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+
+ // pAlloc is the pointer to the start of memory block
+ pAlloc = *((void **)pAlloc );
+ return g_pMemAlloc->GetSize( pAlloc ) - ( (byte *)pMemBlock - (byte *)pAlloc );
+
+#endif
+}
+
+
+struct aligned_tmp_t
+{
+ // empty base class
+};
+
+// template here to allow adding alignment at levels of hierarchy that aren't the base
+template< int bytesAlignment = 16, class T = aligned_tmp_t >
+class CAlignedNewDelete : public T
+{
+public:
+ void *operator new( size_t nSize )
+ {
+ return MemAlloc_AllocAligned( nSize, bytesAlignment );
+ }
+
+ void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
+ {
+ return MemAlloc_AllocAlignedFileLine( nSize, bytesAlignment, pFileName, nLine );
+ }
+
+ void operator delete(void *pData)
+ {
+ if ( pData )
+ {
+ MemAlloc_FreeAligned( pData );
+ }
+ }
+
+ void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
+ {
+ if ( pData )
+ {
+ MemAlloc_FreeAligned( pData, pFileName, nLine );
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
+#define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ )
+#define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line )
+#define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo()
+#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
+#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
+#else
+#define MEM_ALLOC_CREDIT_(tag) ((void)0)
+#define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0)
+#define MemAlloc_PopAllocDbgInfo() ((void)0)
+#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
+#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+
+class CMemAllocAttributeAlloction
+{
+public:
+ CMemAllocAttributeAlloction( const char *pszFile, int line )
+ {
+ MemAlloc_PushAllocDbgInfo( pszFile, line );
+ }
+
+ ~CMemAllocAttributeAlloction()
+ {
+ MemAlloc_PopAllocDbgInfo();
+ }
+};
+
+#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
+
+//-----------------------------------------------------------------------------
+
+#if defined(MSVC) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) )
+
+ #pragma warning(disable:4290)
+ #pragma warning(push)
+ #include <typeinfo.h>
+
+ // MEM_DEBUG_CLASSNAME is opt-in.
+ // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads
+ // simultaneously, it'll need a mutex.
+ #if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)
+
+ template <typename T> const char *MemAllocClassName( T *p )
+ {
+ static const char *pszName = typeid(*p).name(); // @TODO: support having debug heap ignore certain allocations, and ignore memory allocated here [5/7/2009 tom]
+ return pszName;
+ }
+
+ #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( MemAllocClassName( this ) )
+ #define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name())
+ #else
+ #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ )
+ #define MEM_ALLOC_CLASSNAME(type) (__FILE__)
+ #endif
+
+ // MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example )
+ #ifdef _MSC_VER
+ #define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ )
+ #else
+ #define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__)
+ #endif
+
+ #pragma warning(pop)
+#else
+ #define MEM_ALLOC_CREDIT_CLASS()
+ #define MEM_ALLOC_CLASSNAME(type) NULL
+ #define MEM_ALLOC_CREDIT_FUNCTION()
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
+struct MemAllocFileLine_t
+{
+ const char *pszFile;
+ int line;
+};
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \
+ static CUtlMap<void *, MemAllocFileLine_t, int> s_##tag##Allocs( DefLessFunc( void *) ); \
+ CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs = &s_##tag##Allocs; \
+ static CThreadFastMutex s_##tag##AllocsMutex; \
+ CThreadFastMutex * g_p##tag##AllocsMutex = &s_##tag##AllocsMutex; \
+ const char * g_psz##tag##Alloc = strcpy( (char *)MemAlloc_Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
+
+#define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag ) \
+ extern CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs; \
+ extern CThreadFastMutex *g_p##tag##AllocsMutex; \
+ extern const char * g_psz##tag##Alloc;
+
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
+ if ( !p ) \
+ ; \
+ else \
+ { \
+ AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
+ MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
+ g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
+ if ( fileLine.pszFile != g_psz##tag##Alloc ) \
+ { \
+ g_p##tag##Allocs->Insert( p, fileLine ); \
+ } \
+ \
+ MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
+ }
+
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
+ if ( !p ) \
+ ; \
+ else \
+ { \
+ AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
+ MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
+ CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_p##tag##Allocs->Find( p ); \
+ if ( iRecordedFileLine != g_p##tag##Allocs->InvalidIndex() ) \
+ { \
+ fileLine = (*g_p##tag##Allocs)[iRecordedFileLine]; \
+ g_p##tag##Allocs->RemoveAt( iRecordedFileLine ); \
+ } \
+ \
+ MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
+ }
+
+#else
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
+#define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag )
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
+
+//-----------------------------------------------------------------------------
+
+#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
+#include <malloc.h>
+
+#define MEM_ALLOC_CREDIT_(tag) ((void)0)
+#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
+#define MEM_ALLOC_CREDIT_CLASS()
+#define MEM_ALLOC_CLASSNAME(type) NULL
+
+#define MemAlloc_PushAllocDbgInfo( pszFile, line )
+#define MemAlloc_PopAllocDbgInfo()
+
+#define MemAlloc_RegisterAllocation( a,b,c,d,e ) ((void)0)
+#define MemAlloc_RegisterDeallocation( a,b,c,d,e ) ((void)0)
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
+
+inline void *MemAlloc_AllocAligned( size_t size, size_t align )
+{
+ return (void *)_aligned_malloc( size, align );
+}
+inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
+{
+ pszFile = pszFile;
+ nLine = nLine;
+ return (void *)_aligned_malloc( size, align );
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock )
+{
+ _aligned_free( pMemBlock );
+}
+inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
+{
+ pszFile = pszFile;
+ nLine = nLine;
+ _aligned_free( pMemBlock );
+}
+
+#endif // !STEAM && NO_MALLOC_OVERRIDE
+
+//-----------------------------------------------------------------------------
+
+
+
+// linux memory tracking via hooks.
+#if defined( POSIX ) && !defined( _PS3 )
+PLATFORM_INTERFACE void MemoryLogMessage( char const *s ); // throw a message into the memory log
+PLATFORM_INTERFACE void EnableMemoryLogging( bool bOnOff );
+PLATFORM_INTERFACE void DumpMemoryLog( int nThresh );
+PLATFORM_INTERFACE void DumpMemorySummary( void );
+PLATFORM_INTERFACE void SetMemoryMark( void );
+PLATFORM_INTERFACE void DumpChangedMemory( int nThresh );
+
+// ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
+PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
+#else
+inline void MemoryLogMessage( char const * )
+{
+}
+inline void EnableMemoryLogging( bool )
+{
+}
+inline void DumpMemoryLog( int )
+{
+}
+inline void DumpMemorySummary( void )
+{
+}
+inline void SetMemoryMark( void )
+{
+}
+inline void DumpChangedMemory( int )
+{
+}
+inline size_t ApproximateProcessMemoryUsage( void )
+{
+ return 0;
+}
+#endif
+
+
+#endif /* TIER0_MEMALLOC_H */
diff --git a/external/vpc/public/tier0/memdbgoff.h b/external/vpc/public/tier0/memdbgoff.h
new file mode 100644
index 0000000..4d2c021
--- /dev/null
+++ b/external/vpc/public/tier0/memdbgoff.h
@@ -0,0 +1,25 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This header, which must be the final line of a .h file,
+// causes all crt methods to stop using debugging versions of the memory allocators.
+// NOTE: Use memdbgon.h to re-enable memory debugging.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifdef MEM_OVERRIDE_ON
+
+#undef malloc
+#undef realloc
+#undef calloc
+#undef free
+#undef _expand
+#undef _msize
+#undef new
+#undef _aligned_malloc
+#undef _aligned_free
+#undef _malloc_dbg
+
+#undef MEM_OVERRIDE_ON
+
+#endif
diff --git a/external/vpc/public/tier0/memdbgon.h b/external/vpc/public/tier0/memdbgon.h
new file mode 100644
index 0000000..e66664d
--- /dev/null
+++ b/external/vpc/public/tier0/memdbgon.h
@@ -0,0 +1,281 @@
+//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This header, which must be the final include in a .cpp (or .h) file,
+// causes all crt methods to use debugging versions of the memory allocators.
+// NOTE: Use memdbgoff.h to disable memory debugging.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+// SPECIAL NOTE! This file must *not* use include guards; we need to be able
+// to include this potentially multiple times (since we can deactivate debugging
+// by including memdbgoff.h)
+
+#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
+
+// SPECIAL NOTE #2: This must be the final include in a .cpp or .h file!!!
+
+#if defined(_DEBUG) && !defined(USE_MEM_DEBUG) && !defined( _PS3 )
+#define USE_MEM_DEBUG 1
+#endif
+
+// If debug build or ndebug and not already included MS custom alloc files, or already included this file
+#if (defined(_DEBUG) || !defined(_INC_CRTDBG)) || defined(MEMDBGON_H)
+
+#include "tier0/basetypes.h"
+
+#include "tier0/valve_off.h"
+ #ifdef COMPILER_MSVC
+ #include <tchar.h>
+ #else
+ #include <wchar.h>
+ #endif
+ #include <string.h>
+ #ifndef _PS3
+ #include <malloc.h>
+ #endif
+#include "tier0/valve_on.h"
+
+#include "commonmacros.h"
+#include "memalloc.h"
+
+#ifdef _WIN32
+#ifndef MEMALLOC_REGION
+#define MEMALLOC_REGION 0
+#endif
+#else
+#undef MEMALLOC_REGION
+#endif
+
+#if defined(USE_MEM_DEBUG)
+ #if defined( POSIX ) || defined( _PS3 )
+ #define _NORMAL_BLOCK 1
+
+ #include "tier0/valve_off.h"
+ #include <cstddef>
+ #include <new>
+ #include <sys/types.h>
+ #if !defined( DID_THE_OPERATOR_NEW )
+ #define DID_THE_OPERATOR_NEW
+ // posix doesn't have a new of this form, so we impl our own
+ void* operator new( size_t nSize, int blah, const char *pFileName, int nLine );
+ void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine );
+ #endif
+
+ #else // defined(POSIX)
+
+ // Include crtdbg.h and make sure _DEBUG is set to 1.
+ #if !defined(_DEBUG)
+ #define _DEBUG 1
+ #include <crtdbg.h>
+ #undef _DEBUG
+ #else
+ #include <crtdbg.h>
+ #endif // !defined(_DEBUG)
+
+ #endif // defined(POSIX)
+#endif
+
+#include "tier0/memdbgoff.h"
+
+// --------------------------------------------------------
+// Debug/non-debug agnostic elements
+
+#define MEM_OVERRIDE_ON 1
+
+#undef malloc
+#undef realloc
+#undef calloc
+#undef _expand
+#undef free
+#undef _msize
+#undef _aligned_malloc
+#undef _aligned_free
+
+#ifndef MEMDBGON_H
+inline void *MemAlloc_InlineCallocMemset( void *pMem, size_t nCount, size_t nElementSize)
+{
+ memset(pMem, 0, nElementSize * nCount);
+ return pMem;
+}
+#endif
+
+#define calloc(c, s) MemAlloc_InlineCallocMemset(malloc(c*s), c, s)
+#ifndef USE_LIGHT_MEM_DEBUG
+#define free(p) g_pMemAlloc->Free( p )
+#define _aligned_free( p ) MemAlloc_FreeAligned( p )
+#else
+extern const char *g_pszModule;
+#define free(p) g_pMemAlloc->Free( p, g_pszModule, 0 )
+#define _aligned_free( p ) MemAlloc_FreeAligned( p, g_pszModule, 0 )
+#endif
+#define _msize(p) g_pMemAlloc->GetSize( p )
+#define _expand(p, s) _expand_NoLongerSupported(p, s)
+
+// --------------------------------------------------------
+// Debug path
+#if defined(USE_MEM_DEBUG)
+
+#define malloc(s) MemAlloc_Alloc( s, __FILE__, __LINE__)
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s, __FILE__, __LINE__ )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
+
+#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s)
+
+#undef new
+
+#if defined( _PS3 )
+ #ifndef PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ #define PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ inline void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ inline void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ #endif
+ #define new new( 1, __FILE__, __LINE__ )
+#elif !defined( GNUC )
+ #if defined(__AFX_H__) && defined(DEBUG_NEW)
+ #define new DEBUG_NEW
+ #else
+ #define MEMALL_DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
+ #define new MEMALL_DEBUG_NEW
+ #endif
+#endif
+
+#undef _strdup
+#undef strdup
+#undef _wcsdup
+#undef wcsdup
+
+#define _strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__)
+#define strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__)
+#define _wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__)
+#define wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__)
+
+// Make sure we don't define strdup twice
+#if !defined(MEMDBGON_H)
+
+inline char *MemAlloc_StrDup(const char *pString, const char *pFileName, unsigned nLine)
+{
+ char *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = strlen(pString) + 1;
+ if ((pMemory = (char *)MemAlloc_Alloc(len, pFileName, nLine)) != NULL)
+ {
+ return strcpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString, const char *pFileName, unsigned nLine)
+{
+ wchar_t *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = (wcslen(pString) + 1);
+ if ((pMemory = (wchar_t *)MemAlloc_Alloc(len * sizeof(wchar_t), pFileName, nLine)) != NULL)
+ {
+ return wcscpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+#endif // DBMEM_DEFINED_STRDUP
+
+#else
+// --------------------------------------------------------
+// Release path
+
+#ifndef USE_LIGHT_MEM_DEBUG
+#define malloc(s) MemAlloc_Alloc( s )
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a )
+#else
+#define malloc(s) MemAlloc_Alloc( s, g_pszModule, 0 )
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s, g_pszModule, 0 )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
+#endif
+
+#ifndef _malloc_dbg
+#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s)
+#endif
+
+#undef new
+
+#if defined( _PS3 ) && !defined( _CERT )
+ #ifndef PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ #define PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ inline void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ inline void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ #endif
+ #define new new( 1, __FILE__, __LINE__ )
+#endif
+
+#undef _strdup
+#undef strdup
+#undef _wcsdup
+#undef wcsdup
+
+#define _strdup(s) MemAlloc_StrDup(s)
+#define strdup(s) MemAlloc_StrDup(s)
+#define _wcsdup(s) MemAlloc_WcStrDup(s)
+#define wcsdup(s) MemAlloc_WcStrDup(s)
+
+// Make sure we don't define strdup twice
+#if !defined(MEMDBGON_H)
+
+inline char *MemAlloc_StrDup(const char *pString)
+{
+ char *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = strlen(pString) + 1;
+ if ((pMemory = (char *)malloc(len)) != NULL)
+ {
+ return strcpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString)
+{
+ wchar_t *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = (wcslen(pString) + 1);
+ if ((pMemory = (wchar_t *)malloc(len * sizeof(wchar_t))) != NULL)
+ {
+ return wcscpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+#endif // DBMEM_DEFINED_STRDUP
+
+#endif // USE_MEM_DEBUG
+
+#define MEMDBGON_H // Defined here so can be used above
+
+#else
+
+#if defined(USE_MEM_DEBUG)
+#ifndef _STATIC_LINKED
+#pragma message ("Note: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build")
+#else
+#error "Error: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build. Not recoverable in static build"
+#endif
+#endif
+#endif // _INC_CRTDBG
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
diff --git a/external/vpc/public/tier0/memvirt.h b/external/vpc/public/tier0/memvirt.h
new file mode 100644
index 0000000..eeb0996
--- /dev/null
+++ b/external/vpc/public/tier0/memvirt.h
@@ -0,0 +1,46 @@
+//========== Copyright (C) Valve Corporation, All rights reserved. ==========//
+//
+// Purpose: CVirtualMemoryManager interface
+//
+//===========================================================================//
+
+#ifndef MEM_VIRT_H
+#define MEM_VIRT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#define VMM_KB ( 1024 )
+#define VMM_MB ( 1024 * VMM_KB )
+
+#ifdef _PS3
+// Total virtual address space reserved by CVirtualMemoryManager on startup:
+#define VMM_VIRTUAL_SIZE ( 512 * VMM_MB )
+#define VMM_PAGE_SIZE ( 64 * VMM_KB )
+#endif
+
+
+
+// Allocate virtual sections via IMemAlloc::AllocateVirtualMemorySection
+abstract_class IVirtualMemorySection
+{
+public:
+ // Information about memory section
+ virtual void * GetBaseAddress() = 0;
+ virtual size_t GetPageSize() = 0;
+ virtual size_t GetTotalSize() = 0;
+
+ // Functions to manage physical memory mapped to virtual memory
+ virtual bool CommitPages( void *pvBase, size_t numBytes ) = 0;
+ virtual void DecommitPages( void *pvBase, size_t numBytes ) = 0;
+
+ // Release the physical memory and associated virtual address space
+ virtual void Release() = 0;
+};
+
+// Get the IVirtualMemorySection associated with a given memory address (if any):
+extern IVirtualMemorySection *GetMemorySectionForAddress( void *pAddress );
+
+
+#endif // MEM_VIRT_H
diff --git a/external/vpc/public/tier0/minidump.h b/external/vpc/public/tier0/minidump.h
new file mode 100644
index 0000000..8f4b7b0
--- /dev/null
+++ b/external/vpc/public/tier0/minidump.h
@@ -0,0 +1,82 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef MINIDUMP_H
+#define MINIDUMP_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+// writes out a minidump of the current stack trace with a unique filename
+PLATFORM_INTERFACE void WriteMiniDump();
+
+typedef void (*FnWMain)( int , tchar *[] );
+
+#ifdef IS_WINDOWS_PC
+
+// calls the passed in function pointer and catches any exceptions/crashes thrown by it, and writes a minidump
+// use from wmain() to protect the whole program
+
+PLATFORM_INTERFACE void CatchAndWriteMiniDump( FnWMain pfn, int argc, tchar *argv[] );
+
+// The ExceptionInfo_t struct is a typeless data struct
+// which is OS-dependent and should never be used by external code.
+// Just pass it back into MinidumpSetUnhandledExceptionFunction
+struct ExceptionInfo_t;
+
+
+// Replaces the current function pointer with the one passed in.
+// Returns the previously-set function.
+// The function is called internally by WriteMiniDump() and CatchAndWriteMiniDump()
+// The default is the built-in function that uses DbgHlp.dll's MiniDumpWriteDump function
+typedef void (*FnMiniDump)( unsigned int uStructuredExceptionCode, ExceptionInfo_t * pExceptionInfo );
+PLATFORM_INTERFACE FnMiniDump SetMiniDumpFunction( FnMiniDump pfn );
+
+// Use this to write a minidump explicitly.
+// Some of the tools choose to catch the minidump themselves instead of using CatchAndWriteMinidump
+// so they can show their own dialog.
+//
+// ptchMinidumpFileNameBuffer if not-NULL should be a writable tchar buffer of length at
+// least _MAX_PATH and on return will contain the name of the minidump file written.
+// If ptchMinidumpFileNameBuffer is NULL the name of the minidump file written will not
+// be available after the function returns.
+//
+
+
+// NOTE: Matches windows.h
+enum MinidumpType_t
+{
+ MINIDUMP_Normal = 0x00000000,
+ MINIDUMP_WithDataSegs = 0x00000001,
+ MINIDUMP_WithFullMemory = 0x00000002,
+ MINIDUMP_WithHandleData = 0x00000004,
+ MINIDUMP_FilterMemory = 0x00000008,
+ MINIDUMP_ScanMemory = 0x00000010,
+ MINIDUMP_WithUnloadedModules = 0x00000020,
+ MINIDUMP_WithIndirectlyReferencedMemory = 0x00000040,
+ MINIDUMP_FilterModulePaths = 0x00000080,
+ MINIDUMP_WithProcessThreadData = 0x00000100,
+ MINIDUMP_WithPrivateReadWriteMemory = 0x00000200,
+ MINIDUMP_WithoutOptionalData = 0x00000400,
+ MINIDUMP_WithFullMemoryInfo = 0x00000800,
+ MINIDUMP_WithThreadInfo = 0x00001000,
+ MINIDUMP_WithCodeSegs = 0x00002000
+};
+
+PLATFORM_INTERFACE bool WriteMiniDumpUsingExceptionInfo(
+ unsigned int uStructuredExceptionCode,
+ ExceptionInfo_t *pExceptionInfo,
+ uint32 nMinidumpTypeFlags, // OR-ed together MinidumpType_t flags
+ tchar *ptchMinidumpFileNameBuffer = NULL
+ );
+
+PLATFORM_INTERFACE void MinidumpSetUnhandledExceptionFunction( FnMiniDump pfn );
+
+#endif
+
+#endif // MINIDUMP_H
diff --git a/external/vpc/public/tier0/p4performancecounters.h b/external/vpc/public/tier0/p4performancecounters.h
new file mode 100644
index 0000000..d0882b9
--- /dev/null
+++ b/external/vpc/public/tier0/p4performancecounters.h
@@ -0,0 +1,322 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef P4PERFORMANCECOUNTERS_H
+#define P4PERFORMANCECOUNTERS_H
+
+#pragma once
+// Pentium 4 support
+
+/*
+ http://developer.intel.com/design/Pentium4/documentation.htm
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 1: Basic Architecture
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, A-M
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 2B: Instruction Set Reference, N-Z
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 3: System Programming Guide
+
+
+ From Mikael Pettersson's perfctr:
+
+ http://user.it.uu.se/~mikpe/linux/perfctr/
+
+ * Known quirks:
+ - OVF_PMI+FORCE_OVF counters must have an ireset value of -1.
+ This allows the regular overflow check to also handle FORCE_OVF
+ counters. Not having this restriction would lead to MAJOR
+ complications in the driver's "detect overflow counters" code.
+ There is no loss of functionality since the ireset value doesn't
+ affect the counter's PMI rate for FORCE_OVF counters.
+
+ - In experiments with FORCE_OVF counters, and regular OVF_PMI
+ counters with small ireset values between -8 and -1, it appears
+ that the faulting instruction is subjected to a new PMI before
+ it can complete, ad infinitum. This occurs even though the driver
+ clears the CCCR (and in testing also the ESCR) and invokes a
+ user-space signal handler before restoring the CCCR and resuming
+ the instruction.
+*/
+
+#define NCOUNTERS 18
+
+// The 18 counters
+enum Counters
+{
+ MSR_BPU_COUNTER0,
+ MSR_BPU_COUNTER1,
+ MSR_BPU_COUNTER2,
+ MSR_BPU_COUNTER3,
+ MSR_MS_COUNTER0,
+ MSR_MS_COUNTER1,
+ MSR_MS_COUNTER2,
+ MSR_MS_COUNTER3,
+ MSR_FLAME_COUNTER0,
+ MSR_FLAME_COUNTER1,
+ MSR_FLAME_COUNTER2,
+ MSR_FLAME_COUNTER3,
+ MSR_IQ_COUNTER0,
+ MSR_IQ_COUNTER1,
+ MSR_IQ_COUNTER2,
+ MSR_IQ_COUNTER3,
+ MSR_IQ_COUNTER4,
+ MSR_IQ_COUNTER5
+};
+
+// register base for counters
+#define MSR_COUNTER_BASE 0x300
+
+// register base for CCCR register
+#define MSR_CCCR_BASE 0x360
+
+#pragma pack(push, 1)
+// access to these bits is through the methods
+typedef union ESCR
+{
+ struct
+ {
+ uint64 Reserved0_1 : 2; //
+ uint64 USR : 1; //
+ uint64 OS : 1; //
+ uint64 TagEnable : 1; //
+ uint64 TagValue : 4; //
+ uint64 EventMask : 16; // from event select
+ uint64 ESCREventSelect : 6; // 31:25 class of event
+ uint64 Reserved31 : 1; //
+
+ uint64 Reserved32_63 : 32; //
+ };
+ uint64 flat;
+
+} ESCR;
+
+typedef union CCCR
+{
+ struct
+ {
+ uint64 Reserved0_11 : 12;// 0 -11
+ uint64 Enable : 1; // 12
+ uint64 CCCRSelect : 3; // 13-15
+ uint64 Reserved16_17 : 2; // 16 17
+
+ uint64 Compare : 1; // 18
+ uint64 Complement : 1; // 19
+ uint64 Threshold : 4; // 20-23
+ uint64 Edge : 1; // 24
+ uint64 FORCE_OVF : 1; // 25
+ uint64 OVF_PMI : 1; // 26
+ uint64 Reserved27_29 : 3; // 27-29
+ uint64 Cascade : 1; // 30
+ uint64 OVF : 1; // 31
+
+ uint64 Reserved32_63 : 32; //
+ };
+ uint64 flat;
+
+} CCCR;
+
+#pragma pack(pop)
+
+extern const unsigned short cccr_escr_map[NCOUNTERS][8];
+
+enum P4TagState
+{
+ TagDisable, //
+ TagEnable, //
+};
+
+enum P4ForceOverflow
+{
+ ForceOverflowDisable,
+ ForceOverflowEnable,
+};
+
+enum P4OverflowInterrupt
+{
+ OverflowInterruptDisable,
+ OverflowInterruptEnable,
+};
+
+// Turn off the no return value warning in ReadCounter.
+#pragma warning( disable : 4035 )
+class P4BaseEvent
+{
+ int m_counter;
+
+protected:
+
+ void SetCounter(int counter)
+ {
+ m_counter = counter;
+ cccrPort = MSR_CCCR_BASE + m_counter;
+ counterPort = MSR_COUNTER_BASE + m_counter;
+ escrPort = cccr_escr_map[m_counter][cccr.CCCRSelect];
+ }
+
+public:
+
+ unsigned short m_eventMask;
+ const tchar *description;
+ PME *pme;
+ ESCR escr;
+ CCCR cccr;
+ int counterPort;
+ int cccrPort;
+ int escrPort;
+
+ P4BaseEvent()
+ {
+ pme = PME::Instance();
+ m_eventMask = 0;
+ description = _T("");
+ escr.flat = 0;
+ cccr.flat = 0;
+ cccr.Reserved16_17 = 3; // must be set
+ escrPort = 0;
+ m_counter = -1;
+ }
+
+ void StartCounter()
+ {
+ cccr.Enable = 1;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void StopCounter()
+ {
+ cccr.Enable = 0;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void ClearCounter()
+ {
+ pme->WriteMSR( counterPort, 0ui64 ); // clear
+ }
+
+ void WriteCounter( int64 value )
+ {
+ pme->WriteMSR( counterPort, value ); // clear
+ }
+
+ int64 ReadCounter()
+ {
+#if PME_DEBUG
+ if ( escr.USR == 0 && escr.OS == 0 )
+ return -1; // no area to collect, use SetCaptureMode
+
+ if ( escr.EventMask == 0 )
+ return -2; // no event mask set
+
+ if ( m_counter == -1 )
+ return -3; // counter not legal
+#endif
+
+ // ReadMSR should work here too, but RDPMC should be faster
+ int64 value = 0;
+ pme->ReadMSR( counterPort, &value );
+ return value;
+#if 0
+ // we need to copy this into a temp for some reason
+ int temp = m_counter;
+ _asm
+ {
+ mov ecx, temp
+ RDPMC
+ }
+#endif
+ }
+
+ void SetCaptureMode( PrivilegeCapture priv )
+ {
+ switch ( priv )
+ {
+ case OS_Only:
+ {
+ escr.USR = 0;
+ escr.OS = 1;
+ break;
+ }
+ case USR_Only:
+ {
+ escr.USR = 1;
+ escr.OS = 0;
+ break;
+ }
+ case OS_and_USR:
+ {
+ escr.USR = 1;
+ escr.OS = 1;
+ break;
+ }
+ }
+
+ escr.EventMask = m_eventMask;
+ pme->WriteMSR( escrPort, escr.flat );
+ }
+
+ void SetTagging( P4TagState tagEnable, uint8 tagValue )
+ {
+ escr.TagEnable = tagEnable;
+ escr.TagValue = tagValue;
+ pme->WriteMSR( escrPort, escr.flat );
+ }
+
+ void SetFiltering( CompareState compareEnable, CompareMethod compareMethod, uint8 threshold, EdgeState edgeEnable )
+ {
+ cccr.Compare = compareEnable;
+ cccr.Complement = compareMethod;
+ cccr.Threshold = threshold;
+ cccr.Edge = edgeEnable;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void SetOverflowEnables( P4ForceOverflow overflowEnable, P4OverflowInterrupt overflowInterruptEnable )
+ {
+ cccr.FORCE_OVF = overflowEnable;
+ cccr.OVF_PMI = overflowInterruptEnable;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void SetOverflow()
+ {
+ cccr.OVF = 1;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void ClearOverflow()
+ {
+ cccr.OVF = 0;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ bool isOverflow()
+ {
+ CCCR cccr_temp;
+ pme->ReadMSR( cccrPort, &cccr_temp.flat );
+ return cccr_temp.OVF;
+ }
+
+ void SetCascade()
+ {
+ cccr.Cascade = 1;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void ClearCascade()
+ {
+ cccr.Cascade = 0;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+};
+#pragma warning( default : 4035 )
+
+#include "eventmasks.h"
+#include "eventmodes.h"
+
+#endif // P4PERFORMANCECOUNTERS_H
diff --git a/external/vpc/public/tier0/p5p6performancecounters.h b/external/vpc/public/tier0/p5p6performancecounters.h
new file mode 100644
index 0000000..6e2d8b1
--- /dev/null
+++ b/external/vpc/public/tier0/p5p6performancecounters.h
@@ -0,0 +1,225 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef P5P6PERFORMANCECOUNTERS_H
+#define P5P6PERFORMANCECOUNTERS_H
+
+// defined for < Pentium 4
+
+//---------------------------------------------------------------------------
+// Format of the performance event IDs within this header file in case you
+// wish to add any additional events that may not be present here.
+//
+// BITS 0-8 Unit Mask, Unsed on P5 processors
+// BIT 9 Set if event can be set on counter 0
+// BIT 10 Set if event can be set on counter 1
+// BITS 11-15 Unused Set to zero
+// BITS 16-23 Event Select ID, Only bits 16-21 used on P5 Family
+// BITS 24-27 Unused set to zero
+// BITS 28-32 Process family that the event belong to, as returned by
+// the CPUID instruction.
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// PENTIUM PERFORMANCE COUNTERS.
+//---------------------------------------------------------------------------
+#define P5_DTCRD 0x50000300 //Data Cache Reads
+#define P5_DWRIT 0x50010300 //Data Cache Writes
+#define P5_DTTLB 0x50020300 //Data TLB Miss
+#define P5_DTRMS 0x50030300 //Data Read Misses
+#define P5_DWRMS 0x50040300 //Data Write Miss
+#define P5_WHLCL 0x50050300 //Write (Hit) to M- or E-state line
+#define P5_DCLWB 0x50060300 //Data Cache Lines Written Back
+#define P5_DCSNP 0x50070300 //External Snoops
+#define P5_DCSHT 0x50080300 //Data Cache Snoop Hits
+#define P5_MAIBP 0x50090300 //Memory Access in Both Pipes
+#define P5_BANKS 0x500A0300 //Bank Conflicts
+#define P5_MISAL 0x500B0300 //Misaligned Data Memory Reference
+#define P5_COCRD 0x500C0300 //Code Cache Reads
+#define P5_COTLB 0x500D0300 //Code TLB Misses
+#define P5_COCMS 0x500E0300 //Code Cache Misses
+#define P5_ANYSG 0x500F0300 //Any Segment Register Loaded
+#define P5_BRANC 0x50120300 //Branches
+#define P5_BTBHT 0x50130300 //BTB Hits
+#define P5_TBRAN 0x50140300 //Taken Branch or BTB hit
+#define P5_PFLSH 0x50150300 //Pipeline flushes
+#define P5_INSTR 0x50160300 //Instructions Executed
+#define P5_INSTV 0x50170300 //Instructions Executed in the V-Pipe (Pairing)
+#define P5_CLOCL 0x50180300 //Bus active
+#define P5_PSDWR 0x50190300 //Full write buffers
+#define P5_PSWDR 0x501A0300 //Waiting for Data Memory Read
+#define P5_NCLSW 0x501B0300 //Clocks stalled writing an E or M state line
+#define P5_IORWC 0x501D0300 //I/O Read or Write Cycle
+#define P5_NOCMR 0x501E0300 //Non-Cacheable Memory Reads
+#define P5_PSLDA 0x501F0300 //Clocks stalled due to AGI
+#define P5_FLOPS 0x50220300 //Floating Point Operations
+#define P5_DBGR0 0x50230300 //Breakpoint match on DR0
+#define P5_DBGR1 0x50240300 //Breakpoint match on DR1
+#define P5_DBGR2 0x50250300 //Breakpoint match on DR2
+#define P5_DBGR3 0x50260300 //Breakpoint match on DR3
+#define P5_HWINT 0x50270300 //Hardware interrupts
+#define P5_DTRWR 0x50280300 //Data reads or writes
+#define P5_DTRWM 0x50290300 //Data read or write miss
+#define P5_BOLAT 0x502A0100 //Bus ownership latency
+#define P5_BOTFR 0x502A0200 //Bus ownership transfer
+#define P5_MMXA1 0x502B0100 //MMX Instruction Executed in U-pipe
+#define P5_MMXA2 0x502B0200 //MMX Instruction Executed in V-pipe
+#define P5_MMXMS 0x502C0100 //Cache M state line sharing
+#define P5_MMSLS 0x502C0200 //Cache line sharing
+#define P5_MMXB1 0x502D0100 //EMMS Instructions Executed
+#define P5_MMXB2 0x502D0200 //Transition from MMX to FP instructions
+#define P5_NOCMW 0x502E0200 //Non-Cacheable Memory Writes
+#define P5_MMXC1 0x502F0100 //Saturated MMX Instructions Executed
+#define P5_MMXC2 0x502F0200 //Saturations Performed
+#define P5_MMXHS 0x50300100 //Cycles Not in HALT State
+#define P5_MMXD2 0x50310100 //MMX Data Read
+#define P5_MMXFP 0x50320100 //Floating Point Stalls
+#define P5_MMXTB 0x50320200 //Taken Branches
+#define P5_MMXD0 0x50330100 //D1 Starvation and FIFO Empty
+#define P5_MMXD1 0x50330200 //D1 Starvation and one instruction in FIFO
+#define P5_MMXE1 0x50340100 //MMX Data Writes
+#define P5_MMXE2 0x50340200 //MMX Data Write Misses
+#define P5_MMXWB 0x50350100 //Pipeline flushes, wrong branch prediction
+#define P5_MMXWJ 0x50350200 //Pipeline flushes, branch prediction WB-stage
+#define P5_MMXF1 0x50360100 //Misaligned MMX Data Memory Reference
+#define P5_MMXF2 0x50360200 //Pipeline Stalled Waiting for MMX data read
+#define P5_MMXRI 0x50370100 //Returns Predicted Incorrectly
+#define P5_MMXRP 0x50370200 //Returns Predicted
+#define P5_MMXG1 0x50380100 //MMX Multiply Unit Interlock
+#define P5_MMXG2 0x50380200 //MOVD/MOVQ store stall, previous operation
+#define P5_MMXRT 0x50390100 //Returns
+#define P5_MMXRO 0x50390200 //RSB Overflows
+#define P5_MMXBF 0x503A0100 //BTB False entries
+#define P5_MMXBM 0x503A0200 //BTB misprediction on a Not-Taken Branch
+#define P5_PXDWR 0x503B0100 //stalled due MMX Full write buffers
+#define P5_PXZWR 0x503B0200 //stalled on MMX write to E or M state line
+
+#define P5_CLOCK 0x503F0300 //Special value to count clocks on P5
+
+
+//---------------------------------------------------------------------------
+// PENTIUM PRO / PENTIUM II PERFORMANCE COUNTERS.
+//---------------------------------------------------------------------------
+#define P6_STRBB 0x60030300 //Store Buffer Block
+#define P6_STBDC 0x60040300 //Store Buffer Drain Cycles
+#define P6_MISMM 0x60050300 //Misaligned Data Memory Reference
+#define P6_SEGLD 0x60060300 //Segment register loads
+#define P6_FPOPE 0x60100100 //FP Computational Op. (COUNTER 0 ONLY)
+#define P6_FPEOA 0x60110200 //FP Microcode Exceptions (COUNTER 1 ONLY)
+#define P6_FMULT 0x60120200 //Multiplies (COUNTER 1 ONLY)
+#define P6_FPDIV 0x60130200 //Divides (COUNTER 1 ONLY)
+#define P6_DBUSY 0x60140200 //Cycles Divider Busy (COUNTER 1 ONLY)
+#define P6_L2STR 0x60210300 //L2 address strobes => address bus utilization
+#define P6_L2BBS 0x60220300 //Cycles L2 Bus Busy
+#define P6_L2BBT 0x60230300 //Cycles L2 Bus Busy transferring data to CPU
+#define P6_L2ALO 0x60240300 //L2 Lines Allocated
+#define P6_L2MAL 0x60250300 //L2 M-state Lines Allocated
+#define P6_L2CEV 0x60260300 //L2 Lines Evicted
+#define P6_L2MEV 0x60270300 //L2 M-state Lines Evicted
+#define P6_L2MCF 0x60280301 //L2 Cache Instruction Fetch Misses
+#define P6_L2FET 0x6028030F //L2 Cache Instruction Fetches
+#define P6_L2DRM 0x60290301 //L2 Cache Read Misses
+#define P6_L2DMR 0x6029030F //L2 Cache Reads
+#define P6_L2DWM 0x602A0301 //L2 Cache Write Misses
+#define P6_L2DMW 0x602A030F //L2 Cache Writes
+#define P6_L2CMS 0x602E0301 //L2 Cache Request Misses
+#define P6_L2DCR 0x602E030F //L2 Cache Requests
+#define P6_DMREF 0x60430300 //Data Memory References
+#define P6_DCALO 0x6045030F //L1 Lines Allocated
+#define P6_DCMAL 0x60460300 //L1 M-state Data Cache Lines Allocated
+#define P6_DCMEV 0x60470300 //L1 M-state Data Cache Lines Evicted
+#define P6_DCOUT 0x60480300 //L1 Misses outstanding
+#define P6_TSMCD 0x60520300 //Time Self-Modifiying Code Detected
+#define P6_BRWRA 0x60600300 //External Bus Cycles While Receive Active
+#define P6_BRDCD 0x60600300 //External Bus Request Outstanding
+#define P6_BRBNR 0x60610300 //External Bus Cycles While BNR Asserted
+#define P6_BUSBS 0x60620300 //External Bus Cycles-DRDY Asserted (busy)
+#define P6_BLOCK 0x60630300 //External Bus Cycles-LOCK signal asserted
+#define P6_BBRCV 0x60640300 //External Bus Cycles-Processor receiving data
+#define P6_BURST 0x60650300 //External Bus Burst Read Operations
+#define P6_BRINV 0x60660300 //External Bus Read for Ownership Transaction
+#define P6_BMLEV 0x60670300 //External Bus Writeback M-state Evicted
+#define P6_BBIFT 0x60680300 //External Bus Burst Instruction Fetches
+#define P6_BINVL 0x60690300 //External Bus Invalidate Transactions
+#define P6_BPRBT 0x606A0300 //External Bus Partial Read Transactions
+#define P6_BPTMO 0x606B0300 //External Bus Partial Memory Transactions
+#define P6_BUSIO 0x606C0300 //External Bus I/O Bus Transactions
+#define P6_BUSDF 0x606D0300 //External Bus Deferred Transactions
+#define P6_BUSTB 0x606E0300 //External Bus Burst Transactions
+#define P6_BMALL 0x606F0300 //External Bus Memory Transactions
+#define P6_BSALL 0x60700300 //External Bus Transactions
+#define P6_CLOCK 0x60790300 //Clockticks
+#define P6_BRHIT 0x607A0300 //External Bus Cycles While HIT Asserted
+#define P6_BRHTM 0x607B0300 //External Bus Cycles While HITM Asserted
+#define P6_BRSST 0x607E0300 //External Bus Cycles While Snoop Stalled
+#define P6_CMREF 0x60800300 //Total Instruction Fetches
+#define P6_TOIFM 0x60810300 //Total Instruction Fetch Misses
+#define P6_INTLB 0x60850300 //Instructions TLB Misses
+#define P6_CSFET 0x60860300 //Cycles Instruction Fetch Stalled
+#define P6_FTSTL 0x60870300 //Cycles Instruction Fetch stalled
+#define P6_RSTAL 0x60A20300 //Resource Related Stalls
+#define P6_MMXIE 0x60B00300 //MMX Instructions Executed
+#define P6_SAISE 0x60B10300 //Saturated Arithmetic Instructions Executed
+#define P6_PORT0 0x60B20301 //MMX micro-ops executed on Port 0
+#define P6_PORT1 0x60B20302 //MMX micro-ops executed on Port 1
+#define P6_PORT2 0x60B20304 //MMX micro-ops executed on Port 2
+#define P6_PORT3 0x60B20308 //MMX micro-ops executed on Port 3
+#define P6_MMXPA 0x60B30300 //MMX Packed Arithmetic
+#define P6_MMXPM 0x60B30301 //MMX Packed Multiply
+#define P6_MMXPS 0x60B30302 //MMX Packed Shift
+#define P6_MMXPO 0x60B30304 //MMX Packed Operations
+#define P6_MMXUO 0x60B30308 //MMX Unpacked Operations
+#define P6_MMXPL 0x60B30310 //MMX Packed Logical
+#define P6_INSTR 0x60C00300 //Instructions Retired
+#define P6_FPOPS 0x60C10100 //FP operations retired (COUNTER 0 ONLY)
+#define P6_UOPSR 0x60C20300 //Micro-Ops Retired
+#define P6_BRRET 0x60C40300 //Branch Instructions Retired
+#define P6_BRMSR 0x60C50300 //Branch Mispredictions Retired
+#define P6_MASKD 0x60C60300 //Clocks while interrupts masked
+#define P6_MSKPN 0x60C70300 //Clocks while interrupt is pending
+#define P6_HWINT 0x60C80300 //Hardware Interrupts Received
+#define P6_BTAKR 0x60C90300 //Taken Branch Retired
+#define P6_BTAKM 0x60CA0300 //Taken Branch Mispredictions
+#define P6_FPMMX 0x60CC0301 //Transitions from Floating Point to MMX
+#define P6_MMXFP 0x60CC0300 //Transitions from MMX to Floating Point
+#define P6_SIMDA 0x60CD0300 //SIMD Assists (EMMS Instructions Executed)
+#define P6_MMXIR 0x60CE0300 //MMX Instructions Retired
+#define P6_SAISR 0x60CF0300 //Saturated Arithmetic Instructions Retired
+#define P6_INSTD 0x60D00300 //Instructions Decoded
+#define P6_NPRTL 0x60D20300 //Renaming Stalls
+#define P6_SRSES 0x60D40301 //Segment Rename Stalls - ES
+#define P6_SRSDS 0x60D40302 //Segment Rename Stalls - DS
+#define P6_SRSFS 0x60D40304 //Segment Rename Stalls - FS
+#define P6_SRSGS 0x60D40308 //Segment Rename Stalls - GS
+#define P6_SRSXS 0x60D4030F //Segment Rename Stalls - ES DS FS GS
+#define P6_SRNES 0x60D50301 //Segment Renames - ES
+#define P6_SRNDS 0x60D50302 //Segment Renames - DS
+#define P6_SRNFS 0x60D50304 //Segment Renames - FS
+#define P6_SRNGS 0x60D50308 //Segment Renames - GS
+#define P6_SRNXS 0x60D5030F //Segment Renames - ES DS FS GS
+#define P6_BRDEC 0x60E00300 //Branch Instructions Decoded
+#define P6_BTBMS 0x60E20301 //BTB Misses
+#define P6_RETDC 0x60E40300 //Bogus Branches
+#define P6_BACLR 0x60E60300 //BACLEARS Asserted (Testing)
+
+
+
+
+
+
+// INTEL
+#define PENTIUM_FAMILY 5 // define for pentium
+#define PENTIUMPRO_FAMILY 6 // define for pentium pro
+#define PENTIUM4_FAMILY 15 // define for pentium 4
+
+
+// AMD
+#define K6_FAMILY 5
+#define K8_FAMILY 6
+#define EXTENDED_FAMILY 15 // AMD 64 and AMD Opteron
+
+#endif // P5P6PERFORMANCECOUNTERS_H
diff --git a/external/vpc/public/tier0/platform.h b/external/vpc/public/tier0/platform.h
new file mode 100644
index 0000000..4dad5df
--- /dev/null
+++ b/external/vpc/public/tier0/platform.h
@@ -0,0 +1,2032 @@
+//===== Copyright 1997-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+
+#ifdef SN_TARGET_PS3
+
+#define _PS3 1
+#define COMPILER_PS3 1
+#define PLATFORM_PS3 1
+
+// There are 2 compilers for the PS3: GCC and the SN Systems compiler.
+// They are mostly similar, but in a few places we need to distinguish between the two.
+#if defined( __SNC__ )
+#define COMPILER_SNC 1
+#elif defined( __GCC__ )
+#define COMPILER_GCC 1
+#else
+#error "Unrecognized PS3 compiler; either __SNC__ or __GCC__ must be defined"
+#endif
+
+#endif // SN_TARGET_PS3
+
+#ifdef __GCC__
+#define COMPILER_GCC 1
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+#define PLATFORM_PPC 1
+#endif
+
+
+#ifdef COMPILER_MSVC
+#pragma once
+#endif
+
+#if defined (_PS3)
+ #include <ppu_intrinsics.h>
+
+ // We want to force the assert to be redefined, because the STD assert might have been
+ // included and redefined. ps3_assert.h will do a check for assert being redefined.
+ // #include "ps3/ps3_assert.h"
+ #ifndef COMPILER_PS3
+ #error "for PS3, VPC must define COMPILER_PS3 macro just like it does for COMPILER_MSVCX360 macro"
+ #endif
+ #if !defined( COMPILER_SNC ) && !defined( COMPILER_GCC )
+ #error "for PS3, VPC must define COMPILER_SNC or COMPILER_GCC macro, depending on the target compiler, just like it does for COMPILER_MSVCX360 macro"
+ #endif
+
+#elif defined( _X360 )
+ #define NO_STEAM
+ #define NO_VOICE
+ // for the 360, the ppc platform and the rtos are tightly coupled
+ // setup the 360 environment here !once! for much less leaf module include wackiness
+ // these are critical order and purposely appear *before* anything else
+ #define _XBOX
+ #include <xaudio2.h>
+ #include <xbdm.h>
+ #include <xgraphics.h>
+ #include <xui.h>
+ #include <pmcpbsetup.h>
+ #include <xmahardwareabstraction.h>
+ #undef _XBOX
+
+#endif
+
+#include "wchartypes.h"
+#include "tier0/valve_off.h"
+
+#ifdef _PS3
+
+ #include "ps3/ps3_platform.h"
+
+ #define NO_STEAM_GAMECOORDINATOR
+
+#else
+
+ #include <malloc.h>
+ #include <memory.h>
+ #include <limits.h>
+ #include <float.h>
+ #include <stdlib.h>
+ #include <string.h>
+#ifdef OSX
+ #include <signal.h>
+#endif
+
+#endif
+
+// This macro
+#if defined( _PS3 ) && defined ( COMPILER_SNC )
+
+// There are known bugs in the PS3 optimizer. The following macros allow us to lower optimization for a subset of a file
+// If you run into build problems with optimization on, try turning off optimization for the selected file. If that
+// fixes the problem, use process of elimination and the below macros to find the bare minimum that needs to be
+// unoptimized and report the compiler issue to Sony as well.
+//
+// The correlation between optimization levels and numbers passed to the _Pragma xopt and postopt calls is as follows:
+// See: Control-group reference tables / -Xshow
+// .... xopt
+// -O1 0
+// -O2 5
+// -O3 5
+//
+// These macros MUST be used in pairs - Otherwise, the compiler will barf 'At end of source: error 67: expected a "}"'
+
+// xopt disables some of the miscellaneous optimizations
+#if __option(xopt)
+#define SN_OPT_DISABLE extern "C++" { _Pragma("control %push xopt=0")
+#define SN_OPT_ENABLE _Pragma("control %pop xopt") }
+#else // !__option(xopt)
+#define SN_OPT_DISABLE
+#define SN_OPT_ENABLE
+#endif // !__option(xopt)
+
+// postopt disables the main optimizer
+#if __option(postopt) > 0
+#define SN_MAIN_OPT_DISABLE extern "C++" { _Pragma("control %push postopt=0")
+#define SN_MAIN_OPT_ENABLE _Pragma("control %pop postopt") }
+#else // !__option(postopt) > 0
+#define SN_MAIN_OPT_DISABLE
+#define SN_MAIN_OPT_ENABLE
+#endif // !__option(postopt) > 0
+
+#else // ! ( _PS3 && COMPILER_SNC )
+#define SN_OPT_DISABLE
+#define SN_OPT_ENABLE
+#define SN_MAIN_OPT_DISABLE
+#define SN_MAIN_OPT_ENABLE
+#endif // ! ( _PS3 && COMPILER_SNC )
+
+#ifdef __cplusplus
+#if defined( COMPILER_GCC ) || defined( COMPILER_PS3 )
+ #include <new>
+#else
+ #include <new.h>
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// Old-school defines we don't want to use moving forward
+//-----------------------------------------------------------------------------
+#if CROSS_PLATFORM_VERSION < 1
+
+// feature enables
+#define NEW_SOFTWARE_LIGHTING
+#if !defined( _X360 )
+#define SUPPORT_PACKED_STORE
+#endif
+
+#if defined( BINK_VIDEO ) && ( defined( _X360 ) || defined( _PS3 ) )
+#define BINK_ENABLED_FOR_CONSOLE
+#endif
+
+#if !defined( PORTAL2 )
+//#define PORTAL2
+#endif
+
+// C functions for external declarations that call the appropriate C++ methods
+#ifndef EXPORT
+ #ifdef _WIN32
+ #define EXPORT _declspec( dllexport )
+ #else
+ #define EXPORT /* */
+ #endif
+#endif
+
+#endif // CROSS_PLATFORM_VERSION < 1
+
+#if defined(_STATIC_LINKED)
+#include "staticlink/system.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// NOTE: All compiler defines are set up in the base VPC scripts
+// COMPILER_MSVC, COMPILER_MSVC32, COMPILER_MSVC64, COMPILER_MSVCX360
+// COMPILER_GCC
+// The rationale for this is that we need COMPILER_MSVC for the pragma blocks
+// #pragma once that occur at the top of all header files, therefore we can't
+// place the defines for these in here.
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Set up platform defines.
+//-----------------------------------------------------------------------------
+#ifdef _WIN32
+ #define IsPlatformLinux() 0
+ #define IsPlatformPosix() 0
+ #define IsPlatformOSX() 0
+ #define IsOSXOpenGL() 0
+ #define IsPlatformPS3() 0
+ #define IsPlatformPS3_PPU() 0
+ #define IsPlatformPS3_SPU() 0
+ #define PLATFORM_WINDOWS 1
+ #define PLATFORM_OPENGL 0
+
+ #ifndef _X360
+ #define IsPlatformX360() 0
+ #define IsPlatformWindowsPC() 1
+ #define PLATFORM_WINDOWS_PC 1
+
+ #ifdef _WIN64
+ #define IsPlatformWindowsPC64() 1
+ #define IsPlatformWindowsPC32() 0
+ #define PLATFORM_WINDOWS_PC64 1
+ #else
+ #define IsPlatformWindowsPC64() 0
+ #define IsPlatformWindowsPC32() 1
+ #define PLATFORM_WINDOWS_PC32 1
+ #endif
+
+ #else // _X360
+
+ #define IsPlatformWindowsPC() 0
+ #define IsPlatformWindowsPC64() 0
+ #define IsPlatformWindowsPC32() 0
+ #define IsPlatformX360() 1
+ #define PLATFORM_X360 1
+
+ #endif // _X360
+#elif defined(_PS3)
+
+
+#define IsPlatformX360() 0
+#define IsPlatformPS3() 1
+#ifdef SPU
+#define IsPlatformPS3_PPU() 0
+#define IsPlatformPS3_SPU() 1
+#else
+#define IsPlatformPS3_PPU() 1
+#define IsPlatformPS3_SPU() 0
+#endif
+#define IsPlatformWindowsPC() 0
+#define IsPlatformWindowsPC64() 0
+#define IsPlatformWindowsPC32() 0
+#define IsPlatformPosix() 1
+#define PLATFORM_POSIX 1
+#define PLATFORM_OPENGL 0
+
+#define IsPlatformLinux() 0
+#define IsPlatformOSX() 0
+#define IsOSXOpenGL() 0
+
+
+#elif defined(POSIX)
+ #define IsPlatformX360() 0
+ #define IsPlatformPS3() 0
+ #define IsPlatformPS3_PPU() 0
+ #define IsPlatformPS3_SPU() 0
+ #define IsPlatformWindowsPC() 0
+ #define IsPlatformWindowsPC64() 0
+ #define IsPlatformWindowsPC32() 0
+ #define IsPlatformPosix() 1
+ #define PLATFORM_POSIX 1
+
+ #if defined( LINUX ) && !defined( OSX ) // for havok we define both symbols, so don't let the osx build wander down here
+ #define IsPlatformLinux() 1
+ #define IsPlatformOSX() 0
+ #define IsOSXOpenGL() 0
+ #define PLATFORM_OPENGL 0
+ #define PLATFORM_LINUX 1
+ #elif defined ( OSX )
+ #define IsPlatformLinux() 0
+ #define IsPlatformOSX() 1
+ #define IsOSXOpenGL() 1
+ #define PLATFORM_OSX 1
+ #define PLATFORM_OPENGL 1
+ #else
+ #define IsPlatformLinux() 0
+ #define IsPlatformOSX() 0
+ #define IsOSXOpenGL() 0
+ #define PLATFORM_OPENGL 0
+ #endif
+
+#else
+ #error
+#endif
+
+// IsXXXX platform pseudo-functions
+#if ( defined( PLATFORM_WINDOWS ) && ( PLATFORM_WINDOWS ) )
+#define IsPlatformWindows() 1
+#else
+#define IsPlatformWindows() 0
+#endif
+
+#if ( defined( PLATFORM_OPENGL ) && PLATFORM_OPENGL )
+#define IsOpenGL() 1
+#else
+#define IsOpenGL() 0
+#endif
+
+
+
+#ifndef _PS3
+//#include <malloc.h>
+//#include <new.h>
+#else
+#include <stdlib.h> // For malloc()
+#include <alloca.h> // for alloca()
+#define _alloca alloca
+ #ifdef __cplusplus
+ #include <new>
+ #endif
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Old-school defines we're going to support since much code uses them
+//-----------------------------------------------------------------------------
+#if CROSS_PLATFORM_VERSION < 2
+
+#define IsLinux() IsPlatformLinux()
+#define IsOSX() IsPlatformOSX()
+#define IsPosix() IsPlatformPosix()
+#define IsX360() IsPlatformX360()
+#define IsPS3() IsPlatformPS3()
+
+// Setup platform defines.
+#ifdef COMPILER_MSVC
+#define MSVC 1
+#endif
+
+#ifdef COMPILER_GCC
+#define GNUC 1
+#endif
+
+#if defined( _WIN32 )
+#define _WINDOWS 1
+#endif
+
+#ifdef PLATFORM_WINDOWS_PC
+#define IS_WINDOWS_PC 1
+#endif
+
+#endif // CROSS_PLATFORM_VERSION < 2
+
+// VXConsole is enabled for...
+#if defined(_X360) || defined(_PS3)
+#define USE_VXCONSOLE 1
+#define HasVxConsole() 1
+#else
+#define HasVxConsole() 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Set up platform type defines.
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_X360 ) || defined( _PS3 )
+ #ifndef _GAMECONSOLE
+ #define _GAMECONSOLE
+ #endif
+ #define IsPC() 0
+ #define IsGameConsole() 1
+#else
+ #define IsPC() 1
+ #define IsGameConsole() 0
+#endif
+
+
+
+//-----------------------------------------------------------------------------
+// Set up build configuration defines.
+//-----------------------------------------------------------------------------
+#ifdef _CERT
+#define IsCert() 1
+#else
+#define IsCert() 0
+#endif
+
+#ifdef _DEBUG
+#define IsRelease() 0
+#define IsDebug() 1
+#else
+#define IsRelease() 1
+#define IsDebug() 0
+#endif
+
+#ifdef _RETAIL
+#define IsRetail() 1
+#else
+#define IsRetail() 0
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Portable data types
+//-----------------------------------------------------------------------------
+typedef unsigned char uint8;
+typedef signed char int8;
+
+#if defined( COMPILER_MSVC )
+
+ typedef __int16 int16;
+ typedef unsigned __int16 uint16;
+ typedef __int32 int32;
+ typedef unsigned __int32 uint32;
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+
+ // intp is an integer that can accomodate a pointer
+ // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
+ typedef intptr_t intp;
+ typedef uintptr_t uintp;
+
+ #if defined( COMPILER_MSVCX360 )
+ #ifdef __m128
+ #undef __m128
+ #endif
+ #define __m128 __vector4
+ #endif
+
+#else // !COMPILER_MSVC
+
+ typedef short int16;
+ typedef unsigned short uint16;
+ typedef int int32;
+ typedef unsigned int uint32;
+ typedef long long int64;
+ typedef unsigned long long uint64;
+ #ifdef PLATFORM_64BITS
+ typedef long long intp;
+ typedef unsigned long long uintp;
+ #else
+ typedef int intp;
+ typedef unsigned int uintp;
+ #endif
+ typedef void *HWND;
+#endif // else COMPILER_MSVC
+
+#if defined(_PS3) && !defined(NO_SIMD)
+typedef union __attribute__ ((aligned (16)))
+{
+ float m128_f32[4];
+} l_m128;
+
+typedef __vector float __vector4;
+typedef __vector4 __m128;
+
+const __m128 VMX_ZERO=(vector float)(0.0f);
+const __m128 VMX_ONE_HALF=(vector float)(0.5f);
+const __m128 VMX_ONE=(vector float)(1.0f);
+
+// Syntaxic sugar for multiply
+inline __attribute__ ((always_inline)) __m128 __vec_mul(const __m128 a, const __m128 b)
+{
+ return vec_madd(a,b,VMX_ZERO);
+}
+
+// Refined reciprocal function
+inline __attribute__ ((always_inline)) __m128 __vec_rec(const __m128 a)
+{
+ //Get the reciprocal estimate
+ vector float estimate = vec_re( a );
+
+ //One round of Newton-Raphson refinement
+ return vec_madd( vec_nmsub( estimate, a, VMX_ONE ), estimate, estimate );
+}
+
+// refined reciprocal square root
+inline __attribute__ ((always_inline)) __m128 __vec_rsqrt(const __m128 a)
+{
+ //Get the square root reciprocal estimate
+ __m128 estimate = vec_rsqrte( a );
+
+ //One round of Newton-Raphson refinement
+ __m128 estimateSquared = __vec_mul( estimate, estimate);
+ __m128 halfEstimate = __vec_mul( estimate, VMX_ONE_HALF);
+ return vec_madd( vec_nmsub( a, estimateSquared, VMX_ONE ), halfEstimate, estimate );
+}
+
+// refined square root
+inline __attribute__ ((always_inline)) __m128 __vec_sqrt(const __m128 a)
+{
+ return __vec_mul( a, __vec_rsqrt( a ));
+}
+
+// estimate square root
+inline __attribute__ ((always_inline)) __m128 __vec_sqrtest(const __m128 a)
+{
+ return __vec_mul( a, vec_rsqrte( a ));
+}
+
+// Syntaxic sugar for multiply
+inline __attribute__ ((always_inline)) __m128 __vec_div(const __m128 a, const __m128 b)
+{
+ return __vec_mul( a, __vec_rec( b ));
+}
+
+// load an unaligned array of float in a vector of floats
+inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned(const float* in)
+{
+ return vec_perm(vec_ld(0,in),
+ vec_ld(sizeof(__m128),in),
+ vec_lvsl( 0, in ));
+}
+
+// load an unaligned array of 3 floats in a vector of floats, last member being 0.
+inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned3(const float* in)
+{
+ return vec_and(__vec_ld_unaligned(in),(__m128)(vector unsigned int)(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ,0));
+}
+
+// stores a vector of floats in an unaligned array of float
+inline __attribute__ ((always_inline)) void __vec_st_unaligned(__m128 in, float* out)
+{
+ __m128 temp0 = vec_ld(0,out);
+ __m128 temp1 = vec_ld(16,out);
+ vector unsigned char align = vec_lvsr(0,out);
+ vector unsigned char mask = vec_perm ((vector unsigned char)(0), (vector unsigned char)(0xFF), align);
+
+ in = vec_perm ( in, in, align);
+ temp0 = vec_sel ( temp0, in, (vector bool)mask);
+ temp1 = vec_sel ( in, temp1, (vector bool)mask);
+ vec_st ( temp0, 0, out);
+ vec_st ( temp1, 16, out);
+}
+
+// stores x,y,z from a vector of floats in an unaligned array of 3 floats
+inline __attribute__ ((always_inline)) void __vec_st_unaligned3(__m128 in, float* out)
+{
+ __m128 temp0 = vec_ld(0,out);
+ __m128 temp1 = vec_ld(16,out);
+ vector unsigned char align = vec_lvsr(0,out);
+ vector unsigned char mask = vec_perm ((vector unsigned char)(0),
+ (vector unsigned char)(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0),
+ align);
+
+ in = vec_perm ( in, in, align);
+ temp0 = vec_sel ( temp0, in, (vector bool)mask);
+ temp1 = vec_sel ( in, temp1, (vector bool)mask);
+ vec_st ( temp0, 0, out);
+ vec_st ( temp1, 16, out);
+}
+
+#endif // defined(NO_SIMD)
+
+
+typedef float float32;
+typedef double float64;
+
+// for when we don't care about how many bits we use
+typedef unsigned int uint;
+
+#ifdef PLATFORM_POSIX
+#ifndef _PS3
+typedef unsigned int DWORD;
+typedef unsigned int *LPDWORD;
+#endif
+typedef unsigned short WORD;
+typedef void * HINSTANCE;
+#define _MAX_PATH PATH_MAX
+#endif
+
+// MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms
+// As a result, we pick the least common denominator here. This should be used anywhere
+// you might typically want to use RAND_MAX
+#define VALVE_RAND_MAX 0x7fff
+// Maximum and minimum representable values
+#ifndef PLATFORM_OSX
+
+#define INT8_MAX SCHAR_MAX
+#define INT16_MAX SHRT_MAX
+#define INT32_MAX LONG_MAX
+#define INT64_MAX (((int64)~0) >> 1)
+
+#define INT8_MIN SCHAR_MIN
+#define INT16_MIN SHRT_MIN
+#define INT32_MIN LONG_MIN
+#define INT64_MIN (((int64)1) << 63)
+
+#define UINT8_MAX ((uint8)~0)
+#define UINT16_MAX ((uint16)~0)
+#define UINT32_MAX ((uint32)~0)
+#define UINT64_MAX ((uint64)~0)
+
+#define UINT8_MIN 0
+#define UINT16_MIN 0
+#define UINT32_MIN 0
+#define UINT64_MIN 0
+
+#endif // PLATFORM_OSX
+
+#ifndef UINT_MIN
+#define UINT_MIN UINT32_MIN
+#endif
+
+#define FLOAT32_MAX FLT_MAX
+#define FLOAT64_MAX DBL_MAX
+
+#ifdef GNUC
+#undef offsetof
+// Note: can't use builtin offsetof because many use cases (esp. in templates) wouldn't compile due to restrictions on the builtin offsetof
+//#define offsetof( type, var ) __builtin_offsetof( type, var )
+#define offsetof(s,m) ( (size_t)&(((s *)0x1000000)->m) - 0x1000000u )
+#else
+#include <stddef.h>
+#undef offsetof
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+#endif
+
+
+#define FLOAT32_MIN FLT_MIN
+#define FLOAT64_MIN DBL_MIN
+
+//-----------------------------------------------------------------------------
+// Long is evil because it's treated differently by different compilers
+// Preventing its use is nasty however. This #define, which should be
+// turned on in individual VPC files, causes you to include tier0/valve_off.h
+// before standard C + windows headers, and include tier0/valve_on.h after
+// standard C + windows headers. So, there's some painful overhead to disabling long
+//-----------------------------------------------------------------------------
+#ifdef DISALLOW_USE_OF_LONG
+ #define long long_is_the_devil_stop_using_it_use_int32_or_int64
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Various compiler-specific keywords
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_MSVC
+
+ #ifdef FORCEINLINE
+ #undef FORCEINLINE
+ #endif
+ #define STDCALL __stdcall
+ #ifndef FASTCALL
+ #define FASTCALL __fastcall
+ #endif
+ #define FORCEINLINE __forceinline
+ #define FORCEINLINE_TEMPLATE __forceinline
+ #define NULLTERMINATED __nullterminated
+
+ // This can be used to ensure the size of pointers to members when declaring
+ // a pointer type for a class that has only been forward declared
+ #define SINGLE_INHERITANCE __single_inheritance
+ #define MULTIPLE_INHERITANCE __multiple_inheritance
+ #define EXPLICIT explicit
+ #define NO_VTABLE __declspec( novtable )
+
+ // gcc doesn't allow storage specifiers on explicit template instatiation, but visual studio needs them to avoid link errors.
+ #define TEMPLATE_STATIC static
+
+ // Used for dll exporting and importing
+ #define DLL_EXPORT extern "C" __declspec( dllexport )
+ #define DLL_IMPORT extern "C" __declspec( dllimport )
+
+ // Can't use extern "C" when DLL exporting a class
+ #define DLL_CLASS_EXPORT __declspec( dllexport )
+ #define DLL_CLASS_IMPORT __declspec( dllimport )
+
+ // Can't use extern "C" when DLL exporting a global
+ #define DLL_GLOBAL_EXPORT extern __declspec( dllexport )
+ #define DLL_GLOBAL_IMPORT extern __declspec( dllimport )
+
+ // Pass hints to the compiler to prevent it from generating unnessecary / stupid code
+ // in certain situations. Several compilers other than MSVC also have an equivilent
+ // construct.
+ //
+ // Essentially the 'Hint' is that the condition specified is assumed to be true at
+ // that point in the compilation. If '0' is passed, then the compiler assumes that
+ // any subsequent code in the same 'basic block' is unreachable, and thus usually
+ // removed.
+ #define HINT(THE_HINT) __assume((THE_HINT))
+
+ // decls for aligning data
+ #define DECL_ALIGN(x) __declspec( align( x ) )
+
+ // GCC had a few areas where it didn't construct objects in the same order
+ // that Windows does. So when CVProfile::CVProfile() would access g_pMemAlloc,
+ // it would crash because the allocator wasn't initalized yet.
+ #define CONSTRUCT_EARLY
+
+ #define SELECTANY __declspec(selectany)
+
+ #define RESTRICT __restrict
+ #define RESTRICT_FUNC __declspec(restrict)
+ #define FMTFUNCTION( a, b )
+ #define NOINLINE
+
+#if !defined( NO_THREAD_LOCAL )
+ #define DECL_THREAD_LOCAL __declspec(thread)
+#endif
+
+ #define DISABLE_VC_WARNING( x ) __pragma(warning(disable:4310) )
+ #define DEFAULT_VC_WARNING( x ) __pragma(warning(default:4310) )
+
+
+#elif defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
+
+ #if defined( COMPILER_SNC )
+ #define STDCALL
+ #define __stdcall
+ #elif (CROSS_PLATFORM_VERSION >= 1) && !defined( PLATFORM_64BITS ) && !defined( COMPILER_PS3 )
+ #define STDCALL __attribute__ ((__stdcall__))
+ #else
+ #define STDCALL
+ #define __stdcall __attribute__ ((__stdcall__))
+ #endif
+
+ #define FASTCALL
+ #ifdef _LINUX_DEBUGGABLE
+ #define FORCEINLINE
+ #else
+ #ifdef _PS3
+ // [IESTYN 7/29/2010] As of SDK 3.4.0, this causes bad code generation in NET_Tick::ReadFromBuffer in netmessages.cpp,
+ // which caused (seeming) random network packet corruption. It probably causes other bugs too.
+ #define FORCEINLINE inline /* __attribute__ ((always_inline)) */
+ #else
+ #define FORCEINLINE inline __attribute__ ((always_inline))
+ #endif
+ #endif
+
+ // GCC 3.4.1 has a bug in supporting forced inline of templated functions
+ // this macro lets us not force inlining in that case
+ #define FORCEINLINE_TEMPLATE inline
+ #define SINGLE_INHERITANCE
+ #define MULTIPLE_INHERITANCE
+ #define EXPLICIT
+ #define NO_VTABLE
+
+ #define NULLTERMINATED
+
+#if defined( COMPILER_SNC )
+ #define TEMPLATE_STATIC static
+#else
+ #define TEMPLATE_STATIC
+#endif
+
+ // Used for dll exporting and importing
+ #ifdef COMPILER_SNC
+ #define DLL_DECLARATION_DEFAULT_VISIBILITY
+ #else
+ #define DLL_DECLARATION_DEFAULT_VISIBILITY __attribute__ ((visibility("default")))
+ #endif
+ #define DLL_EXPORT extern "C" DLL_DECLARATION_DEFAULT_VISIBILITY
+ #define DLL_IMPORT extern "C"
+
+ // Can't use extern "C" when DLL exporting a class
+#ifndef _PS3
+ #define __stdcall __attribute__ ((__stdcall__))
+#endif
+ #define DLL_CLASS_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
+ #define DLL_CLASS_IMPORT
+
+ // Can't use extern "C" when DLL exporting a global
+ #define DLL_GLOBAL_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
+ #define DLL_GLOBAL_IMPORT extern
+
+ #define HINT(THE_HINT) __builtin_expect( THE_HINT, 1 )
+ #define DECL_ALIGN(x) __attribute__( ( aligned( x ) ) )
+ #define CONSTRUCT_EARLY __attribute__((init_priority(101)))
+ #define SELECTANY __attribute__((weak))
+ #define RESTRICT __restrict__
+ #define RESTRICT_FUNC RESTRICT_FUNC_NOT_YET_DEFINED_FOR_THIS_COMPILER
+ #define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( printf, fmtargnumber, firstvarargnumber )))
+ #define NOINLINE __attribute__ ((noinline))
+
+#if !defined( NO_THREAD_LOCAL )
+ #define DECL_THREAD_LOCAL __thread
+#endif
+
+ #define DISABLE_VC_WARNING( x )
+ #define DEFAULT_VC_WARNING( x )
+
+#else
+
+ #define DECL_ALIGN(x) /* */
+ #define SELECTANY static
+
+#endif
+
+#if defined( GNUC ) && !defined( COMPILER_PS3 ) // use pre-align on PS3
+// gnuc has the align decoration at the end
+#define ALIGN4
+#define ALIGN8
+#define ALIGN16
+#define ALIGN32
+#define ALIGN128
+
+#undef ALIGN16_POST
+#define ALIGN4_POST DECL_ALIGN(4)
+#define ALIGN8_POST DECL_ALIGN(8)
+#define ALIGN16_POST DECL_ALIGN(16)
+#define ALIGN32_POST DECL_ALIGN(32)
+#define ALIGN128_POST DECL_ALIGN(128)
+#else
+// MSVC has the align at the start of the struct
+// PS3 SNC supports both
+#define ALIGN4 DECL_ALIGN(4)
+#define ALIGN8 DECL_ALIGN(8)
+#define ALIGN16 DECL_ALIGN(16)
+#define ALIGN32 DECL_ALIGN(32)
+#define ALIGN128 DECL_ALIGN(128)
+
+#define ALIGN4_POST
+#define ALIGN8_POST
+#define ALIGN16_POST
+#define ALIGN32_POST
+#define ALIGN128_POST
+#endif
+
+// This can be used to declare an abstract (interface only) class.
+// Classes marked abstract should not be instantiated. If they are, and access violation will occur.
+//
+// Example of use:
+//
+// abstract_class CFoo
+// {
+// ...
+// }
+//
+// MSDN __declspec(novtable) documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_novtable.asp
+//
+// Note: NJS: This is not enabled for regular PC, due to not knowing the implications of exporting a class with no no vtable.
+// It's probable that this shouldn't be an issue, but an experiment should be done to verify this.
+//
+#ifndef COMPILER_MSVCX360
+ #define abstract_class class
+#else
+ #define abstract_class class NO_VTABLE
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Why do we need this? It would be nice to make it die die die
+//-----------------------------------------------------------------------------
+// Alloca defined for this platform
+#if defined( COMPILER_MSVC ) && !defined( WINDED )
+ #if defined(_M_IX86)
+ #define __i386__ 1
+ #endif
+#endif
+
+#if defined __i386__ && !defined __linux__
+ #define id386 1
+#else
+ #define id386 0
+#endif // __i386__
+
+
+//-----------------------------------------------------------------------------
+// Disable annoying unhelpful warnings
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_MSVC
+// Remove warnings from warning level 4.
+#pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed
+#pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
+#pragma warning(disable : 4127) // warning C4127: conditional expression is constant
+#pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated
+#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
+#pragma warning(disable : 4710) // warning C4710: function 'x' not inlined
+#pragma warning(disable : 4702) // warning C4702: unreachable code
+#pragma warning(disable : 4505) // unreferenced local function has been removed
+#pragma warning(disable : 4239) // nonstandard extension used : 'argument' ( conversion from class Vector to class Vector& )
+#pragma warning(disable : 4097) // typedef-name 'BaseClass' used as synonym for class-name 'CFlexCycler::CBaseFlex'
+#pragma warning(disable : 4324) // Padding was added at the end of a structure
+#pragma warning(disable : 4244) // type conversion warning.
+#pragma warning(disable : 4305) // truncation from 'const double ' to 'float '
+#pragma warning(disable : 4786) // Disable warnings about long symbol names
+#pragma warning(disable : 4250) // 'X' : inherits 'Y::Z' via dominance
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+
+#if _MSC_VER >= 1300
+#pragma warning(disable : 4511) // Disable warnings about private copy constructors
+#pragma warning(disable : 4121) // warning C4121: 'symbol' : alignment of a member was sensitive to packing
+#pragma warning(disable : 4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc (disabled due to std headers having exception syntax)
+#endif
+
+#if _MSC_VER >= 1400
+#pragma warning(disable : 4996) // functions declared deprecated
+#endif
+
+// When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems...
+#if !defined( COMPILER_MSVC64 )
+#if ( CROSS_PLATFORM_VERSION < 1 )
+#pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
+#pragma warning( disable : 4311 ) // pointer truncation from 'char *' to 'int'
+#pragma warning( disable : 4312 ) // conversion from 'unsigned int' to 'memhandle_t' of greater size
+#endif
+#endif
+
+#elif defined( COMPILER_SNC )
+#pragma diag_suppress=1700 // warning 1700: class "%s" has virtual functions but non-virtual destructor
+// Uncomment the following line if you want to investigate a specific compiler remark without all the noise:
+// #pragma diag_suppress=1700, 83, 162, 182, 192, 194, 229, 238, 262, 341, 382, 401, 402, 403, 481, 817, 828, 833, 1363, 1771, 1774, 1779, 1780, 1783, 1785, 1786, 1788
+#endif
+
+// Pull in the /analyze code annotations.
+#include "annotations.h"
+
+//-----------------------------------------------------------------------------
+// Convert int<-->pointer, avoiding 32/64-bit compiler warnings:
+//-----------------------------------------------------------------------------
+#define INT_TO_POINTER( i ) (void *)( ( i ) + (char *)NULL )
+#define POINTER_TO_INT( p ) ( (int)(uint64)( p ) )
+
+
+//-----------------------------------------------------------------------------
+// Stack-based allocation related helpers
+//-----------------------------------------------------------------------------
+#if defined( COMPILER_GCC ) || defined( COMPILER_SNC )
+
+ #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) )
+
+ #ifdef PLATFORM_OSX
+ #define mallocsize( _p ) ( malloc_size( _p ) )
+ #else
+ #define mallocsize( _p ) ( malloc_usable_size( _p ) )
+ #endif
+
+#elif defined ( COMPILER_MSVC )
+
+ #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) )
+ #define mallocsize( _p ) ( _msize( _p ) )
+
+#endif
+
+#define stackfree( _p ) 0
+
+//-----------------------------------------------------------------------------
+// Used to break into the debugger
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_MSVC64
+ #define DebuggerBreak() __debugbreak()
+#elif COMPILER_MSVC32
+ #define DebuggerBreak() __asm { int 3 }
+#elif COMPILER_MSVCX360
+ #define DebuggerBreak() DebugBreak()
+#elif COMPILER_GCC
+ #if defined( _PS3 )
+ #define DebuggerBreak() { __asm volatile ("tw 31,1,1"); }
+ #elif defined( OSX )
+ #define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm__ __volatile__ ( "int $3" ); } else { raise(SIGTRAP); }
+ #elif defined( PLATFORM_CYGWIN ) || defined( PLATFORM_POSIX )
+ #define DebuggerBreak() __asm__( "int $0x3;")
+ #else
+ #define DebuggerBreak() asm( "int3" )
+ #endif
+#elif defined( COMPILER_SNC ) && defined( COMPILER_PS3 )
+static bool sPS3_SuppressAssertsInThisFile = false; // you can throw this in the debugger to temporarily disable asserts inside any particular .cpp module.
+ #define DebuggerBreak() if (!sPS3_SuppressAssertsInThisFile) __builtin_snpause(); // <sergiy> from SNC Migration Guide, tw 31,1,1
+#else
+#error DebuggerBreak() is not defined for this platform!
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+ #if defined( fsel )
+ #error
+ #endif
+#else
+
+FORCEINLINE float fsel(float fComparand, float fValGE, float fLT)
+{
+ return fComparand >= 0 ? fValGE : fLT;
+}
+FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
+{
+ return fComparand >= 0 ? fValGE : fLT;
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// DLL export for platform utilities
+//-----------------------------------------------------------------------------
+#ifndef STATIC_TIER0
+
+#ifdef TIER0_DLL_EXPORT
+#define PLATFORM_INTERFACE DLL_EXPORT
+#define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT
+#define PLATFORM_CLASS DLL_CLASS_EXPORT
+#else
+#define PLATFORM_INTERFACE DLL_IMPORT
+#define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT
+#define PLATFORM_CLASS DLL_CLASS_IMPORT
+#endif
+
+#else // BUILD_AS_DLL
+
+#define PLATFORM_INTERFACE extern
+#define PLATFORM_OVERLOAD
+#define PLATFORM_CLASS
+
+#endif // BUILD_AS_DLL
+
+
+//-----------------------------------------------------------------------------
+// Returns true if debugger attached, false otherwise
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_WINDOWS ) || defined( _PS3 )
+PLATFORM_INTERFACE void Plat_DebugString( const tchar * );
+#else
+#define Plat_DebugString(s) ((void)0)
+#endif
+
+PLATFORM_INTERFACE bool Plat_IsInDebugSession();
+
+#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
+
+
+//-----------------------------------------------------------------------------
+// Message Box
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_WINDOWS_PC )
+PLATFORM_INTERFACE void Plat_MessageBox( const char *pTitle, const tchar *pMessage );
+#else
+#define Plat_MessageBox( t, m ) ((void)0)
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Posix platform helpers
+//-----------------------------------------------------------------------------
+#ifdef PLATFORM_POSIX
+
+// Visual Studio likes to put an underscore in front of anything that looks like a portable function.
+#define _strupr strupr
+#define _getcwd getcwd
+#define _open open
+#define _lseek lseek
+#define _read read
+#define _close close
+#define _vsnprintf vsnprintf
+#define _stat stat
+#define _O_RDONLY O_RDONLY
+#define _stricmp strcasecmp
+#define _finite finite
+#define _unlink unlink
+#define _putenv putenv
+#define _chdir chdir
+#define _access access
+
+#define strcmpi stricmp
+#define stricmp strcasecmp
+#define _alloca alloca
+#define GetProcAddress dlsym
+#define _chdir chdir
+#ifndef _PS3
+#define _strnicmp strnicmp
+#endif
+#define strnicmp strncasecmp
+#define _snwprintf swprintf
+#define swprintf_s swprintf
+#define wcsicmp _wcsicmp
+#define _wcsicmp wcscmp
+#define _tempnam tempnam
+#define strtok_s strtok_r
+#define _mkdir(dir) mkdir( dir, S_IRWXU | S_IRWXG | S_IRWXO )
+#define _wtoi(arg) wcstol(arg, NULL, 10)
+#define _wtoi64(arg) wcstoll(arg, NULL, 10)
+
+#ifndef _PS3
+typedef uint32 HMODULE;
+#endif
+typedef void *HANDLE;
+#define __cdecl
+
+#if !defined( _snprintf ) // some vpc's define this on the command line
+#define _snprintf snprintf
+#endif
+
+#include <alloca.h>
+#include <unistd.h> // get unlink
+#include <errno.h>
+
+#endif // PLATFORM_POSIX
+
+#ifdef PLATFORM_WINDOWS
+#ifndef SOCKLEN_T
+#define SOCKLEN_T
+typedef int socklen_t;
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// Generally useful platform-independent macros (move to another file?)
+//-----------------------------------------------------------------------------
+
+// need macro for constant expression
+#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) )
+
+// Force a function call site -not- to inlined. (useful for profiling)
+#define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
+
+// Marks the codepath from here until the next branch entry point as unreachable,
+// and asserts if any attempt is made to execute it.
+#define UNREACHABLE() { Assert(0); HINT(0); }
+
+// In cases where no default is present or appropriate, this causes MSVC to generate
+// as little code as possible, and throw an assertion in debug.
+#define NO_DEFAULT default: UNREACHABLE();
+
+// Defines MAX_PATH
+#ifndef MAX_PATH
+ #define MAX_PATH 260
+#endif
+
+
+//-----------------------------------------------------------------------------
+// FP exception handling
+//-----------------------------------------------------------------------------
+//#define CHECK_FLOAT_EXCEPTIONS 1
+//#define CHECK_FPU_CONTROL_WORD_SET 1 // x360 only
+
+#if defined( COMPILER_MSVC64 )
+
+ inline void SetupFPUControlWord()
+ {
+ }
+
+#elif defined ( COMPILER_MSVC32 )
+
+ inline void SetupFPUControlWordForceExceptions()
+ {
+ // use local to get and store control word
+ uint16 tmpCtrlW;
+ __asm
+ {
+ fnclex /* clear all current exceptions */
+ fnstcw word ptr [tmpCtrlW] /* get current control word */
+ and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
+ or [tmpCtrlW], 0230h /* set to 53-bit, mask only inexact, underflow */
+ fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
+ }
+ }
+
+ #ifdef CHECK_FLOAT_EXCEPTIONS
+
+ inline void SetupFPUControlWord()
+ {
+ SetupFPUControlWordForceExceptions();
+ }
+
+ #else
+
+ inline void SetupFPUControlWord()
+ {
+ // use local to get and store control word
+ uint16 tmpCtrlW;
+ __asm
+ {
+ fnstcw word ptr [tmpCtrlW] /* get current control word */
+ and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
+ or [tmpCtrlW], 023Fh /* set to 53-bit, mask only inexact, underflow */
+ fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
+ }
+ }
+
+ #endif
+
+#elif defined ( COMPILER_GCC )
+
+// Works for PS3
+ inline void SetupFPUControlWord()
+ {
+#ifdef _PS3
+// TODO: PS3 compiler spits out the following errors:
+// C:/tmp/ccIN0aaa.s: Assembler messages:
+// C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
+// C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
+#else
+ __volatile unsigned short int __cw;
+ __asm __volatile ("fnstcw %0" : "=m" (__cw));
+ __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
+ __cw = __cw | 0x023F; // set 53-bit, no exceptions
+ __asm __volatile ("fldcw %0" : : "m" (__cw));
+#endif
+ }
+
+#elif defined ( COMPILER_SNC )
+
+// Works for PS3
+ inline void SetupFPUControlWord()
+ {
+#ifdef _PS3
+// TODO: PS3 compiler spits out the following errors:
+// C:/tmp/ccIN0aaa.s: Assembler messages:
+// C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
+// C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
+#else
+ __volatile unsigned short int __cw;
+ __asm __volatile ("fnstcw %0" : "=m" (__cw));
+ __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
+ __cw = __cw | 0x023F; // set 53-bit, no exceptions
+ __asm __volatile ("fldcw %0" : : "m" (__cw));
+#endif
+ }
+
+#elif defined( COMPILER_MSVCX360 )
+
+ #ifdef CHECK_FPU_CONTROL_WORD_SET
+ FORCEINLINE bool IsFPUControlWordSet()
+ {
+ float f = 0.996f;
+ union
+ {
+ double flResult;
+ int pResult[2];
+ };
+ flResult = __fctiw( f );
+ return ( pResult[1] == 1 );
+ }
+ #else
+ #define IsFPUControlWordSet() 1
+ #endif
+
+ inline void SetupFPUControlWord()
+ {
+ // Set round-to-nearest in FPSCR
+ // (cannot assemble, must use op-code form)
+ __emit( 0xFF80010C ); // mtfsfi 7,0
+
+ // Favour compatibility over speed (make sure the VPU set to Java-compliant mode)
+ // NOTE: the VPU *always* uses round-to-nearest
+ __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
+ a; // Avoid compiler warning
+ __asm
+ {
+ mtvscr a; // Clear the Vector Status & Control Register to zero
+ }
+ }
+
+#endif // COMPILER_MSVCX360
+
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Standard functions for handling endian-ness
+//-----------------------------------------------------------------------------
+
+//-------------------------------------
+// Basic swaps
+//-------------------------------------
+
+template <typename T>
+inline T WordSwapC( T w )
+{
+ uint16 temp;
+
+ temp = ((*((uint16 *)&w) & 0xff00) >> 8);
+ temp |= ((*((uint16 *)&w) & 0x00ff) << 8);
+
+ return *((T*)&temp);
+}
+
+template <typename T>
+inline T DWordSwapC( T dw )
+{
+ uint32 temp;
+
+ temp = *((uint32 *)&dw) >> 24;
+ temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
+ temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
+ temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
+
+ return *((T*)&temp);
+}
+
+//-------------------------------------
+// Fast swaps
+//-------------------------------------
+
+#if defined( COMPILER_MSVCX360 )
+
+ #define WordSwap WordSwap360Intr
+ #define DWordSwap DWordSwap360Intr
+
+ template <typename T>
+ inline T WordSwap360Intr( T w )
+ {
+ T output;
+ __storeshortbytereverse( w, 0, &output );
+ return output;
+ }
+
+ template <typename T>
+ inline T DWordSwap360Intr( T dw )
+ {
+ T output;
+ __storewordbytereverse( dw, 0, &output );
+ return output;
+ }
+
+#elif defined( COMPILER_MSVC32 )
+
+ #define WordSwap WordSwapAsm
+ #define DWordSwap DWordSwapAsm
+
+ #pragma warning(push)
+ #pragma warning (disable:4035) // no return value
+
+ template <typename T>
+ inline T WordSwapAsm( T w )
+ {
+ __asm
+ {
+ mov ax, w
+ xchg al, ah
+ }
+ }
+
+ template <typename T>
+ inline T DWordSwapAsm( T dw )
+ {
+ __asm
+ {
+ mov eax, dw
+ bswap eax
+ }
+ }
+
+ #pragma warning(pop)
+
+#else
+
+ #define WordSwap WordSwapC
+ #define DWordSwap DWordSwapC
+
+#endif
+
+//-------------------------------------
+// The typically used methods.
+//-------------------------------------
+
+#if defined( _SGI_SOURCE ) || defined( PLATFORM_X360 ) || defined( _PS3 )
+#define PLAT_BIG_ENDIAN 1
+#else
+#define PLAT_LITTLE_ENDIAN 1
+#endif
+
+
+// If a swapped float passes through the fpu, the bytes may get changed.
+// Prevent this by swapping floats as DWORDs.
+#define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) ))
+
+#if defined(PLAT_LITTLE_ENDIAN)
+#define BigShort( val ) WordSwap( val )
+#define BigWord( val ) WordSwap( val )
+#define BigLong( val ) DWordSwap( val )
+#define BigDWord( val ) DWordSwap( val )
+#define LittleShort( val ) ( val )
+#define LittleWord( val ) ( val )
+#define LittleLong( val ) ( val )
+#define LittleDWord( val ) ( val )
+#define SwapShort( val ) BigShort( val )
+#define SwapWord( val ) BigWord( val )
+#define SwapLong( val ) BigLong( val )
+#define SwapDWord( val ) BigDWord( val )
+
+// Pass floats by pointer for swapping to avoid truncation in the fpu
+#define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
+#define LittleFloat( pOut, pIn ) ( *pOut = *pIn )
+#define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn )
+
+#elif defined(PLAT_BIG_ENDIAN)
+
+#define BigShort( val ) ( val )
+#define BigWord( val ) ( val )
+#define BigLong( val ) ( val )
+#define BigDWord( val ) ( val )
+#define LittleShort( val ) WordSwap( val )
+#define LittleWord( val ) WordSwap( val )
+#define LittleLong( val ) DWordSwap( val )
+#define LittleDWord( val ) DWordSwap( val )
+#define SwapShort( val ) LittleShort( val )
+#define SwapWord( val ) LittleWord( val )
+#define SwapLong( val ) LittleLong( val )
+#define SwapDWord( val ) LittleDWord( val )
+
+// Pass floats by pointer for swapping to avoid truncation in the fpu
+#define BigFloat( pOut, pIn ) ( *pOut = *pIn )
+#define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
+#define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn )
+
+#else
+
+// @Note (toml 05-02-02): this technique expects the compiler to
+// optimize the expression and eliminate the other path. On any new
+// platform/compiler this should be tested.
+inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
+inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
+inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
+inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
+inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
+inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
+inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
+inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
+inline short SwapShort( short val ) { return WordSwap( val ); }
+inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); }
+inline long SwapLong( long val ) { return DWordSwap( val ); }
+inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); }
+
+// Pass floats by pointer for swapping to avoid truncation in the fpu
+inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); }
+inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); }
+inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); }
+
+#endif
+
+#if PLAT_BIG_ENDIAN
+ #if defined( _PS3 )
+ inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
+ {
+ return __lwbrx( base + dwordIndex );
+ }
+
+ inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
+ {
+ __stwbrx( base + dwordIndex, dword );
+ }
+ inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
+ {
+ return __ldbrx( base + nWordIndex );
+ }
+
+ inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
+ {
+ __stdbrx( base + nWordIndex, nWord );
+ }
+ #else
+ inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
+ {
+ return __loadwordbytereverse( dwordIndex<<2, base );
+ }
+
+ inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
+ {
+ __storewordbytereverse( dword, dwordIndex<<2, base );
+ }
+ inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
+ {
+ return __loaddoublewordbytereverse( nWordIndex<<2, base );
+ }
+
+ inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
+ {
+ __storedoublewordbytereverse( nWord, nWordIndex<<2, base );
+ }
+ #endif
+#else
+ inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
+ {
+ return LittleDWord( base[dwordIndex] );
+ }
+
+ inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
+ {
+ base[dwordIndex] = LittleDWord(dword);
+ }
+#endif
+
+
+// When in benchmark mode, the timer returns a simple incremented value each time you call it.
+//
+// It should not be changed after startup unless you really know what you're doing. The only place
+// that should do this is the benchmark code itself so it can output a legit duration.
+PLATFORM_INTERFACE void Plat_SetBenchmarkMode( bool bBenchmarkMode );
+PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode();
+
+
+PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded.
+PLATFORM_INTERFACE uint32 Plat_MSTime(); // Time in milliseconds.
+PLATFORM_INTERFACE uint64 Plat_GetClockStart(); // Snapshot of the clock when app started.
+PLATFORM_INTERFACE uint64 Timer_GetTimeUS();
+
+// Get the local calendar time.
+// Same as time() followed by localtime(), but non-crash-prone and threadsafe.
+PLATFORM_INTERFACE void Plat_GetLocalTime( struct tm *pNow );
+
+// Convert a time_t (specified in nTime - seconds since Jan 1, 1970 UTC) to a local calendar time in a threadsafe and non-crash-prone way.
+PLATFORM_INTERFACE void Plat_ConvertToLocalTime( uint64 nTime, struct tm *pNow );
+
+// Get a time string (same as ascstring, but threadsafe).
+PLATFORM_INTERFACE void Plat_GetTimeString( struct tm *pTime, char *pOut, int nMaxBytes );
+
+// converts a time_t to a struct tm without the local time conversion of ConvertToLocalTime
+PLATFORM_INTERFACE void Plat_gmtime( uint64 nTime, struct tm *pTime );
+PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr );
+
+// Get the process' executable filename.
+PLATFORM_INTERFACE void Plat_GetModuleFilename( char *pOut, int nMaxBytes );
+
+PLATFORM_INTERFACE void Plat_ExitProcess( int nCode );
+
+// b/w compatibility
+#define Sys_FloatTime Plat_FloatTime
+
+// Protect against bad auto operator=
+#define DISALLOW_OPERATOR_EQUAL( _classname ) \
+ private: \
+ _classname &operator=( const _classname & ); \
+ public:
+
+// Define a reasonable operator=
+#define IMPLEMENT_OPERATOR_EQUAL( _classname ) \
+ public: \
+ _classname &operator=( const _classname &src ) \
+ { \
+ memcpy( this, &src, sizeof(_classname) ); \
+ return *this; \
+ }
+
+// Processor Information:
+struct CPUInformation
+{
+ int m_Size; // Size of this structure, for forward compatability.
+
+ bool m_bRDTSC : 1, // Is RDTSC supported?
+ m_bCMOV : 1, // Is CMOV supported?
+ m_bFCMOV : 1, // Is FCMOV supported?
+ m_bSSE : 1, // Is SSE supported?
+ m_bSSE2 : 1, // Is SSE2 Supported?
+ m_b3DNow : 1, // Is 3DNow! Supported?
+ m_bMMX : 1, // Is MMX supported?
+ m_bHT : 1; // Is HyperThreading supported?
+
+ uint8 m_nLogicalProcessors; // Number op logical processors.
+ uint8 m_nPhysicalProcessors; // Number of physical processors
+
+ bool m_bSSE3 : 1,
+ m_bSSSE3 : 1,
+ m_bSSE4a : 1,
+ m_bSSE41 : 1,
+ m_bSSE42 : 1;
+
+ int64 m_Speed; // In cycles per second.
+
+ tchar* m_szProcessorID; // Processor vendor Identification.
+
+ CPUInformation(): m_Size(0){}
+};
+
+PLATFORM_INTERFACE const CPUInformation& GetCPUInformation();
+
+PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear );
+PLATFORM_INTERFACE void GetCurrentDayOfTheWeek( int *pDay ); // 0 = Sunday
+PLATFORM_INTERFACE void GetCurrentDayOfTheYear( int *pDay ); // 0 = Jan 1
+
+// ---------------------------------------------------------------------------------- //
+// Performance Monitoring Events - L2 stats etc...
+// ---------------------------------------------------------------------------------- //
+PLATFORM_INTERFACE void InitPME();
+PLATFORM_INTERFACE void ShutdownPME();
+
+
+//-----------------------------------------------------------------------------
+// Security related functions
+//-----------------------------------------------------------------------------
+// Ensure that the hardware key's drivers have been installed.
+PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver();
+
+// Ok, so this isn't a very secure way to verify the hardware key for now. It
+// is primarially depending on the fact that all the binaries have been wrapped
+// with the secure wrapper provided by the hardware keys vendor.
+PLATFORM_INTERFACE bool Plat_VerifyHardwareKey();
+
+// The same as above, but notifies user with a message box when the key isn't in
+// and gives him an opportunity to correct the situation.
+PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt();
+
+// Can be called in real time, doesn't perform the verify every frame. Mainly just
+// here to allow the game to drop out quickly when the key is removed, rather than
+// allowing the wrapper to pop up it's own blocking dialog, which the engine doesn't
+// like much.
+PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey();
+
+//-----------------------------------------------------------------------------
+// Just logs file and line to simple.log
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE void* Plat_SimpleLog( const tchar* file, int line );
+
+
+#if defined( _X360 )
+#define Plat_FastMemset XMemSet
+#define Plat_FastMemcpy XMemCpy
+#else
+#define Plat_FastMemset memset
+#define Plat_FastMemcpy memcpy
+#endif
+
+//-----------------------------------------------------------------------------
+// XBOX Components valid in PC compilation space
+//-----------------------------------------------------------------------------
+
+#define XBOX_DVD_SECTORSIZE 2048
+#define XBOX_DVD_ECC_SIZE 32768 // driver reads in quantum ECC blocks
+#define XBOX_HDD_SECTORSIZE 512
+
+// Custom windows messages for Xbox input
+#define WM_XREMOTECOMMAND (WM_USER + 100)
+#define WM_XCONTROLLER_KEY (WM_USER + 101)
+#define WM_SYS_UI (WM_USER + 102)
+#define WM_SYS_SIGNINCHANGED (WM_USER + 103)
+#define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104)
+#define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105)
+#define WM_SYS_MUTELISTCHANGED (WM_USER + 106)
+#define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107)
+#define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108)
+#define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109)
+#define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110)
+#define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111)
+#define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112)
+#define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113)
+#define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114)
+#define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115)
+#define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116)
+#define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117)
+#define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118)
+#define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119)
+#define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120)
+#define WM_XMP_STATECHANGED (WM_USER + 121)
+#define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122)
+#define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123)
+#define WM_SYS_SHUTDOWNREQUEST (WM_USER + 124)
+
+#if defined( _PS3 )
+#define PLATFORM_EXT ".ps3"
+#elif defined( PLATFORM_X360 )
+#define PLATFORM_EXT ".360"
+#else
+#define PLATFORM_EXT ""
+#endif
+
+inline const char *GetPlatformExt( void )
+{
+ return PLATFORM_EXT;
+}
+
+// flat view, 6 hw threads
+#define XBOX_PROCESSOR_0 ( 1<<0 )
+#define XBOX_PROCESSOR_1 ( 1<<1 )
+#define XBOX_PROCESSOR_2 ( 1<<2 )
+#define XBOX_PROCESSOR_3 ( 1<<3 )
+#define XBOX_PROCESSOR_4 ( 1<<4 )
+#define XBOX_PROCESSOR_5 ( 1<<5 )
+
+// core view, 3 cores with 2 hw threads each
+#define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0
+#define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1
+#define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2
+#define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3
+#define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4
+#define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5
+
+//-----------------------------------------------------------------------------
+// Include additional dependant header components.
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_X360 )
+#include "xbox/xbox_core.h"
+#elif defined( PLATFORM_PS3 )
+#include "ps3/ps3_core.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Methods to invoke the constructor, copy constructor, and destructor
+//-----------------------------------------------------------------------------
+
+template <class T>
+inline T* Construct( T* pMemory )
+{
+ return ::new( pMemory ) T;
+}
+
+template <class T, typename ARG1>
+inline T* Construct( T* pMemory, ARG1 a1 )
+{
+ return ::new( pMemory ) T( a1 );
+}
+
+template <class T, typename ARG1, typename ARG2>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2 )
+{
+ return ::new( pMemory ) T( a1, a2 );
+}
+
+template <class T, typename ARG1, typename ARG2, typename ARG3>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3 )
+{
+ return ::new( pMemory ) T( a1, a2, a3 );
+}
+
+template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4 )
+{
+ return ::new( pMemory ) T( a1, a2, a3, a4 );
+}
+
+template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4, typename ARG5>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4, ARG5 a5 )
+{
+ return ::new( pMemory ) T( a1, a2, a3, a4, a5 );
+}
+
+template <class T>
+inline T* CopyConstruct( T* pMemory, T const& src )
+{
+ return ::new( pMemory ) T(src);
+}
+
+template <class T>
+inline void Destruct( T* pMemory )
+{
+ pMemory->~T();
+
+#ifdef _DEBUG
+ memset( pMemory, 0xDD, sizeof(T) );
+#endif
+}
+
+
+//
+// GET_OUTER()
+//
+// A platform-independent way for a contained class to get a pointer to its
+// owner. If you know a class is exclusively used in the context of some
+// "outer" class, this is a much more space efficient way to get at the outer
+// class than having the inner class store a pointer to it.
+//
+// class COuter
+// {
+// class CInner // Note: this does not need to be a nested class to work
+// {
+// void PrintAddressOfOuter()
+// {
+// printf( "Outer is at 0x%x\n", GET_OUTER( COuter, m_Inner ) );
+// }
+// };
+//
+// CInner m_Inner;
+// friend class CInner;
+// };
+
+#define GET_OUTER( OuterType, OuterMember ) \
+ ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) )
+
+
+/* TEMPLATE_FUNCTION_TABLE()
+
+ (Note added to platform.h so platforms that correctly support templated
+ functions can handle portions as templated functions rather than wrapped
+ functions)
+
+ Helps automate the process of creating an array of function
+ templates that are all specialized by a single integer.
+ This sort of thing is often useful in optimization work.
+
+ For example, using TEMPLATE_FUNCTION_TABLE, this:
+
+ TEMPLATE_FUNCTION_TABLE(int, Function, ( int blah, int blah ), 10)
+ {
+ return argument * argument;
+ }
+
+ is equivilent to the following:
+
+ (NOTE: the function has to be wrapped in a class due to code
+ generation bugs involved with directly specializing a function
+ based on a constant.)
+
+ template<int argument>
+ class FunctionWrapper
+ {
+ public:
+ int Function( int blah, int blah )
+ {
+ return argument*argument;
+ }
+ }
+
+ typedef int (*FunctionType)( int blah, int blah );
+
+ class FunctionName
+ {
+ public:
+ enum { count = 10 };
+ FunctionType functions[10];
+ };
+
+ FunctionType FunctionName::functions[] =
+ {
+ FunctionWrapper<0>::Function,
+ FunctionWrapper<1>::Function,
+ FunctionWrapper<2>::Function,
+ FunctionWrapper<3>::Function,
+ FunctionWrapper<4>::Function,
+ FunctionWrapper<5>::Function,
+ FunctionWrapper<6>::Function,
+ FunctionWrapper<7>::Function,
+ FunctionWrapper<8>::Function,
+ FunctionWrapper<9>::Function
+ };
+*/
+
+PLATFORM_INTERFACE bool vtune( bool resume );
+
+
+#define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \
+ \
+typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \
+ \
+template<const int nArgument> \
+struct __Function_##NAME \
+{ \
+ static RETURN_TYPE FASTCALL Run ARGS; \
+}; \
+ \
+template <const int i> \
+struct __MetaLooper_##NAME : __MetaLooper_##NAME<i-1> \
+{ \
+ __Type_##NAME func; \
+ inline __MetaLooper_##NAME() { func = __Function_##NAME<i>::Run; } \
+}; \
+ \
+template<> \
+struct __MetaLooper_##NAME<0> \
+{ \
+ __Type_##NAME func; \
+ inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \
+}; \
+ \
+class NAME \
+{ \
+private: \
+ static const __MetaLooper_##NAME<COUNT> m; \
+public: \
+ enum { count = COUNT }; \
+ static const __Type_##NAME* functions; \
+}; \
+const __MetaLooper_##NAME<COUNT> NAME::m; \
+const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \
+template<const int nArgument> \
+RETURN_TYPE FASTCALL __Function_##NAME<nArgument>::Run ARGS
+
+
+#define LOOP_INTERCHANGE(BOOLEAN, CODE)\
+ if( (BOOLEAN) )\
+ {\
+ CODE;\
+ } else\
+ {\
+ CODE;\
+ }
+
+
+//-----------------------------------------------------------------------------
+// Dynamic libs support
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_WINDOWS )
+
+PLATFORM_INTERFACE void *Plat_GetProcAddress( const char *pszModule, const char *pszName );
+
+template <typename FUNCPTR_TYPE>
+class CDynamicFunction
+{
+public:
+ CDynamicFunction( const char *pszModule, const char *pszName, FUNCPTR_TYPE pfnFallback = NULL )
+ {
+ m_pfn = pfnFallback;
+ void *pAddr = Plat_GetProcAddress( pszModule, pszName );
+ if ( pAddr )
+ {
+ m_pfn = (FUNCPTR_TYPE)pAddr;
+ }
+ }
+
+ operator bool() { return m_pfn != NULL; }
+ bool operator !() { return !m_pfn; }
+ operator FUNCPTR_TYPE() { return m_pfn; }
+
+private:
+ FUNCPTR_TYPE m_pfn;
+};
+#endif
+
+
+//-----------------------------------------------------------------------------
+// What OS version are we?
+//-----------------------------------------------------------------------------
+enum PlatOSVersion_t
+{
+ PLAT_OS_VERSION_UNKNOWN = -1,
+
+ // X360-specific versions
+ PLAT_OS_VERSION_XBOX360 = 0,
+
+ // PC-specific OS versions
+ PLAT_OS_VERSION_XP = 5,
+ PLAT_OS_VERSION_VISTA = 6,
+};
+
+PLATFORM_INTERFACE PlatOSVersion_t Plat_GetOSVersion();
+
+
+// Watchdog timer support. Call BeginWatchdogTimer( nn ) to kick the timer off. if you don't call
+// EndWatchdogTimer within nn seconds, the program will kick off an exception. This is for making
+// sure that hung dedicated servers abort (and restart) instead of staying hung. Calling
+// EndWatchdogTimer more than once or when there is no active watchdog is fine. Only does anything
+// under linux right now. It should be possible to implement this functionality in windows via a
+// thread, if desired.
+
+#if defined( POSIX ) && !defined( _PS3 )
+
+PLATFORM_INTERFACE void BeginWatchdogTimer( int nSecs );
+PLATFORM_INTERFACE void EndWatchdogTimer( void );
+PLATFORM_INTERFACE void ResetBaseTime( void ); // reset plat_floattime to 0 for a subprocess
+#else
+FORCEINLINE void BeginWatchdogTimer( int nSecs )
+{
+}
+
+FORCEINLINE void EndWatchdogTimer( void )
+{
+}
+FORCEINLINE void ResetBaseTime( void ) // reset plat_floattime to 0 for a subprocess
+{
+}
+
+#endif
+
+
+#ifdef COMPILER_MSVC
+/*
+FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
+{
+ return _rotl8( nValue, nRotateBits );
+}
+FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
+{
+ return _rotl( nValue, nRotateBits );
+}
+FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
+{
+return _rotr8( nValue, nRotateBits );
+}
+FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
+{
+return _rotr16( nValue, nRotateBits );
+}
+*/
+FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
+{
+ return _rotl( nValue, nRotateBits );
+}
+FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
+{
+ return _rotl64( nValue, nRotateBits );
+}
+FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
+{
+ return _rotr( nValue, nRotateBits );
+}
+FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
+{
+ return _rotr64( nValue, nRotateBits );
+}
+#else
+// GCC should compile this all into single instruction
+/*
+FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 7 ) );
+}
+FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 15 ) );
+}
+FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 7 ) );
+}
+FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 15 ) );
+}
+*/
+FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 31 ) );
+}
+FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( - nRotateBits ) & 63 ) );
+}
+FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 31 ) );
+}
+FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( - nRotateBits ) & 63 ) );
+}
+#endif
+PLATFORM_INTERFACE const char * GetPlatformSpecificFileName(const char * FileName);
+
+#include "tier0/valve_on.h"
+
+#if defined(TIER0_DLL_EXPORT)
+extern "C" int V_tier0_stricmp(const char *s1, const char *s2 );
+#undef stricmp
+#undef strcmpi
+#define stricmp(s1,s2) V_tier0_stricmp( s1, s2 )
+#define strcmpi(s1,s2) V_tier0_stricmp( s1, s2 )
+#else
+int _V_stricmp (const char *s1, const char *s2 );
+int V_strncasecmp (const char *s1, const char *s2, int n);
+
+// A special high-performance case-insensitive compare function that in
+// a single call distinguishes between exactly matching strings,
+// strings equal in case-insensitive way, and not equal strings:
+// returns 0 if strings match exactly
+// returns >0 if strings match in a case-insensitive way, but do not match exactly
+// returns <0 if strings do not match even in a case-insensitive way
+int _V_stricmp_NegativeForUnequal ( const char *s1, const char *s2 );
+
+#undef stricmp
+#undef strcmpi
+#define stricmp(s1,s2) _V_stricmp(s1, s2)
+#define strcmpi(s1,s2) _V_stricmp(s1, s2)
+#undef strnicmp
+#define strnicmp V_strncasecmp
+#endif
+
+#endif /* PLATFORM_H */
diff --git a/external/vpc/public/tier0/pmelib.h b/external/vpc/public/tier0/pmelib.h
new file mode 100644
index 0000000..dcdec5f
--- /dev/null
+++ b/external/vpc/public/tier0/pmelib.h
@@ -0,0 +1,212 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+#ifndef PMELIB_H
+#define PMELIB_H
+
+//#include "windows.h"
+
+#include "tier0/platform.h"
+
+// Get rid of a bunch of STL warnings!
+#pragma warning( push, 3 )
+#pragma warning( disable : 4018 )
+
+#define VERSION "1.0.2"
+
+// uncomment this list to add some runtime checks
+//#define PME_DEBUG
+
+#include "tier0/valve_off.h"
+#include <string>
+#include "tier0/valve_on.h"
+
+using namespace std;
+
+// RDTSC Instruction macro
+#ifdef COMPILER_MSVC64
+#define RDTSC(var) (var = __rdtsc())
+#else
+#define RDTSC(var) \
+_asm RDTSC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+// RDPMC Instruction macro
+#ifdef COMPILER_MSVC64
+#define RDPMC(counter, var) (var = __readpmc(counter))
+#else
+#define RDPMC(counter, var) \
+_asm mov ecx, counter \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+// RDPMC Instruction macro, for performance counter 1 (ecx = 1)
+#ifdef COMPILER_MSVC64
+#define RDPMC0(var) (var = __readpmc(0))
+#else
+#define RDPMC0(var) \
+_asm mov ecx, 0 \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+#ifdef COMPILER_MSVC64
+#define RDPMC1(var) (var = __readpmc(1))
+#else
+#define RDPMC1(var) \
+_asm mov ecx, 1 \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+#define EVENT_TYPE(mode) EventType##mode
+#define EVENT_MASK(mode) EventMask##mode
+
+#include "ia32detect.h"
+
+enum ProcessPriority
+{
+ ProcessPriorityNormal,
+ ProcessPriorityHigh,
+};
+
+enum PrivilegeCapture
+{
+ OS_Only, // ring 0, kernel level
+ USR_Only, // app level
+ OS_and_USR, // all levels
+};
+
+enum CompareMethod
+{
+ CompareGreater, //
+ CompareLessEqual, //
+};
+
+enum EdgeState
+{
+ RisingEdgeDisabled, //
+ RisingEdgeEnabled, //
+};
+
+enum CompareState
+{
+ CompareDisable, //
+ CompareEnable, //
+};
+
+// Singletion Class
+class PME : public ia32detect
+{
+public:
+//private:
+
+ static PME* _singleton;
+
+ HANDLE hFile;
+ bool bDriverOpen;
+ double m_CPUClockSpeed;
+
+ //ia32detect detect;
+ HRESULT Init();
+ HRESULT Close();
+
+protected:
+
+ PME()
+ {
+ hFile = NULL;
+ bDriverOpen = FALSE;
+ m_CPUClockSpeed = 0;
+ Init();
+ }
+
+public:
+
+ static PME* Instance(); // gives back a real object
+
+ ~PME()
+ {
+ Close();
+ }
+
+ double GetCPUClockSpeedSlow( void );
+ double GetCPUClockSpeedFast( void );
+
+ HRESULT SelectP5P6PerformanceEvent( uint32 dw_event, uint32 dw_counter, bool b_user, bool b_kernel );
+
+ HRESULT ReadMSR( uint32 dw_reg, int64 * pi64_value );
+ HRESULT ReadMSR( uint32 dw_reg, uint64 * pi64_value );
+
+ HRESULT WriteMSR( uint32 dw_reg, const int64 & i64_value );
+ HRESULT WriteMSR( uint32 dw_reg, const uint64 & i64_value );
+
+ void SetProcessPriority( ProcessPriority priority )
+ {
+ switch( priority )
+ {
+ case ProcessPriorityNormal:
+ {
+ SetPriorityClass (GetCurrentProcess(),NORMAL_PRIORITY_CLASS);
+ SetThreadPriority (GetCurrentThread(),THREAD_PRIORITY_NORMAL);
+ break;
+ }
+ case ProcessPriorityHigh:
+ {
+ SetPriorityClass (GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
+ SetThreadPriority (GetCurrentThread(),THREAD_PRIORITY_HIGHEST);
+ break;
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ // Return the family of the processor
+ //---------------------------------------------------------------------------
+ CPUVendor GetVendor(void)
+ {
+ return vendor;
+ }
+
+ int GetProcessorFamily(void)
+ {
+ return version.Family;
+ }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+};
+
+#include "p5p6performancecounters.h"
+#include "p4performancecounters.h"
+#include "k8performancecounters.h"
+
+enum PerfErrors
+{
+ E_UNKNOWN_CPU_VENDOR = -1,
+ E_BAD_COUNTER = -2,
+ E_UNKNOWN_CPU = -3,
+ E_CANT_OPEN_DRIVER = -4,
+ E_DRIVER_ALREADY_OPEN = -5,
+ E_DRIVER_NOT_OPEN = -6,
+ E_DISABLED = -7,
+ E_BAD_DATA = -8,
+ E_CANT_CLOSE = -9,
+ E_ILLEGAL_OPERATION = -10,
+};
+
+#pragma warning( pop )
+
+#endif // PMELIB_H \ No newline at end of file
diff --git a/external/vpc/public/tier0/stackstats.h b/external/vpc/public/tier0/stackstats.h
new file mode 100644
index 0000000..a14d64b
--- /dev/null
+++ b/external/vpc/public/tier0/stackstats.h
@@ -0,0 +1,966 @@
+//========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Tools for grabbing/dumping the stack at runtime
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_STACKSTATS_H
+#define TIER0_STACKSTATS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/stacktools.h"
+#include "tier0/threadtools.h"
+
+#if defined ENABLE_RUNTIME_STACK_TRANSLATION
+#define ENABLE_STACK_STATS_GATHERING //uncomment to enable the gathering class
+#endif
+
+#if defined ENABLE_STACK_STATS_GATHERING
+#include "tier0/valve_off.h"
+# include <map> //needed for CCallStackStatsGatherer
+# include <vector>
+#include "tier0/valve_on.h"
+#define CDefaultStatsGathererAllocator std::allocator
+#else
+template<class _Ty> class CNullStatsGathererAllocator { CNullStatsGathererAllocator( void ) { } };
+#define CDefaultStatsGathererAllocator CNullStatsGathererAllocator
+#endif
+
+
+typedef size_t (*FN_DescribeStruct)( uint8 *, size_t );
+
+class CCallStackStatsGatherer_Standardized_t;
+struct CCallStackStatsGatherer_FunctionTable_t
+{
+ void (*pfn_GetDumpInfo)( void *, const char *&, size_t &, size_t &, void *&, size_t &, CCallStackStatsGatherer_Standardized_t *&, size_t & );
+ void (*pfn_PushSubTree)( void *, const CCallStackStatsGatherer_Standardized_t &, const CCallStackStorage & );
+ void (*pfn_PopSubTree)( void * );
+ size_t (*pfn_DescribeCallStackStatStruct)( uint8 *, size_t );
+ void (*pfn_SyncMutexes)( void *, bool );
+ void *(*pfn_GetEntry)( void *, uint32 );
+ void (*pfn_ApplyTreeAccessLock)( void *, bool );
+ void (*pfn_LockEntry)( void *, uint32, bool );
+};
+
+//templatized classes are fun, can't really use a base pointer effectively, so we'll have a translator struct and store pointers to instances of the translator function
+class CCallStackStatsGatherer_Standardized_t
+{
+public:
+ CCallStackStatsGatherer_Standardized_t( void ) {};
+ CCallStackStatsGatherer_Standardized_t( void *pThis, const CCallStackStatsGatherer_FunctionTable_t &FnTable ) : pGatherer( pThis ), pFunctionTable( &FnTable ) {};
+
+ //go ahead and create some helper functions that are likely to be used by helper code
+ void PushSubTree( const CCallStackStatsGatherer_Standardized_t &SubTree, const CCallStackStorage &PushStack = CCallStackStorage() ) const
+ {
+ pFunctionTable->pfn_PushSubTree( pGatherer, SubTree, PushStack );
+ }
+
+ inline void PopSubTree( void ) const
+ {
+ pFunctionTable->pfn_PopSubTree( pGatherer );
+ }
+
+ void *pGatherer;
+ const CCallStackStatsGatherer_FunctionTable_t *pFunctionTable;
+};
+
+//Designed to be called by an instance of CCallStackStatsGatherer to dump it's data
+PLATFORM_INTERFACE bool _CCallStackStatsGatherer_Internal_DumpStatsToFile( const char *szFileName, const CCallStackStatsGatherer_Standardized_t &StatsGatherer, bool bAllowMemoryAllocations );
+
+
+
+
+
+
+template <class STATSTRUCT>
+class CCallStackStatsGatherer_StructAccessor_Base
+{
+public:
+ CCallStackStatsGatherer_StructAccessor_Base( const CCallStackStatsGatherer_Standardized_t &Gatherer, int iEntryIndex ) : m_Gatherer( Gatherer ), m_iEntryIndex( iEntryIndex ) {};
+protected:
+ uint32 m_iEntryIndex; //index of the stat entry we want in the vector. Stored as index as the vector base address can change.
+ CCallStackStatsGatherer_Standardized_t m_Gatherer; //so we can lock the vector memory in place while manipulating the values
+};
+
+
+class CCallStackStatsGatherer_StatMutexBase
+{
+public:
+ void LockEntry( uint32 iEntryIndex, bool bLock ) {} //true to increase lock refcount, false to decrease
+};
+
+template <uint32 SHAREDENTRYMUTEXES> //must be a power of 2
+class CCallStackStatsGatherer_StatMutexPool
+{
+public:
+ void LockEntry( uint32 iEntryIndex, bool bLock )
+ {
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ COMPILE_TIME_ASSERT( (SHAREDENTRYMUTEXES & (SHAREDENTRYMUTEXES - 1)) == 0 ); //must be a power of 2
+
+ if( bLock )
+ {
+ m_IndividualEntryMutexes[iEntryIndex & (SHAREDENTRYMUTEXES - 1)].Lock();
+ }
+ else
+ {
+ m_IndividualEntryMutexes[iEntryIndex & (SHAREDENTRYMUTEXES - 1)].Unlock();
+ }
+#endif
+ }
+protected:
+ CThreadFastMutex m_IndividualEntryMutexes[SHAREDENTRYMUTEXES];
+};
+
+
+
+
+//STATSTRUCT - The structure you'll use to track whatever it is you're tracking.
+//CAPTUREDCALLSTACKLENGTH - The maximum length of your stack trace that we'll use to distinguish entries
+//STACKACQUISITIONFUNCTION - The function to use to gather the current call stack. GetCallStack() is safe, GetCallStack_Fast() is faster, but has special requirements
+//STATMUTEXHANDLER - If you want automatic mutex management for your individual entries, supply a handler here.
+// You'll need to not only call GetEntry(), but lock/unlock the entry while accessing it.
+//TEMPLATIZEDMEMORYALLOCATOR - We'll need to allocate memory, supply an allocator if you want to manage that
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION = GetCallStack, typename STATMUTEXHANDLER = CCallStackStatsGatherer_StatMutexPool<4>, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR = CDefaultStatsGathererAllocator>
+class CCallStackStatsGatherer : public STATMUTEXHANDLER
+{
+public:
+#if !defined( ENABLE_STACK_STATS_GATHERING )
+ CCallStackStatsGatherer( void )
+ {
+ for( size_t i = 0; i != CAPTUREDCALLSTACKLENGTH; ++i )
+ m_SingleCallStack[i] = NULL;
+ }
+#endif
+
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH] ); //get the entry using some callstack grabbed a while ago. Assumes ALL invalid entries have been nullified
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ); //same as above, but does the work of nullifying invalid entries
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( const CCallStackStorage &PushStack = CCallStackStorage( STACKACQUISITIONFUNCTION ) );
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( uint32 iEntryIndex );
+
+ //get the entry index for the caller's current call stack. Pre-nullified entries count as valid entries (and save re-nullification work)
+ uint32 GetEntryIndex( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ); //index is unchanging, safe to keep and use later (designed for exactly that purpose)
+ uint32 GetEntryIndex( const CCallStackStorage &PushStack = CCallStackStorage( STACKACQUISITIONFUNCTION ) );
+
+
+
+ typedef void *(&StackReference)[CAPTUREDCALLSTACKLENGTH];
+ StackReference GetCallStackForIndex( uint32 iEntryIndex )
+ {
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return m_StatEntries[iEntryIndex].m_CallStack;
+#else
+ return m_SingleCallStack;
+#endif
+ }
+
+ void GetCallStackForIndex( uint32 iEntryIndex, void *CallStackOut[CAPTUREDCALLSTACKLENGTH] );
+
+ size_t NumEntries( void ) const;
+
+ bool DumpToFile( const char *szFileName, bool bAllowMemoryAllocations = true );
+
+ static const CCallStackStatsGatherer_FunctionTable_t &GetFunctionTable( void );
+
+ static void GetDumpInfo( void *pThis, const char *&szStructName, size_t &iCapturedStackLength, size_t &iEntrySizeWithStack, void *&pEntries, size_t &iEntryCount, CCallStackStatsGatherer_Standardized_t *&pSubTrees, size_t &iSubTreeCount );
+ static void PushSubTree( void *pParent, const CCallStackStatsGatherer_Standardized_t &SubTree, const CCallStackStorage &PushStack );
+
+ void PushSubTree( CCallStackStatsGatherer_Standardized_t &Parent, const CCallStackStorage &PushStack = CCallStackStorage( STACKACQUISITIONFUNCTION ) );
+
+ static void PopSubTree( void *pParent );
+ static void SyncMutexes( void *pParent, bool bLock ); //true for lock, false for unlock
+ static void *GetEntry( void *pParent, uint32 iEntryIndex );
+ static void ApplyTreeAccessLock( void *pParent, bool bLock );
+ static void LockEntry( void *pParent, uint32 iEntryIndex, bool bLock );
+
+ void Reset( void );
+
+
+ CCallStackStatsGatherer_Standardized_t Standardized( void );
+ operator CCallStackStatsGatherer_Standardized_t( void );
+
+ const static FN_GetCallStack StackFunction; //publish the requested acquisition function so you can easily key all your stack gathering to the class instance
+ const static size_t CapturedCallStackLength;
+private:
+
+#pragma pack(push)
+#pragma pack(1)
+ struct StackAndStats_t
+ {
+ void *m_CallStack[CAPTUREDCALLSTACKLENGTH];
+ STATSTRUCT m_Stats;
+ };
+#pragma pack(pop)
+
+ typedef CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR> ThisCast;
+
+
+#if defined( ENABLE_STACK_STATS_GATHERING )
+
+ struct IndexMapKey_t
+ {
+ IndexMapKey_t( void * const CallStack[CAPTUREDCALLSTACKLENGTH] )
+ {
+ m_Hash = 0;
+ for( int i = 0; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ m_CallStack[i] = CallStack[i];
+ m_Hash += (uintp)CallStack[i];
+ }
+ }
+ bool operator<( const IndexMapKey_t &key ) const
+ {
+ if( m_Hash != key.m_Hash )
+ return m_Hash < key.m_Hash;
+
+ //only here if there's a hash match. Do a full check. Extremely likely to be the exact same call stack. But not 100% guaranteed.
+ for( int i = 0; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ if( m_CallStack[i] == key.m_CallStack[i] )
+ {
+ continue;
+ }
+
+ return m_CallStack[i] < key.m_CallStack[i];
+ }
+
+ return false; //exact same call stack
+ }
+
+ uintp m_Hash;
+ void *m_CallStack[CAPTUREDCALLSTACKLENGTH];
+ };
+
+ void KeepSubTree( CCallStackStatsGatherer_Standardized_t &SubTree )
+ {
+ AUTO_LOCK_FM( m_SubTreeMutex );
+ for( StoredSubTreeVector_t::iterator treeIter = m_StoredSubTrees.begin(); treeIter != m_StoredSubTrees.end(); ++treeIter )
+ {
+ if( SubTree.pGatherer == treeIter->pGatherer )
+ return;
+ }
+
+ //Warning( "Storing subtree\n" );
+
+ m_StoredSubTrees.push_back( SubTree );
+ }
+
+ uint32 PatchInSubTrees( void * const CallStackIn[CAPTUREDCALLSTACKLENGTH], void *CallStackOut[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries )
+ {
+ if( iValidEntries > CAPTUREDCALLSTACKLENGTH )
+ {
+ iValidEntries = CAPTUREDCALLSTACKLENGTH;
+ }
+
+ AUTO_LOCK_FM( m_SubTreeMutex );
+ if( m_PushedSubTrees.size() == 0 )
+ {
+ memcpy( CallStackOut, CallStackIn, sizeof( void * ) * iValidEntries );
+ return iValidEntries;
+ }
+
+ unsigned long iThreadID = ThreadGetCurrentId();
+ PushedSubTreeVector_t::reverse_iterator treeIter;
+ for( treeIter = m_PushedSubTrees.rbegin(); treeIter != m_PushedSubTrees.rend(); ++treeIter )
+ {
+ if( treeIter->iThreadID == iThreadID )
+ {
+ break;
+ }
+ }
+
+ if( treeIter == m_PushedSubTrees.rend() )
+ {
+ memcpy( CallStackOut, CallStackIn, sizeof( void * ) * iValidEntries );
+ return iValidEntries;
+ }
+
+ //char szTemp[4096];
+ //TranslateStackInfo( CallStackIn, CAPTUREDCALLSTACKLENGTH, szTemp, sizeof( szTemp ), "\n\t" );
+
+ //Warning( "Attempting to link trees:\n=======================ONE=======================\n\t%s\n", szTemp );
+ //TranslateStackInfo( treeIter->Stack, CAPTUREDCALLSTACKLENGTH, szTemp, sizeof( szTemp ), "\n\t" );
+ //Warning( "=======================TWO=======================\n\t%s\n", szTemp );
+
+ void *pMatchAddress = treeIter->Stack[1]; //while the first entry is where the actual push was made. The second entry is the first that is matchable in most cases
+
+ uint32 i;
+ for( i = 0; i < iValidEntries; ++i )
+ {
+ if( CallStackIn[i] == pMatchAddress )
+ {
+ //TranslateStackInfo( CallStackIn, i, szTemp, sizeof( szTemp ), "\n\t" );
+ //Warning( "======================MATCH======================\n\t%s\n", szTemp );
+
+ CallStackOut[i] = treeIter->tree.pGatherer; //tag this entry as leading into the sub-tree
+ KeepSubTree( treeIter->tree ); //store the sub-tree forever
+ return i + 1;
+ }
+ CallStackOut[i] = CallStackIn[i];
+ }
+
+ return iValidEntries;
+
+ //Warning( "=======================END=======================\n" );
+ }
+
+ struct StatIndex_t
+ {
+ StatIndex_t( void ) : m_Index((unsigned int)-1) {};
+ unsigned int m_Index;
+ };
+
+ typedef std::vector<StackAndStats_t, TEMPLATIZEDMEMORYALLOCATOR<StackAndStats_t> > StatVector_t;
+ typedef std::map< IndexMapKey_t, StatIndex_t, std::less<IndexMapKey_t>, TEMPLATIZEDMEMORYALLOCATOR<std::pair<const IndexMapKey_t, StatIndex_t> > > IndexMap_t;
+ typedef typename IndexMap_t::iterator IndexMapIter_t;
+ typedef typename IndexMap_t::value_type IndexMapEntry_t;
+
+ StatVector_t m_StatEntries;
+ IndexMap_t m_IndexMap;
+
+ struct PushedSubTree_t
+ {
+ unsigned long iThreadID;
+ CCallStackStatsGatherer_Standardized_t tree;
+ void *Stack[CAPTUREDCALLSTACKLENGTH];
+ };
+
+ typedef std::vector<PushedSubTree_t, TEMPLATIZEDMEMORYALLOCATOR<PushedSubTree_t> > PushedSubTreeVector_t;
+ PushedSubTreeVector_t m_PushedSubTrees;
+
+ typedef std::vector<CCallStackStatsGatherer_Standardized_t, TEMPLATIZEDMEMORYALLOCATOR<CCallStackStatsGatherer_Standardized_t> > StoredSubTreeVector_t;
+ StoredSubTreeVector_t m_StoredSubTrees;
+
+ CThreadFastMutex m_IndexMapMutex;
+ CThreadFastMutex m_SubTreeMutex;
+
+ //only for locking the memory in place, locked for write when the entry addresses might change.
+ //Locked for read when you've claimed you're manipulating a value.
+ //You're on your own for making sure two threads don't access the same index simultaneously
+ CThreadRWLock m_StatEntryLock;
+
+#else //#if defined( ENABLE_STACK_STATS_GATHERING )
+
+ STATSTRUCT m_SingleEntry; //the class is disabled, we'll always return this same struct
+ void *m_SingleCallStack[CAPTUREDCALLSTACKLENGTH];
+
+ static size_t NULL_DescribeCallStackStatStruct( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) { return 0; }
+
+#endif //#if defined( ENABLE_STACK_STATS_GATHERING )
+};
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+const FN_GetCallStack CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::StackFunction = STACKACQUISITIONFUNCTION;
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+const size_t CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::CapturedCallStackLength = CAPTUREDCALLSTACKLENGTH;
+
+#if defined( ENABLE_STACK_STATS_GATHERING )
+
+class CallStackStatStructDescFuncs;
+PLATFORM_INTERFACE size_t _CCallStackStatsGatherer_Write_FieldDescriptions( CallStackStatStructDescFuncs *pFieldDescriptions, uint8 *pWriteBuffer, size_t iWriteBufferSize );
+//PLATFORM_INTERFACE size_t _CCallStackStatsGatherer_Write_FieldMergeScript( CallStackStatStructDescFuncs *pFieldDescriptions, CallStackStatStructDescFuncs::MergeScript_Language scriptMergeLanguage, uint8 *pWriteBuffer, size_t iWriteBufferSize );
+
+#define DECLARE_CALLSTACKSTATSTRUCT() static const char *STATSTRUCTSTRINGNAME;\
+ static size_t DescribeCallStackStatStruct( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength );
+
+#define BEGIN_STATSTRUCTDESCRIPTION( className ) const char *className::STATSTRUCTSTRINGNAME = #className;\
+ size_t className::DescribeCallStackStatStruct( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) {\
+ size_t iWroteBytes = 0;
+#define END_STATSTRUCTDESCRIPTION() return iWroteBytes; }
+
+
+#define DECLARE_CALLSTACKSTATSTRUCT_FIELDDESCRIPTION() static CallStackStatStructDescFuncs *GetStatStructFieldDescriptions( void );
+
+#define BEGIN_STATSTRUCTFIELDDESCRIPTION( className ) CallStackStatStructDescFuncs * className::GetStatStructFieldDescriptions( void ) {\
+ typedef className ThisStruct;\
+ CallStackStatStructDescFuncs *_pHeadLinkage = NULL;\
+ CallStackStatStructDescFuncs **_pLinkageHelperVar = &_pHeadLinkage;
+
+#define _DEFINE_STATSTRUCTFIELD_VARNAME( varName, fieldName, fieldStruct, fieldParmsInParentheses ) static fieldStruct varName##_desc##fieldParmsInParentheses;\
+ varName##_desc.m_szFieldName = #fieldName;\
+ varName##_desc.m_iFieldOffset = (size_t)(&((ThisStruct *)NULL)->fieldName);\
+ varName##_desc.m_pNext = NULL;\
+ *_pLinkageHelperVar = &varName##_desc;\
+ _pLinkageHelperVar = &varName##_desc.m_pNext;
+
+#define DEFINE_STATSTRUCTFIELD( fieldName, fieldStruct, fieldParmsInParentheses ) _DEFINE_STATSTRUCTFIELD_VARNAME( fieldName, fieldName, fieldStruct, fieldParmsInParentheses )
+#define DEFINE_STATSTRUCTFIELD_ARRAYENTRY( arrayName, arrayIndex, fieldStruct, fieldParmsInParentheses ) _DEFINE_STATSTRUCTFIELD_VARNAME( arrayName##_##arrayIndex, arrayName##[##arrayIndex##], fieldStruct, fieldParmsInParentheses )
+
+#define END_STATSTRUCTFIELDDESCRIPTION() static CallStackStatStructDescFuncs *s_pHeadStruct = _pHeadLinkage;\
+ return s_pHeadStruct; }
+
+#define WRITE_STATSTRUCT_FIELDDESCRIPTION() iWroteBytes += _CCallStackStatsGatherer_Write_FieldDescriptions( GetStatStructFieldDescriptions(), pDescribeWriteBuffer + iWroteBytes, iDescribeMaxLength - iWroteBytes );
+//#define WRITE_STATSTRUCT_FIELDMERGESCRIPT( scriptMergeLanguage ) iWroteBytes += _CCallStackStatsGatherer_Write_FieldMergeScript( GetStatStructFieldDescriptions(), CallStackStatStructDescFuncs::scriptMergeLanguage, pDescribeWriteBuffer + iWroteBytes, iDescribeMaxLength - iWroteBytes );
+
+
+#else //#if defined( ENABLE_STACK_STATS_GATHERING )
+
+#define DECLARE_CALLSTACKSTATSTRUCT()
+#define BEGIN_STATSTRUCTDESCRIPTION( className )
+#define END_STATSTRUCTDESCRIPTION()
+
+#define DECLARE_CALLSTACKSTATSTRUCT_FIELDDESCRIPTION()
+#define BEGIN_STATSTRUCTFIELDDESCRIPTION( className )
+#define DEFINE_STATSTRUCTFIELD( fieldName, fieldStruct, fieldParmsInParentheses )
+#define END_STATSTRUCTFIELDDESCRIPTION()
+
+#define WRITE_STATSTRUCT_FIELDDESCRIPTION()
+//#define WRITE_STATSTRUCT_FIELDMERGESCRIPT( scriptMergeLanguage )
+
+#endif //#if defined( ENABLE_STACK_STATS_GATHERING )
+
+
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH] ) //get the entry using some callstack grabbed a while ago. Assumes ALL invalid entries have been nullified
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return GetEntry( GetEntryIndex( CallStack ) );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ) //same as above, but does the work of nullifying invalid entries
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ void *CleanedCallStack[CAPTUREDCALLSTACKLENGTH];
+ size_t i;
+ for( i = 0; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ CleanedCallStack[i] = CallStack[i];
+ }
+
+ for( ; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ CleanedCallStack[i] = NULL;
+ }
+ return GetEntry( GetEntryIndex( CleanedCallStack ) );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ COMPILE_TIME_ASSERT( CAPTUREDCALLSTACKLENGTH <= ARRAYSIZE( PushStack.pStack ) );
+ return GetEntry( GetEntryIndex( PushStack.pStack, PushStack.iValidEntries ) );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+uint32 CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntryIndex( const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ COMPILE_TIME_ASSERT( CAPTUREDCALLSTACKLENGTH <= ARRAYSIZE( PushStack.pStack ) );
+ return GetEntryIndex( PushStack.pStack, PushStack.iValidEntries );
+#else
+ return 0;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( uint32 iEntryIndex )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), iEntryIndex );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+uint32 CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntryIndex( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ) //index is unchanging, safe to keep and use later (designed for exactly that purpose)
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ AUTO_LOCK_FM( m_IndexMapMutex );
+ std::pair<IndexMapIter_t, bool> indexMapIter;
+ void *PatchedStack[CAPTUREDCALLSTACKLENGTH];
+
+ //if we have a sub-tree. We'll be splicing it into the original call stack as if it were a return address. Then patching that when we interpret the results later
+ //A stack with a sub-tree along the line is treated as distinctly different than one without a sub-tree
+ iValidEntries = PatchInSubTrees( CallStack, PatchedStack, iValidEntries );
+
+ Assert( iValidEntries <= CAPTUREDCALLSTACKLENGTH );
+
+ for( int i = iValidEntries; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ PatchedStack[i] = NULL;
+ }
+
+ indexMapIter = m_IndexMap.insert( IndexMapEntry_t( IndexMapKey_t( PatchedStack ), StatIndex_t() ) );
+
+ if( indexMapIter.first->second.m_Index == -1 )
+ {
+ m_StatEntryLock.LockForWrite();
+ indexMapIter.first->second.m_Index = (unsigned int)m_StatEntries.size();
+
+ m_StatEntries.push_back( StackAndStats_t() );
+ memcpy( m_StatEntries[indexMapIter.first->second.m_Index].m_CallStack, PatchedStack, sizeof( void * ) * CAPTUREDCALLSTACKLENGTH );
+ m_StatEntryLock.UnlockWrite();
+ }
+
+ return indexMapIter.first->second.m_Index;
+#else
+ return 0;
+#endif
+}
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetCallStackForIndex( uint32 iEntryIndex, void *CallStackOut[CAPTUREDCALLSTACKLENGTH] )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ m_StatEntryLock.LockForRead();
+ for( size_t i = 0; i != CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ CallStackOut[i] = m_StatEntries[iEntryIndex].m_CallStack[i];
+ }
+ m_StatEntryLock.UnlockRead();
+#else
+ for( size_t i = 0; i != CAPTUREDCALLSTACKLENGTH; ++i )
+ CallStackOut[i] = NULL;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+size_t CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::NumEntries( void ) const
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return m_StatEntries.size();
+#else
+ return 0;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+bool CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::DumpToFile( const char *szFileName, bool bAllowMemoryAllocations )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ CCallStackStatsGatherer_Standardized_t StandardThis = Standardized();
+ SyncMutexes( this, true );
+ bool bRetVal = _CCallStackStatsGatherer_Internal_DumpStatsToFile( szFileName, StandardThis, bAllowMemoryAllocations );
+ SyncMutexes( this, false );
+ return bRetVal;
+#else
+ return false;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+const CCallStackStatsGatherer_FunctionTable_t &CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetFunctionTable( void )
+{
+ static CCallStackStatsGatherer_FunctionTable_t retVal =
+ { GetDumpInfo,
+ PushSubTree,
+ PopSubTree,
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ STATSTRUCT::DescribeCallStackStatStruct,
+#else
+ NULL_DescribeCallStackStatStruct,
+#endif
+ SyncMutexes,
+ GetEntry,
+ ApplyTreeAccessLock,
+ LockEntry };
+
+ return retVal;
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetDumpInfo( void *pThis, const char *&szStructName, size_t &iCapturedStackLength, size_t &iEntrySizeWithStack, void *&pEntries, size_t &iEntryCount, CCallStackStatsGatherer_Standardized_t *&pSubTrees, size_t &iSubTreeCount )
+{
+ ThisCast *pThisCast = (ThisCast *)pThis;
+ iCapturedStackLength = CAPTUREDCALLSTACKLENGTH;
+ iEntrySizeWithStack = sizeof( CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::StackAndStats_t );
+
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ szStructName = STATSTRUCT::STATSTRUCTSTRINGNAME;
+ iEntryCount = pThisCast->m_StatEntries.size();
+ pEntries = iEntryCount > 0 ? &pThisCast->m_StatEntries[0] : NULL;
+ iSubTreeCount = pThisCast->m_StoredSubTrees.size();
+ pSubTrees = iSubTreeCount > 0 ? &pThisCast->m_StoredSubTrees[0] : NULL;
+#else
+ szStructName = "";
+ iEntryCount = 0;
+ pEntries = NULL;
+ iSubTreeCount = 0;
+ pSubTrees = NULL;
+#endif
+}
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::PushSubTree( void *pParent, const CCallStackStatsGatherer_Standardized_t &SubTree, const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ PushedSubTree_t pushVal;
+ pushVal.iThreadID = ThreadGetCurrentId();
+ pushVal.tree = SubTree;
+
+ memcpy( pushVal.Stack, PushStack.pStack, MIN( CAPTUREDCALLSTACKLENGTH, PushStack.iValidEntries ) * sizeof( void * ) );
+
+ for( int i = PushStack.iValidEntries; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ pushVal.Stack[i] = NULL;
+ }
+
+ pParentCast->m_SubTreeMutex.Lock();
+ pParentCast->m_PushedSubTrees.push_back( pushVal );
+ pParentCast->m_SubTreeMutex.Unlock();
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::PushSubTree( CCallStackStatsGatherer_Standardized_t &Parent, const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ CCallStackStatsGatherer_Standardized_t StandardThis = Standardized();
+ Parent.PushSubTree( StandardThis, PushStack );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::PopSubTree( void *pParent )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ pParentCast->m_SubTreeMutex.Lock();
+ unsigned long iThreadID = ThreadGetCurrentId();
+
+ for( PushedSubTreeVector_t::reverse_iterator treeIter = pParentCast->m_PushedSubTrees.rbegin(); treeIter != pParentCast->m_PushedSubTrees.rend(); ++treeIter )
+ {
+ if( treeIter->iThreadID == iThreadID )
+ {
+ ++treeIter; //[24.4.1/1] &*(reverse_iterator(i)) == &*(i - 1)
+ PushedSubTreeVector_t::iterator eraseIter = treeIter.base();
+ pParentCast->m_PushedSubTrees.erase(eraseIter);
+ break;
+ }
+ }
+
+ pParentCast->m_SubTreeMutex.Unlock();
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::SyncMutexes( void *pParent, bool bLock ) //true for lock, false for unlock
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ if( bLock )
+ {
+ pParentCast->m_IndexMapMutex.Lock();
+ pParentCast->m_SubTreeMutex.Lock();
+
+ for( StoredSubTreeVector_t::iterator treeIter = pParentCast->m_StoredSubTrees.begin(); treeIter != pParentCast->m_StoredSubTrees.end(); ++treeIter )
+ {
+ treeIter->pFunctionTable->pfn_SyncMutexes( treeIter->pGatherer, true );
+ }
+ }
+ else
+ {
+ for( StoredSubTreeVector_t::iterator treeIter = pParentCast->m_StoredSubTrees.begin(); treeIter != pParentCast->m_StoredSubTrees.end(); ++treeIter )
+ {
+ treeIter->pFunctionTable->pfn_SyncMutexes( treeIter->pGatherer, false );
+ }
+
+ pParentCast->m_IndexMapMutex.Unlock();
+ pParentCast->m_SubTreeMutex.Unlock();
+ }
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void *CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( void *pParent, uint32 iEntryIndex )
+{
+ ThisCast *pParentCast = (ThisCast *)pParent;
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return &pParentCast->m_StatEntries[iEntryIndex].m_Stats;
+#else
+ return &pParentCast->m_SingleEntry;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::ApplyTreeAccessLock( void *pParent, bool bLock )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ if( bLock )
+ {
+ pParentCast->m_StatEntryLock.LockForRead();
+ }
+ else
+ {
+ pParentCast->m_StatEntryLock.UnlockRead();
+ }
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::LockEntry( void *pParent, uint32 iEntryIndex, bool bLock )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ pParentCast->STATMUTEXHANDLER::LockEntry( iEntryIndex, bLock );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::Reset( void )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ m_StatEntryLock.LockForWrite();
+ m_IndexMapMutex.Lock();
+ m_SubTreeMutex.Lock();
+
+ m_StatEntries.clear();
+ m_IndexMap.clear();
+ m_StoredSubTrees.clear();
+
+ m_SubTreeMutex.Unlock();
+ m_IndexMapMutex.Unlock();
+ m_StatEntryLock.UnlockWrite();
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::operator CCallStackStatsGatherer_Standardized_t( void )
+{
+ return CCallStackStatsGatherer_Standardized_t( this, GetFunctionTable() );
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_Standardized_t CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::Standardized( void )
+{
+ return CCallStackStatsGatherer_Standardized_t( this, GetFunctionTable() );
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class PLATFORM_CLASS CallStackStatStructDescFuncs
+{
+public:
+ //description file format
+ //1 byte version per entry. Assuming that the field will get more descriptive over time, reserving this now.
+ virtual size_t DescribeField( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) = 0;
+
+ enum MergeScript_Language
+ {
+ SSMSL_Squirrel, //Only support squirrel for now, theoretically expandable to any vscript supported language
+ };
+
+#if 0 //embedded script handling not ready yet
+ //this is expected to write a piece of script code into the body of a function that will merge two values of this type
+ //The function will have two parameters, "mergeTo", and "mergeFrom". Both are tables with your field defined by name
+ //So, an example to merge an integer count defined as "foo" in the stack struct would look like this "mergeTo.foo += mergeFrom.foo\n"
+ virtual size_t DescribeMergeOperation( MergeScript_Language scriptLanguage, uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) = 0;
+#endif
+
+ //reserve your description field versions here to avoid stomping others
+ enum DescribeFieldVersions_t
+ {
+ DFV_BasicStatStructFieldTypes_t, //Format: 1 byte BasicStatStructFieldTypes_t type, 4 byte field offset, null terminated string field name
+ };
+
+ const char *m_szFieldName;
+ size_t m_iFieldOffset;
+ CallStackStatStructDescFuncs *m_pNext; //needed for how the description macros are laid out. Couldn't figure out a way to store the static struct instances as a static array
+};
+
+enum StatStructDescription_LumpID
+{
+ SSDLID_UNKNOWN,
+ SSDLID_STATICINTERPRETER,
+ SSDLID_FIELDDESC,
+ SSDLID_EMBEDDEDSCRIPT,
+
+
+ SSDLID_COUNT,
+ SSDLID_FORCE_UINT32 = 0xFFFFFFFF,
+};
+
+enum BasicStatStructFieldTypes_t
+{
+ BSSFT_UNKNOWN,
+ BSSFT_BOOL,
+ BSSFT_INT8,
+ BSSFT_UINT8,
+ BSSFT_INT16,
+ BSSFT_UINT16,
+ BSSFT_INT32,
+ BSSFT_UINT32,
+ BSSFT_INT64,
+ BSSFT_UINT64,
+ BSSFT_FLOAT,
+ BSSFT_DOUBLE,
+ BSSFT_VECTOR2D,
+ BSSFT_VECTOR3D,
+ BSSFT_VECTOR4D,
+
+ BSSFT_COUNT,
+};
+
+#define BSSFT_INT (sizeof( int ) == sizeof( int32 ) ? BSSFT_INT32 : BSSFT_INT64)
+#define BSSFT_UINT (sizeof( unsigned int ) == sizeof( uint32 ) ? BSSFT_UINT32 : BSSFT_UINT64)
+#define BSSFT_SIZE_T (sizeof( size_t ) == sizeof( uint32 ) ? BSSFT_UINT32 : BSSFT_UINT64)
+
+enum BasicStatStructFieldCombineMethods_t
+{
+ BSSFCM_UNKNOWN,
+ BSSFCM_CUSTOM, //rely on some outside handler
+ BSSFCM_ADD, //add the values
+ //BSSFCM_SUBTRACT, //what would subtract even mean? which one from which?
+ BSSFCM_MAX, //keep max value
+ BSSFCM_MIN, //keep min value
+ BSSFCM_AND, // &= , Non-integer behavior undefined
+ BSSFCM_OR, // |= , Non-integer behavior undefined
+ BSSFCM_XOR, // ^= , Non-integer behavior undefined
+ /*BSSFCM_LIST, //keep a list of each value (probably complicated)*/
+
+ BSSFCM_COUNT,
+};
+
+class PLATFORM_CLASS BasicStatStructFieldDesc : public CallStackStatStructDescFuncs
+{
+public:
+ BasicStatStructFieldDesc( BasicStatStructFieldTypes_t type, BasicStatStructFieldCombineMethods_t combineMethod ) : m_Type(type), m_Combine(combineMethod) {};
+ size_t DescribeField( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength );
+#if 0 //embedded script handling not ready yet
+ size_t DescribeMergeOperation( MergeScript_Language scriptLanguage, uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength );
+#endif
+
+ BasicStatStructFieldTypes_t m_Type;
+ BasicStatStructFieldCombineMethods_t m_Combine;
+};
+
+
+
+
+
+
+
+//struct is locked in place while you're holding onto one of these. Get a base, then create one of these from it
+template <class STATSTRUCT>
+class CCallStackStatsGatherer_StructAccessor_AutoLock : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>
+{
+public:
+ CCallStackStatsGatherer_StructAccessor_AutoLock( CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> &copyFrom )
+ : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( copyFrom )
+ {
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, true );
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, true );
+ this->m_pStruct = (STATSTRUCT *)this->m_Gatherer.pFunctionTable->pfn_GetEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex );
+ }
+
+ ~CCallStackStatsGatherer_StructAccessor_AutoLock( void )
+ {
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, false );
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, false );
+ }
+
+ STATSTRUCT *operator->()
+ {
+ return this->m_pStruct;
+ }
+
+ STATSTRUCT *GetStruct( void ) //do not hold this pointer outside the lock period
+ {
+ return this->m_pStruct;
+ }
+
+protected:
+ STATSTRUCT *m_pStruct;
+};
+
+
+//struct is locked in place only between Lock() and paired Unlock() calls. Get a base, then create one of these from it.
+//It's safe to hold onto this for an extended period of time. The entry index is unchanging in the gatherer tree.
+template <class STATSTRUCT>
+class CCallStackStatsGatherer_StructAccessor_Manual : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>
+{
+public:
+ CCallStackStatsGatherer_StructAccessor_Manual( CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> &copyFrom )
+ : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( copyFrom ), m_pStruct( NULL )
+ { }
+
+ STATSTRUCT *operator->()
+ {
+ return this->m_pStruct; //NULL while entry is not locked.
+ }
+
+ STATSTRUCT *GetStruct( void ) //do not hold this pointer outside the lock period
+ {
+ return this->m_pStruct; //NULL while entry is not locked.
+ }
+
+ void Lock( void )
+ {
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, true );
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, true );
+ this->m_pStruct = (STATSTRUCT *)this->m_Gatherer.pFunctionTable->pfn_GetEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex );
+ }
+
+ void Unlock( void )
+ {
+ this->m_pStruct = NULL;
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, false );
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, false );
+ }
+
+protected:
+ STATSTRUCT *m_pStruct;
+};
+
+
+
+
+
+class CCallStackStats_PushSubTree_AutoPop
+{
+public:
+ CCallStackStats_PushSubTree_AutoPop( const CCallStackStatsGatherer_Standardized_t &Parent, const CCallStackStatsGatherer_Standardized_t &Child, const CCallStackStorage &PushStack = CCallStackStorage() )
+ : m_PopFrom( Parent )
+ {
+ Parent.pFunctionTable->pfn_PushSubTree( Parent.pGatherer, Child, PushStack );
+ }
+ ~CCallStackStats_PushSubTree_AutoPop( void )
+ {
+ m_PopFrom.PopSubTree();
+ }
+
+ CCallStackStatsGatherer_Standardized_t m_PopFrom;
+};
+
+
+#endif //#ifndef TIER0_STACKTOOLS_H
diff --git a/external/vpc/public/tier0/stacktools.h b/external/vpc/public/tier0/stacktools.h
new file mode 100644
index 0000000..c356b8c
--- /dev/null
+++ b/external/vpc/public/tier0/stacktools.h
@@ -0,0 +1,153 @@
+//========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Tools for grabbing/dumping the stack at runtime
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_STACKTOOLS_H
+#define TIER0_STACKTOOLS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+#if (defined( PLATFORM_WINDOWS ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT ) && defined( TCHAR_IS_CHAR ) //designed for windows/x360, not built/tested with wide characters, not intended for release builds (but probably wouldn't damage anything)
+# define ENABLE_RUNTIME_STACK_TRANSLATION //uncomment to enable runtime stack translation tools. All of which use on-demand loading of necessary dll's and pdb's
+#endif
+
+#if defined( ENABLE_RUNTIME_STACK_TRANSLATION )
+//#define ENABLE_THREAD_PARENT_STACK_TRACING 1 //uncomment to actually enable tracking stack traces from threads and jobs to their parent thread. Must also define THREAD_PARENT_STACK_TRACE_SUPPORTED in threadtools.h
+# if defined( ENABLE_THREAD_PARENT_STACK_TRACING )
+# define THREAD_PARENT_STACK_TRACE_LENGTH 32
+# endif
+#endif
+
+
+
+
+PLATFORM_INTERFACE int GetCallStack( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
+
+//ONLY WORKS IF THE CRAWLED PORTION OF THE STACK DISABLES FRAME POINTER OMISSION (/Oy-) "vpc /nofpo"
+PLATFORM_INTERFACE int GetCallStack_Fast( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
+
+typedef int (*FN_GetCallStack)( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
+
+//where we'll find our PDB's for win32.
+PLATFORM_INTERFACE void SetStackTranslationSymbolSearchPath( const char *szSemicolonSeparatedList = NULL );
+PLATFORM_INTERFACE void StackToolsNotify_LoadedLibrary( const char *szLibName );
+
+//maximum output sample "tier0.dll!TranslateStackInfo - u:\Dev\L4D\src\tier0\stacktools.cpp(162) + 4 bytes"
+enum TranslateStackInfo_StyleFlags_t
+{
+ TSISTYLEFLAG_NONE = 0,
+ TSISTYLEFLAG_MODULENAME = (1<<0), //start with module Sample: "tier0.dll!"
+ TSISTYLEFLAG_SYMBOLNAME = (1<<1), //include the symbol name Sample: "TranslateStackInfo"
+ TSISTYLEFLAG_FULLPATH = (1<<2), //include full path Sample: "u:\Dev\L4D\src\tier0\stacktools.cpp"
+ TSISTYLEFLAG_SHORTPATH = (1<<3), //only include 2 directories Sample: "\src\tier0\stacktools.cpp"
+ TSISTYLEFLAG_LINE = (1<<4), //file line number Sample: "(162)"
+ TSISTYLEFLAG_LINEANDOFFSET = (1<<5), //file line + offset Sample: "(162) + 4 bytes"
+ TSISTYLEFLAG_LAST = TSISTYLEFLAG_LINEANDOFFSET,
+ TSISTYLEFLAG_DEFAULT = (TSISTYLEFLAG_MODULENAME | TSISTYLEFLAG_SYMBOLNAME | TSISTYLEFLAG_FULLPATH | TSISTYLEFLAG_LINEANDOFFSET), //produces sample above
+};
+
+//Generates a formatted list of function information, returns number of translated entries
+//On 360 this generates a string that can be decoded by VXConsole in print functions. Optimal path for translation because it's one way. Other paths require multiple transactions.
+PLATFORM_INTERFACE int TranslateStackInfo( const void * const *pCallStack, int iCallStackCount, tchar *szOutput, int iOutBufferSize, const tchar *szEntrySeparator, TranslateStackInfo_StyleFlags_t style = TSISTYLEFLAG_DEFAULT );
+
+PLATFORM_INTERFACE void PreloadStackInformation( void * const *pAddresses, int iAddressCount ); //caches data and reduces communication with VXConsole to speed up 360 decoding when using any of the Get***FromAddress() functions. Nop on PC.
+PLATFORM_INTERFACE bool GetFileAndLineFromAddress( const void *pAddress, tchar *pFileNameOut, int iMaxFileNameLength, uint32 &iLineNumberOut, uint32 *pDisplacementOut = NULL );
+PLATFORM_INTERFACE bool GetSymbolNameFromAddress( const void *pAddress, tchar *pSymbolNameOut, int iMaxSymbolNameLength, uint64 *pDisplacementOut = NULL );
+PLATFORM_INTERFACE bool GetModuleNameFromAddress( const void *pAddress, tchar *pModuleNameOut, int iMaxModuleNameLength );
+
+
+
+class PLATFORM_CLASS CCallStackStorage //a helper class to grab a stack trace as close to the leaf code surface as possible, then pass it on to deeper functions intact with less unpredictable inlining pollution
+{
+public:
+ CCallStackStorage( FN_GetCallStack GetStackFunction = GetCallStack, uint32 iSkipCalls = 0 );
+ CCallStackStorage( const CCallStackStorage &copyFrom )
+ {
+ iValidEntries = copyFrom.iValidEntries;
+ memcpy( pStack, copyFrom.pStack, sizeof( void * ) * copyFrom.iValidEntries );
+ }
+
+ void *pStack[128]; //probably too big, possibly too small for some applications. Don't want to spend the time figuring out how to generalize this without templatizing pollution or mallocs
+ uint32 iValidEntries;
+};
+
+
+//Hold onto one of these to denote the top of a functional stack trace. Also allows us to string together threads to their parents
+class PLATFORM_CLASS CStackTop_Base
+{
+protected:
+#if defined( ENABLE_RUNTIME_STACK_TRANSLATION )
+ CStackTop_Base *m_pPrevTop;
+ void *m_pStackBase;
+ void *m_pReplaceAddress;
+
+ void * const *m_pParentStackTrace;
+ int m_iParentStackTraceLength;
+#endif
+};
+
+//makes a copy of the parent stack
+class PLATFORM_CLASS CStackTop_CopyParentStack : public CStackTop_Base
+{
+public:
+ CStackTop_CopyParentStack( void * const * pParentStackTrace, int iParentStackTraceLength );
+ ~CStackTop_CopyParentStack( void );
+};
+
+//just references the parent stack. Assuming that you'll keep that memory around as long as you're keeping this Stack Top marker.
+class PLATFORM_CLASS CStackTop_ReferenceParentStack : public CStackTop_Base
+{
+public:
+ CStackTop_ReferenceParentStack( void * const * pParentStackTrace = NULL, int iParentStackTraceLength = 0 );
+ ~CStackTop_ReferenceParentStack( void );
+ void ReleaseParentStackReferences( void ); //in case you need to delete the parent stack trace before this class goes out of scope
+};
+
+
+//Encodes data so that every byte's most significant bit is a 1. Ensuring no null terminators.
+//This puts the encoded data in the 128-255 value range. Leaving all standard ascii characters for control.
+//Returns string length (not including the written null terminator as is standard).
+//Or if the buffer is too small. Returns negative of necessary buffer size (including room needed for null terminator)
+PLATFORM_INTERFACE int EncodeBinaryToString( const void *pToEncode, int iDataLength, char *pEncodeOut, int iEncodeBufferSize );
+
+//Decodes a string produced by EncodeBinaryToString(). Safe to decode in place if you don't mind trashing your string, binary byte count always less than string byte count.
+//Returns:
+// >= 0 is the decoded data size
+// INT_MIN (most negative value possible) indicates an improperly formatted string (not our data)
+// all other negative values are the negative of how much dest buffer size is necessary.
+PLATFORM_INTERFACE int DecodeBinaryFromString( const char *pString, void *pDestBuffer, int iDestBufferSize, char **ppParseFinishOut = NULL );
+
+
+
+
+// 360<->VXConsole specific communication definitions
+#define XBX_CALLSTACKDECODEPREFIX ":CSDECODE["
+
+enum StackTranslation_BinaryHandler_Command_t
+{
+ ST_BHC_LOADEDLIBARY,
+ ST_BHC_GETTRANSLATIONINFO,
+};
+
+#pragma pack(push)
+#pragma pack(1)
+struct FullStackInfo_t
+{
+ const void *pAddress;
+ char szModuleName[24];
+ char szFileName[MAX_PATH/2];
+ char szSymbol[64];
+ uint32 iLine;
+ uint32 iSymbolOffset;
+
+};
+#pragma pack(pop)
+
+#endif //#ifndef TIER0_STACKTOOLS_H
diff --git a/external/vpc/public/tier0/threadtools.h b/external/vpc/public/tier0/threadtools.h
new file mode 100644
index 0000000..458675a
--- /dev/null
+++ b/external/vpc/public/tier0/threadtools.h
@@ -0,0 +1,2402 @@
+//========== Copyright 2005, Valve Corporation, All rights reserved. ========
+//
+// Purpose: A collection of utility classes to simplify thread handling, and
+// as much as possible contain portability problems. Here avoiding
+// including windows.h.
+//
+//=============================================================================
+
+#ifndef THREADTOOLS_H
+#define THREADTOOLS_H
+
+#include <limits.h>
+
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+
+#if defined( POSIX ) && !defined( _PS3 ) && !defined( _X360 )
+#include <pthread.h>
+#include <errno.h>
+#define WAIT_OBJECT_0 0
+#define WAIT_TIMEOUT 0x00000102
+#define WAIT_FAILED -1
+#define THREAD_PRIORITY_HIGHEST 2
+#endif
+
+#if defined( _PS3 )
+#include <sys/ppu_thread.h>
+#include <sys/synchronization.h>
+#include <cell/atomic.h>
+#include <sys/timer.h>
+#endif
+
+#ifdef OSX
+// Add some missing defines
+#define PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_NORMAL
+#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+#define PTHREAD_MUTEX_ERRORCHECK_NP PTHREAD_MUTEX_ERRORCHECK
+#define PTHREAD_MUTEX_ADAPTIVE_NP 3
+#endif
+
+#ifdef _PS3
+#define PS3_SYS_PPU_THREAD_COMMON_STACK_SIZE ( 256 * 1024 )
+#endif
+
+
+#if defined( _WIN32 )
+#pragma once
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+
+#ifdef COMPILER_MSVC64
+#include <intrin.h>
+#endif
+
+// #define THREAD_PROFILER 1
+
+#define THREAD_MUTEX_TRACING_SUPPORTED
+#if defined(_WIN32) && defined(_DEBUG)
+#define THREAD_MUTEX_TRACING_ENABLED
+#endif
+
+#ifdef _WIN32
+typedef void *HANDLE;
+#endif
+
+// maximum number of threads that can wait on one object
+#define CTHREADEVENT_MAX_WAITING_THREADS 4
+
+#if (defined( PLATFORM_WINDOWS_PC ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT )
+//Thread parent stack trace linkage requires ALL executing binaries to disable frame pointer omission to operate speedily/successfully. (/Oy-) "vpc /nofpo"
+#define THREAD_PARENT_STACK_TRACE_SUPPORTED 1 //uncomment to support joining the root of a thread's stack trace to its parent's at time of invocation. Must also set ENABLE_THREAD_PARENT_STACK_TRACING in stacktools.h
+#endif
+
+#if defined( THREAD_PARENT_STACK_TRACE_SUPPORTED )
+#include "tier0/stacktools.h"
+# if defined( ENABLE_THREAD_PARENT_STACK_TRACING ) //stacktools.h opted in
+# define THREAD_PARENT_STACK_TRACE_ENABLED 1 //both threadtools.h and stacktools.h have opted into the feature, enable it
+# endif
+#endif
+
+extern bool gbCheckNotMultithreaded;
+
+#ifdef _PS3
+
+#define USE_INTRINSIC_INTERLOCKED
+
+#define CHECK_NOT_MULTITHREADED() \
+{ \
+ static int init = 0; \
+ static sys_ppu_thread_t threadIDPrev; \
+ \
+ if (!init) \
+ { \
+ sys_ppu_thread_get_id(&threadIDPrev); \
+ init = 1; \
+ } \
+ else if (gbCheckNotMultithreaded) \
+ { \
+ sys_ppu_thread_t threadID; \
+ sys_ppu_thread_get_id(&threadID); \
+ if (threadID != threadIDPrev) \
+ { \
+ printf("CHECK_NOT_MULTITHREADED: prev thread = %x, cur thread = %x\n", \
+ (uint)threadIDPrev, (uint)threadID); \
+ *(int*)0 = 0; \
+ } \
+ } \
+}
+
+#else
+ #define CHECK_NOT_MULTITHREADED()
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+#define MAX_THREADS_SUPPORTED 16
+#else
+#define MAX_THREADS_SUPPORTED 32
+#endif
+
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+const unsigned TT_INFINITE = 0xffffffff;
+
+#ifdef PLATFORM_64BITS
+typedef uint64 ThreadId_t;
+#else
+typedef uint32 ThreadId_t;
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Simple thread creation. Differs from VCR mode/CreateThread/_beginthreadex
+// in that it accepts a standard C function rather than compiler specific one.
+//
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_SNC
+typedef uint64 ThreadHandle_t;
+#else // COMPILER_SNC
+FORWARD_DECLARE_HANDLE( ThreadHandle_t );
+#endif // !COMPILER_SNC
+typedef uintp (*ThreadFunc_t)( void *pParam );
+
+#if defined( _PS3 )
+PLATFORM_OVERLOAD ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, ThreadId_t *pID, unsigned stackSize = 0x10000 /*64*/ );
+PLATFORM_INTERFACE ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, unsigned stackSize = 0x10000 /*64*/ );
+#else //_PS3
+PLATFORM_OVERLOAD ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, ThreadId_t *pID, unsigned stackSize = 0 );
+PLATFORM_INTERFACE ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, unsigned stackSize = 0 );
+#endif //_PS3
+PLATFORM_INTERFACE bool ReleaseThreadHandle( ThreadHandle_t );
+
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE void ThreadSleep(unsigned duration = 0);
+PLATFORM_INTERFACE ThreadId_t ThreadGetCurrentId();
+PLATFORM_INTERFACE ThreadHandle_t ThreadGetCurrentHandle();
+PLATFORM_INTERFACE int ThreadGetPriority( ThreadHandle_t hThread = NULL );
+PLATFORM_INTERFACE bool ThreadSetPriority( ThreadHandle_t hThread, int priority );
+inline bool ThreadSetPriority( int priority ) { return ThreadSetPriority( NULL, priority ); }
+#ifndef _X360
+PLATFORM_INTERFACE bool ThreadInMainThread();
+PLATFORM_INTERFACE void DeclareCurrentThreadIsMainThread();
+#else
+PLATFORM_INTERFACE byte *g_pBaseMainStack;
+PLATFORM_INTERFACE byte *g_pLimitMainStack;
+inline bool ThreadInMainThread()
+{
+ byte b;
+ byte *p = &b;
+ return ( p < g_pBaseMainStack && p >= g_pLimitMainStack );
+}
+#endif
+
+// NOTE: ThreadedLoadLibraryFunc_t needs to return the sleep time in milliseconds or TT_INFINITE
+typedef int (*ThreadedLoadLibraryFunc_t)();
+PLATFORM_INTERFACE void SetThreadedLoadLibraryFunc( ThreadedLoadLibraryFunc_t func );
+PLATFORM_INTERFACE ThreadedLoadLibraryFunc_t GetThreadedLoadLibraryFunc();
+
+#if defined( PLATFORM_WINDOWS_PC32 )
+DLL_IMPORT unsigned long STDCALL GetCurrentThreadId();
+#define ThreadGetCurrentId GetCurrentThreadId
+#endif
+
+inline void ThreadPause()
+{
+#if defined( COMPILER_PS3 )
+ __db16cyc();
+#elif defined( COMPILER_GCC )
+ __asm __volatile( "pause" );
+#elif defined ( COMPILER_MSVC64 )
+ _mm_pause();
+#elif defined( COMPILER_MSVC32 )
+ __asm pause;
+#elif defined( COMPILER_MSVCX360 )
+ YieldProcessor();
+ __asm { or r0,r0,r0 }
+ YieldProcessor();
+ __asm { or r1,r1,r1 }
+#else
+#error "implement me"
+#endif
+}
+
+PLATFORM_INTERFACE bool ThreadJoin( ThreadHandle_t, unsigned timeout = TT_INFINITE );
+
+PLATFORM_INTERFACE void ThreadSetDebugName( ThreadHandle_t hThread, const char *pszName );
+inline void ThreadSetDebugName( const char *pszName ) { ThreadSetDebugName( NULL, pszName ); }
+
+PLATFORM_INTERFACE void ThreadSetAffinity( ThreadHandle_t hThread, int nAffinityMask );
+
+
+//-----------------------------------------------------------------------------
+//
+// Interlock methods. These perform very fast atomic thread
+// safe operations. These are especially relevant in a multi-core setting.
+//
+//-----------------------------------------------------------------------------
+
+#ifdef _WIN32
+#define NOINLINE
+#elif defined( _PS3 )
+#define NOINLINE __attribute__ ((noinline))
+#elif defined(POSIX)
+#define NOINLINE __attribute__ ((noinline))
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+#define ThreadMemoryBarrier() __lwsync()
+#else
+#define ThreadMemoryBarrier() ((void)0)
+#endif
+
+#if defined( _LINUX ) || defined( _OSX )
+#define USE_INTRINSIC_INTERLOCKED
+// linux implementation
+inline int32 ThreadInterlockedIncrement( int32 volatile *p )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_fetch_and_add( p, 1 ) + 1;
+}
+
+inline int32 ThreadInterlockedDecrement( int32 volatile *p )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_fetch_and_add( p, -1 ) - 1;
+}
+
+inline int32 ThreadInterlockedExchange( int32 volatile *p, int32 value )
+{
+ Assert( (size_t)p % 4 == 0 );
+ int32 nRet;
+
+ // Note: The LOCK instruction prefix is assumed on the XCHG instruction and GCC gets very confused on the Mac when we use it.
+ __asm __volatile(
+ "xchgl %2,(%1)"
+ : "=r" (nRet)
+ : "r" (p), "0" (value)
+ : "memory");
+ return nRet;
+}
+
+inline int32 ThreadInterlockedExchangeAdd( int32 volatile *p, int32 value )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_fetch_and_add( p, value );
+}
+inline int32 ThreadInterlockedCompareExchange( int32 volatile *p, int32 value, int32 comperand )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_val_compare_and_swap( p, comperand, value );
+}
+
+
+inline bool ThreadInterlockedAssignIf( int32 volatile *p, int32 value, int32 comperand )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_bool_compare_and_swap( p, comperand, value );
+}
+
+#elif ( defined( COMPILER_MSVC32 ) && ( _MSC_VER >= 1310 ) )
+// windows 32 implemnetation using compiler intrinsics
+#define USE_INTRINSIC_INTERLOCKED
+
+extern "C"
+{
+ long __cdecl _InterlockedIncrement(volatile long*);
+ long __cdecl _InterlockedDecrement(volatile long*);
+ long __cdecl _InterlockedExchange(volatile long*, long);
+ long __cdecl _InterlockedExchangeAdd(volatile long*, long);
+ long __cdecl _InterlockedCompareExchange(volatile long*, long, long);
+}
+
+#pragma intrinsic( _InterlockedCompareExchange )
+#pragma intrinsic( _InterlockedDecrement )
+#pragma intrinsic( _InterlockedExchange )
+#pragma intrinsic( _InterlockedExchangeAdd )
+#pragma intrinsic( _InterlockedIncrement )
+
+inline int32 ThreadInterlockedIncrement( int32 volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedIncrement( (volatile long*)p ); }
+inline int32 ThreadInterlockedDecrement( int32 volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedDecrement( (volatile long*)p ); }
+inline int32 ThreadInterlockedExchange( int32 volatile *p, int32 value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchange( (volatile long*)p, value ); }
+inline int32 ThreadInterlockedExchangeAdd( int32 volatile *p, int32 value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchangeAdd( (volatile long*)p, value ); }
+inline int32 ThreadInterlockedCompareExchange( int32 volatile *p, int32 value, int32 comperand ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedCompareExchange( (volatile long*)p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( int32 volatile *p, int32 value, int32 comperand ) { Assert( (size_t)p % 4 == 0 ); return ( _InterlockedCompareExchange( (volatile long*)p, value, comperand ) == comperand ); }
+#elif defined( _PS3 )
+PLATFORM_INTERFACE inline int32 ThreadInterlockedIncrement( int32 volatile * ea ) { return cellAtomicIncr32( (uint32_t*)ea ) + 1; }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedDecrement( int32 volatile * ea ) { return cellAtomicDecr32( (uint32_t*)ea ) - 1; }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedExchange( int32 volatile * ea, int32 value ) { return cellAtomicStore32( ( uint32_t* )ea, value); }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedExchangeAdd( int32 volatile * ea, int32 value ) { return cellAtomicAdd32( ( uint32_t* )ea, value ); }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedCompareExchange( int32 volatile * ea, int32 value, int32 comperand ) { return cellAtomicCompareAndSwap32( (uint32_t*)ea, comperand, value ) ; }
+PLATFORM_INTERFACE inline bool ThreadInterlockedAssignIf( int32 volatile * ea, int32 value, int32 comperand ) { return ( cellAtomicCompareAndSwap32( (uint32_t*)ea, comperand, value ) == ( uint32_t ) comperand ); }
+
+PLATFORM_INTERFACE inline int64 ThreadInterlockedCompareExchange64( int64 volatile *pDest, int64 value, int64 comperand ) { return cellAtomicCompareAndSwap64( ( uint64_t* ) pDest, comperand, value ); }
+PLATFORM_INTERFACE inline bool ThreadInterlockedAssignIf64( volatile int64 *pDest, int64 value, int64 comperand ) { return ( cellAtomicCompareAndSwap64( ( uint64_t* ) pDest, comperand, value ) == ( uint64_t ) comperand ); }
+
+#elif defined( _X360 )
+#define TO_INTERLOCK_PARAM(p) ((volatile long *)p)
+#define TO_INTERLOCK_PTR_PARAM(p) ((void **)p)
+FORCEINLINE int32 ThreadInterlockedIncrement( int32 volatile *pDest ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedIncrement( TO_INTERLOCK_PARAM(pDest) ); }
+FORCEINLINE int32 ThreadInterlockedDecrement( int32 volatile *pDest ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedDecrement( TO_INTERLOCK_PARAM(pDest) ); }
+FORCEINLINE int32 ThreadInterlockedExchange( int32 volatile *pDest, int32 value ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedExchange( TO_INTERLOCK_PARAM(pDest), value ); }
+FORCEINLINE int32 ThreadInterlockedExchangeAdd( int32 volatile *pDest, int32 value ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedExchangeAdd( TO_INTERLOCK_PARAM(pDest), value ); }
+FORCEINLINE int32 ThreadInterlockedCompareExchange( int32 volatile *pDest, int32 value, int32 comperand ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedCompareExchange( TO_INTERLOCK_PARAM(pDest), value, comperand ); }
+FORCEINLINE bool ThreadInterlockedAssignIf( int32 volatile *pDest, int32 value, int32 comperand ) { Assert( (size_t)pDest % 4 == 0 ); return ( InterlockedCompareExchange( TO_INTERLOCK_PARAM(pDest), value, comperand ) == comperand ); }
+#else
+// non 32-bit windows and 360 implementation
+PLATFORM_INTERFACE int32 ThreadInterlockedIncrement( int32 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedDecrement( int32 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedExchange( int32 volatile *, int32 value ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedExchangeAdd( int32 volatile *, int32 value ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedCompareExchange( int32 volatile *, int32 value, int32 comperand ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf( int32 volatile *, int32 value, int32 comperand ) NOINLINE;
+#endif
+
+
+#if defined( USE_INTRINSIC_INTERLOCKED ) && !defined( PLATFORM_64BITS )
+#define TIPTR()
+inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)( ( intp )ThreadInterlockedExchange( reinterpret_cast<intp volatile *>(p), reinterpret_cast<intp>(value) ) ); }
+inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)( ( intp )ThreadInterlockedCompareExchange( reinterpret_cast<intp volatile *>(p), reinterpret_cast<intp>(value), reinterpret_cast<intp>(comperand) ) ); }
+inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ( ThreadInterlockedCompareExchange( reinterpret_cast<intp volatile *>(p), reinterpret_cast<intp>(value), reinterpret_cast<intp>(comperand) ) == reinterpret_cast<intp>(comperand) ); }
+#else
+PLATFORM_INTERFACE void *ThreadInterlockedExchangePointer( void * volatile *, void *value ) NOINLINE;
+PLATFORM_INTERFACE void *ThreadInterlockedCompareExchangePointer( void * volatile *, void *value, void *comperand ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignPointerIf( void * volatile *, void *value, void *comperand ) NOINLINE;
+#endif
+
+
+inline unsigned ThreadInterlockedExchangeSubtract( int32 volatile *p, int32 value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, -value ); }
+
+inline void const *ThreadInterlockedExchangePointerToConst( void const * volatile *p, void const *value ) { return ThreadInterlockedExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ) ); }
+inline void const *ThreadInterlockedCompareExchangePointerToConst( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedCompareExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); }
+inline bool ThreadInterlockedAssignPointerToConstIf( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedAssignPointerIf( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); }
+
+
+#ifndef _PS3
+PLATFORM_INTERFACE int64 ThreadInterlockedCompareExchange64( int64 volatile *, int64 value, int64 comperand ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf64( volatile int64 *pDest, int64 value, int64 comperand ) NOINLINE;
+#endif
+
+PLATFORM_INTERFACE int64 ThreadInterlockedExchange64( int64 volatile *, int64 value ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedIncrement64( int64 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedDecrement64( int64 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedExchangeAdd64( int64 volatile *, int64 value ) NOINLINE;
+
+inline unsigned ThreadInterlockedExchangeSubtract( uint32 volatile *p, uint32 value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+
+inline unsigned ThreadInterlockedIncrement( uint32 volatile *p ) { return ThreadInterlockedIncrement( (int32 volatile *)p ); }
+inline unsigned ThreadInterlockedDecrement( uint32 volatile *p ) { return ThreadInterlockedDecrement( (int32 volatile *)p ); }
+inline unsigned ThreadInterlockedExchange( uint32 volatile *p, uint32 value ) { return ThreadInterlockedExchange( (int32 volatile *)p, value ); }
+inline unsigned ThreadInterlockedExchangeAdd( uint32 volatile *p, uint32 value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+inline unsigned ThreadInterlockedCompareExchange( uint32 volatile *p, uint32 value, uint32 comperand ) { return ThreadInterlockedCompareExchange( (int32 volatile *)p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( uint32 volatile *p, uint32 value, uint32 comperand ) { return ThreadInterlockedAssignIf( (int32 volatile *)p, value, comperand ); }
+
+//inline int ThreadInterlockedExchangeSubtract( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+//inline int ThreadInterlockedIncrement( int volatile *p ) { return ThreadInterlockedIncrement( (int32 volatile *)p ); }
+//inline int ThreadInterlockedDecrement( int volatile *p ) { return ThreadInterlockedDecrement( (int32 volatile *)p ); }
+//inline int ThreadInterlockedExchange( int volatile *p, int value ) { return ThreadInterlockedExchange( (int32 volatile *)p, value ); }
+//inline int ThreadInterlockedExchangeAdd( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+//inline int ThreadInterlockedCompareExchange( int volatile *p, int value, int comperand ) { return ThreadInterlockedCompareExchange( (int32 volatile *)p, value, comperand ); }
+//inline bool ThreadInterlockedAssignIf( int volatile *p, int value, int comperand ) { return ThreadInterlockedAssignIf( (int32 volatile *)p, value, comperand ); }
+
+
+//-----------------------------------------------------------------------------
+// Access to VTune thread profiling
+//-----------------------------------------------------------------------------
+#if defined(_WIN32) && defined(THREAD_PROFILER)
+PLATFORM_INTERFACE void ThreadNotifySyncPrepare(void *p);
+PLATFORM_INTERFACE void ThreadNotifySyncCancel(void *p);
+PLATFORM_INTERFACE void ThreadNotifySyncAcquired(void *p);
+PLATFORM_INTERFACE void ThreadNotifySyncReleasing(void *p);
+#else
+#define ThreadNotifySyncPrepare(p) ((void)0)
+#define ThreadNotifySyncCancel(p) ((void)0)
+#define ThreadNotifySyncAcquired(p) ((void)0)
+#define ThreadNotifySyncReleasing(p) ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+// Encapsulation of a thread local datum (needed because THREAD_LOCAL doesn't
+// work in a DLL loaded with LoadLibrary()
+//-----------------------------------------------------------------------------
+
+#ifndef NO_THREAD_LOCAL
+
+#if defined( _PS3 )
+// linux totally supports compiler thread locals, even across dll's.
+#define PLAT_COMPILER_SUPPORTED_THREADLOCALS 1
+#define CTHREADLOCALUSEERROR PS3_ELF_EXPORTED_THREADLOCAL PS3_ELF_EXPORTED_THREADLOCAL PS3_ELF_EXPORTED_THREADLOCAL
+#define CTHREADLOCALINTEGER( typ ) CTHREADLOCALUSEERROR int
+#define CTHREADLOCALINT CTHREADLOCALUSEERROR int
+#define CTHREADLOCALPTR( typ ) CTHREADLOCALUSEERROR typ *
+#define CTHREADLOCAL( typ ) CTHREADLOCALUSEERROR typ
+#define GETLOCAL( x ) ( x )
+#endif
+
+
+#if defined(_LINUX) && !defined(OSX)
+// linux totally supports compiler thread locals, even across dll's.
+#define PLAT_COMPILER_SUPPORTED_THREADLOCALS 1
+#define CTHREADLOCALINTEGER( typ ) __thread int
+#define CTHREADLOCALINT __thread int
+#define CTHREADLOCALPTR( typ ) __thread typ *
+#define CTHREADLOCAL( typ ) __thread typ
+#define GETLOCAL( x ) ( x )
+#ifndef TIER0_DLL_EXPORT
+DLL_IMPORT __thread int g_nThreadID;
+#endif
+#endif
+
+#if defined(WIN32) || defined(OSX)
+#ifndef __AFXTLS_H__ // not compatible with some Windows headers
+
+#define CTHREADLOCALINT GenericThreadLocals::CThreadLocalInt<int>
+#define CTHREADLOCALINTEGER( typ ) GenericThreadLocals::CThreadLocalInt<typ>
+#define CTHREADLOCALPTR( typ ) GenericThreadLocals::CThreadLocalPtr<typ>
+#define CTHREADLOCAL( typ ) GenericThreadLocals::CThreadLocal<typ>
+#define GETLOCAL( x ) ( x.Get() )
+
+
+namespace GenericThreadLocals
+{
+ // a (not so efficient) implementation of thread locals for compilers without full support (i.e. visual c).
+ // don't use this explicity - instead, use the CTHREADxxx macros above.
+
+ class PLATFORM_CLASS CThreadLocalBase
+ {
+public:
+ CThreadLocalBase();
+ ~CThreadLocalBase();
+
+ void * Get() const;
+ void Set(void *);
+
+private:
+#if defined(POSIX) && !defined( _GAMECONSOLE )
+ pthread_key_t m_index;
+#else
+ uint32 m_index;
+#endif
+ };
+
+ //---------------------------------------------------------
+
+ template <class T>
+ class CThreadLocal : public CThreadLocalBase
+ {
+ public:
+ CThreadLocal()
+ {
+#ifdef PLATFORM_64BITS
+ COMPILE_TIME_ASSERT( sizeof(T) <= sizeof(void *) );
+#else
+ COMPILE_TIME_ASSERT( sizeof(T) == sizeof(void *) );
+#endif
+ }
+
+ void operator=( T i ) { Set( i ); }
+
+ T Get() const
+ {
+#ifdef PLATFORM_64BITS
+ void *pData = CThreadLocalBase::Get();
+ return *reinterpret_cast<T*>( &pData );
+#else
+ #ifdef COMPILER_MSVC
+ #pragma warning ( disable : 4311 )
+ #endif
+ return reinterpret_cast<T>( CThreadLocalBase::Get() );
+ #ifdef COMPILER_MSVC
+ #pragma warning ( default : 4311 )
+ #endif
+#endif
+ }
+
+ void Set(T val)
+ {
+#ifdef PLATFORM_64BITS
+ void* pData = 0;
+ *reinterpret_cast<T*>( &pData ) = val;
+ CThreadLocalBase::Set( pData );
+#else
+ #ifdef COMPILER_MSVC
+ #pragma warning ( disable : 4312 )
+ #endif
+ CThreadLocalBase::Set( reinterpret_cast<void *>(val) );
+ #ifdef COMPILER_MSVC
+ #pragma warning ( default : 4312 )
+ #endif
+#endif
+ }
+ };
+
+
+ //---------------------------------------------------------
+
+ template <class T = int32>
+ class CThreadLocalInt : public CThreadLocal<T>
+ {
+ public:
+ operator const T() const { return this->Get(); }
+ int operator=( T i ) { this->Set( i ); return i; }
+
+ T operator++() { T i = this->Get(); this->Set( ++i ); return i; }
+ T operator++(int) { T i = this->Get(); this->Set( i + 1 ); return i; }
+
+ T operator--() { T i = this->Get(); this->Set( --i ); return i; }
+ T operator--(int) { T i = this->Get(); this->Set( i - 1 ); return i; }
+
+ inline CThreadLocalInt( ) { }
+ inline CThreadLocalInt( const T &initialvalue )
+ {
+ this->Set( initialvalue );
+ }
+ };
+
+
+ //---------------------------------------------------------
+
+ template <class T>
+ class CThreadLocalPtr : private CThreadLocalBase
+ {
+ public:
+ CThreadLocalPtr() {}
+
+ operator const void *() const { return (const T *)Get(); }
+ operator void *() { return (T *)Get(); }
+
+ operator const T *() const { return (const T *)Get(); }
+ operator const T *() { return (const T *)Get(); }
+ operator T *() { return (T *)Get(); }
+
+ T * operator=( T *p ) { Set( p ); return p; }
+
+ bool operator !() const { return (!Get()); }
+ bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (Get() != NULL); }
+ bool operator==( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (Get() == NULL); }
+ bool operator==( const void *p ) const { return (Get() == p); }
+ bool operator!=( const void *p ) const { return (Get() != p); }
+ bool operator==( const T *p ) const { return operator==((const void*)p); }
+ bool operator!=( const T *p ) const { return operator!=((const void*)p); }
+
+ T * operator->() { return (T *)Get(); }
+ T & operator *() { return *((T *)Get()); }
+
+ const T * operator->() const { return (const T *)Get(); }
+ const T & operator *() const { return *((const T *)Get()); }
+
+ const T & operator[]( int i ) const { return *((const T *)Get() + i); }
+ T & operator[]( int i ) { return *((T *)Get() + i); }
+
+ private:
+ // Disallowed operations
+ CThreadLocalPtr( T *pFrom );
+ CThreadLocalPtr( const CThreadLocalPtr<T> &from );
+ T **operator &();
+ T * const *operator &() const;
+ void operator=( const CThreadLocalPtr<T> &from );
+ bool operator==( const CThreadLocalPtr<T> &p ) const;
+ bool operator!=( const CThreadLocalPtr<T> &p ) const;
+ };
+}
+
+#ifdef _OSX
+PLATFORM_INTERFACE GenericThreadLocals::CThreadLocalInt<int> g_nThreadID;
+#else // _OSX
+#ifndef TIER0_DLL_EXPORT
+
+#ifndef _PS3
+extern GenericThreadLocals::CThreadLocalInt<int> g_nThreadID;
+#endif // !_PS3
+
+#endif // TIER0_DLL_EXPORT
+#endif // _OSX
+
+#endif /// afx32
+#endif //__win32
+
+#endif // NO_THREAD_LOCAL
+
+//-----------------------------------------------------------------------------
+//
+// A super-fast thread-safe integer A simple class encapsulating the notion of an
+// atomic integer used across threads that uses the built in and faster
+// "interlocked" functionality rather than a full-blown mutex. Useful for simple
+// things like reference counts, etc.
+//
+//-----------------------------------------------------------------------------
+
+template <typename T>
+class CInterlockedIntT
+{
+public:
+ CInterlockedIntT() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T) == sizeof(int32) ); }
+ CInterlockedIntT( T value ) : m_value( value ) {}
+
+ T operator()( void ) const { return m_value; }
+ operator T() const { return m_value; }
+
+ bool operator!() const { return ( m_value == 0 ); }
+ bool operator==( T rhs ) const { return ( m_value == rhs ); }
+ bool operator!=( T rhs ) const { return ( m_value != rhs ); }
+
+ T operator++() { return (T)ThreadInterlockedIncrement( (int32 *)&m_value ); }
+ T operator++(int) { return operator++() - 1; }
+
+ T operator--() { return (T)ThreadInterlockedDecrement( (int32 *)&m_value ); }
+ T operator--(int) { return operator--() + 1; }
+
+ bool AssignIf( T conditionValue, T newValue ) { return ThreadInterlockedAssignIf( (int32 *)&m_value, (int32)newValue, (int32)conditionValue ); }
+
+ T operator=( T newValue ) { ThreadInterlockedExchange((int32 *)&m_value, newValue); return m_value; }
+
+ // Atomic add is like += except it returns the previous value as its return value
+ T AtomicAdd( T add ) { return (T)ThreadInterlockedExchangeAdd( (int32 *)&m_value, (int32)add ); }
+
+ void operator+=( T add ) { ThreadInterlockedExchangeAdd( (int32 *)&m_value, (int32)add ); }
+ void operator-=( T subtract ) { operator+=( -subtract ); }
+ void operator*=( T multiplier ) {
+ T original, result;
+ do
+ {
+ original = m_value;
+ result = original * multiplier;
+ } while ( !AssignIf( original, result ) );
+ }
+ void operator/=( T divisor ) {
+ T original, result;
+ do
+ {
+ original = m_value;
+ result = original / divisor;
+ } while ( !AssignIf( original, result ) );
+ }
+
+ T operator+( T rhs ) const { return m_value + rhs; }
+ T operator-( T rhs ) const { return m_value - rhs; }
+
+private:
+ volatile T m_value;
+};
+
+typedef CInterlockedIntT<int> CInterlockedInt;
+typedef CInterlockedIntT<unsigned> CInterlockedUInt;
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+class CInterlockedPtr
+{
+public:
+ CInterlockedPtr() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T *) == sizeof(int32) ); /* Will need to rework operator+= for 64 bit */ }
+ CInterlockedPtr( T *value ) : m_value( value ) {}
+
+ operator T *() const { return m_value; }
+
+ bool operator!() const { return ( m_value == 0 ); }
+ bool operator==( T *rhs ) const { return ( m_value == rhs ); }
+ bool operator!=( T *rhs ) const { return ( m_value != rhs ); }
+
+ T *operator++() { return ((T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, sizeof(T) )) + 1; }
+ T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, sizeof(T) ); }
+
+ T *operator--() { return ((T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, -sizeof(T) )) - 1; }
+ T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, -sizeof(T) ); }
+
+ bool AssignIf( T *conditionValue, T *newValue ) { return ThreadInterlockedAssignPointerToConstIf( (void const **) &m_value, (void const *) newValue, (void const *) conditionValue ); }
+
+ T *operator=( T *newValue ) { ThreadInterlockedExchangePointerToConst( (void const **) &m_value, (void const *) newValue ); return newValue; }
+
+ void operator+=( int add ) { ThreadInterlockedExchangeAdd( (int32 *)&m_value, add * sizeof(T) ); }
+ void operator-=( int subtract ) { operator+=( -subtract ); }
+
+ // Atomic add is like += except it returns the previous value as its return value
+ T *AtomicAdd( int add ) { return ( T * ) ThreadInterlockedExchangeAdd( (int32 *)&m_value, add * sizeof(T) ); }
+
+ T *operator+( int rhs ) const { return m_value + rhs; }
+ T *operator-( int rhs ) const { return m_value - rhs; }
+ T *operator+( unsigned rhs ) const { return m_value + rhs; }
+ T *operator-( unsigned rhs ) const { return m_value - rhs; }
+ size_t operator-( T *p ) const { return m_value - p; }
+ size_t operator-( const CInterlockedPtr<T> &p ) const { return m_value - p.m_value; }
+
+private:
+ T * volatile m_value;
+};
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Platform independent for critical sections management
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadMutex
+{
+public:
+ CThreadMutex();
+ ~CThreadMutex();
+
+ //------------------------------------------------------
+ // Mutex acquisition/release. Const intentionally defeated.
+ //------------------------------------------------------
+ void Lock();
+ void Lock() const { (const_cast<CThreadMutex *>(this))->Lock(); }
+ void Unlock();
+ void Unlock() const { (const_cast<CThreadMutex *>(this))->Unlock(); }
+
+ bool TryLock();
+ bool TryLock() const { return (const_cast<CThreadMutex *>(this))->TryLock(); }
+
+ void LockSilent(); // A Lock() operation which never spews. Required by the logging system to prevent badness.
+ void UnlockSilent(); // An Unlock() operation which never spews. Required by the logging system to prevent badness.
+
+ //------------------------------------------------------
+ // Use this to make deadlocks easier to track by asserting
+ // when it is expected that the current thread owns the mutex
+ //------------------------------------------------------
+ bool AssertOwnedByCurrentThread();
+
+ //------------------------------------------------------
+ // Enable tracing to track deadlock problems
+ //------------------------------------------------------
+ void SetTrace( bool );
+
+private:
+ // Disallow copying
+ CThreadMutex( const CThreadMutex & );
+ CThreadMutex &operator=( const CThreadMutex & );
+
+#if defined( _WIN32 )
+ // Efficient solution to breaking the windows.h dependency, invariant is tested.
+#ifdef _WIN64
+ #define TT_SIZEOF_CRITICALSECTION 40
+#else
+#ifndef _X360
+ #define TT_SIZEOF_CRITICALSECTION 24
+#else
+ #define TT_SIZEOF_CRITICALSECTION 28
+#endif // !_X360
+#endif // _WIN64
+ byte m_CriticalSection[TT_SIZEOF_CRITICALSECTION];
+#elif defined( _PS3 )
+ sys_mutex_t m_Mutex;
+#elif defined(POSIX)
+ pthread_mutex_t m_Mutex;
+ pthread_mutexattr_t m_Attr;
+#else
+#error
+#endif
+
+#ifdef THREAD_MUTEX_TRACING_SUPPORTED
+ // Debugging (always herge to allow mixed debug/release builds w/o changing size)
+ uint m_currentOwnerID;
+ uint16 m_lockCount;
+ bool m_bTrace;
+#endif
+};
+
+//-----------------------------------------------------------------------------
+//
+// An alternative mutex that is useful for cases when thread contention is
+// rare, but a mutex is required. Instances should be declared volatile.
+// Sleep of 0 may not be sufficient to keep high priority threads from starving
+// lesser threads. This class is not a suitable replacement for a critical
+// section if the resource contention is high.
+//
+//-----------------------------------------------------------------------------
+
+#if !defined(THREAD_PROFILER)
+
+class CThreadFastMutex
+{
+public:
+ CThreadFastMutex()
+ : m_ownerID( 0 ),
+ m_depth( 0 )
+ {
+ }
+
+private:
+ FORCEINLINE bool TryLockInline( const uint32 threadId ) volatile
+ {
+ if ( threadId != m_ownerID && !ThreadInterlockedAssignIf( (volatile int32 *)&m_ownerID, (int32)threadId, 0 ) )
+ return false;
+
+ ThreadMemoryBarrier();
+ ++m_depth;
+ return true;
+ }
+
+ bool TryLock( const uint32 threadId ) volatile
+ {
+ return TryLockInline( threadId );
+ }
+
+ PLATFORM_CLASS void Lock( const uint32 threadId, unsigned nSpinSleepTime ) volatile;
+
+public:
+ bool TryLock() volatile
+ {
+#ifdef _DEBUG
+ if ( m_depth == INT_MAX )
+ DebuggerBreak();
+
+ if ( m_depth < 0 )
+ DebuggerBreak();
+#endif
+ return TryLockInline( ThreadGetCurrentId() );
+ }
+
+#ifndef _DEBUG
+ FORCEINLINE
+#endif
+ void Lock( unsigned int nSpinSleepTime = 0 ) volatile
+ {
+ const uint32 threadId = ThreadGetCurrentId();
+
+ if ( !TryLockInline( threadId ) )
+ {
+ ThreadPause();
+ Lock( threadId, nSpinSleepTime );
+ }
+#ifdef _DEBUG
+ if ( m_ownerID != ThreadGetCurrentId() )
+ DebuggerBreak();
+
+ if ( m_depth == INT_MAX )
+ DebuggerBreak();
+
+ if ( m_depth < 0 )
+ DebuggerBreak();
+#endif
+ }
+
+#ifndef _DEBUG
+ FORCEINLINE
+#endif
+ void Unlock() volatile
+ {
+#ifdef _DEBUG
+ if ( m_ownerID != ThreadGetCurrentId() )
+ DebuggerBreak();
+
+ if ( m_depth <= 0 )
+ DebuggerBreak();
+#endif
+
+ --m_depth;
+ if ( !m_depth )
+ {
+ ThreadMemoryBarrier();
+ ThreadInterlockedExchange( &m_ownerID, 0 );
+ }
+ }
+
+ bool TryLock() const volatile { return (const_cast<CThreadFastMutex *>(this))->TryLock(); }
+ void Lock(unsigned nSpinSleepTime = 0 ) const volatile { (const_cast<CThreadFastMutex *>(this))->Lock( nSpinSleepTime ); }
+ void Unlock() const volatile { (const_cast<CThreadFastMutex *>(this))->Unlock(); }
+
+ // To match regular CThreadMutex:
+ bool AssertOwnedByCurrentThread() { return true; }
+ void SetTrace( bool ) {}
+
+ uint32 GetOwnerId() const { return m_ownerID; }
+ int GetDepth() const { return m_depth; }
+private:
+ volatile uint32 m_ownerID;
+ int m_depth;
+};
+
+class ALIGN128 CAlignedThreadFastMutex : public CThreadFastMutex
+{
+public:
+ CAlignedThreadFastMutex()
+ {
+ Assert( (size_t)this % 128 == 0 && sizeof(*this) == 128 );
+ }
+
+private:
+ uint8 pad[128-sizeof(CThreadFastMutex)];
+};
+
+#else
+#ifdef _PS3
+
+class CThreadFastMutex
+{
+public:
+ CThreadFastMutex();
+ ~CThreadFastMutex();
+
+ //------------------------------------------------------
+ // Mutex acquisition/release. Const intentionally defeated.
+ //------------------------------------------------------
+ void Lock();
+ void Lock() const { (const_cast<CThreadFastMutex *>(this))->Lock(); }
+ void Unlock();
+ void Unlock() const { (const_cast<CThreadFastMutex *>(this))->Unlock(); }
+
+ bool TryLock();
+ bool TryLock() const { return (const_cast<CThreadFastMutex *>(this))->TryLock(); }
+
+ //------------------------------------------------------
+ // Use this to make deadlocks easier to track by asserting
+ // when it is expected that the current thread owns the mutex
+ //------------------------------------------------------
+ bool AssertOwnedByCurrentThread();
+
+ //------------------------------------------------------
+ // Enable tracing to track deadlock problems
+ //------------------------------------------------------
+ void SetTrace( bool );
+
+private:
+ // Disallow copying
+ CThreadFastMutex( const CThreadFastMutex & );
+ //CThreadFastMutex &operator=( const CThreadFastMutex & );
+ sys_lwmutex_t m_Mutex;
+ sys_mutex_t m_SlowMutex;
+};
+
+#else
+
+typedef CThreadMutex CThreadFastMutex;
+
+#endif
+
+class ALIGN128 CAlignedThreadFastMutex : public CThreadFastMutex
+{
+public:
+ CAlignedThreadFastMutex()
+ {
+ Assert( (size_t)this % 128 == 0 && sizeof(*this) == 128 );
+ }
+
+private:
+ uint8 pad[128-sizeof(CThreadFastMutex)];
+};
+
+#endif
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+class CThreadNullMutex
+{
+public:
+ static void Lock() {}
+ static void Unlock() {}
+
+ static bool TryLock() { return true; }
+ static bool AssertOwnedByCurrentThread() { return true; }
+ static void SetTrace( bool b ) {}
+
+ static uint32 GetOwnerId() { return 0; }
+ static int GetDepth() { return 0; }
+};
+
+//-----------------------------------------------------------------------------
+//
+// A mutex decorator class used to control the use of a mutex, to make it
+// less expensive when not multithreading
+//
+//-----------------------------------------------------------------------------
+
+template <class BaseClass, bool *pCondition>
+class CThreadConditionalMutex : public BaseClass
+{
+public:
+ void Lock() { if ( *pCondition ) BaseClass::Lock(); }
+ void Lock() const { if ( *pCondition ) BaseClass::Lock(); }
+ void Unlock() { if ( *pCondition ) BaseClass::Unlock(); }
+ void Unlock() const { if ( *pCondition ) BaseClass::Unlock(); }
+
+ bool TryLock() { if ( *pCondition ) return BaseClass::TryLock(); else return true; }
+ bool TryLock() const { if ( *pCondition ) return BaseClass::TryLock(); else return true; }
+ bool AssertOwnedByCurrentThread() { if ( *pCondition ) return BaseClass::AssertOwnedByCurrentThread(); else return true; }
+ void SetTrace( bool b ) { if ( *pCondition ) BaseClass::SetTrace( b ); }
+};
+
+//-----------------------------------------------------------------------------
+// Mutex decorator that blows up if another thread enters
+//-----------------------------------------------------------------------------
+
+template <class BaseClass>
+class CThreadTerminalMutex : public BaseClass
+{
+public:
+ bool TryLock() { if ( !BaseClass::TryLock() ) { DebuggerBreak(); return false; } return true; }
+ bool TryLock() const { if ( !BaseClass::TryLock() ) { DebuggerBreak(); return false; } return true; }
+ void Lock() { if ( !TryLock() ) BaseClass::Lock(); }
+ void Lock() const { if ( !TryLock() ) BaseClass::Lock(); }
+
+};
+
+//-----------------------------------------------------------------------------
+//
+// Class to Lock a critical section, and unlock it automatically
+// when the lock goes out of scope
+//
+//-----------------------------------------------------------------------------
+
+template <class MUTEX_TYPE = CThreadMutex>
+class CAutoLockT
+{
+public:
+ FORCEINLINE CAutoLockT( MUTEX_TYPE &lock)
+ : m_lock(lock)
+ {
+ m_lock.Lock();
+ }
+
+ FORCEINLINE CAutoLockT(const MUTEX_TYPE &lock)
+ : m_lock(const_cast<MUTEX_TYPE &>(lock))
+ {
+ m_lock.Lock();
+ }
+
+ FORCEINLINE ~CAutoLockT()
+ {
+ m_lock.Unlock();
+ }
+
+
+private:
+ MUTEX_TYPE &m_lock;
+
+ // Disallow copying
+ CAutoLockT<MUTEX_TYPE>( const CAutoLockT<MUTEX_TYPE> & );
+ CAutoLockT<MUTEX_TYPE> &operator=( const CAutoLockT<MUTEX_TYPE> & );
+};
+
+typedef CAutoLockT<CThreadMutex> CAutoLock;
+
+//---------------------------------------------------------
+
+template <int size> struct CAutoLockTypeDeducer {};
+template <> struct CAutoLockTypeDeducer<sizeof(CThreadMutex)> { typedef CThreadMutex Type_t; };
+template <> struct CAutoLockTypeDeducer<sizeof(CThreadNullMutex)> { typedef CThreadNullMutex Type_t; };
+#if !defined(THREAD_PROFILER)
+template <> struct CAutoLockTypeDeducer<sizeof(CThreadFastMutex)> { typedef CThreadFastMutex Type_t; };
+template <> struct CAutoLockTypeDeducer<sizeof(CAlignedThreadFastMutex)> { typedef CAlignedThreadFastMutex Type_t; };
+#else
+template <> struct CAutoLockTypeDeducer<sizeof(CAlignedThreadFastMutex)> { typedef CAlignedThreadFastMutex Type_t; };
+#endif
+
+
+#ifdef MSVC
+#define AUTO_LOCK_( type, mutex ) \
+ CAutoLockT< typename type > UNIQUE_ID( static_cast<const type &>( mutex ) )
+#else
+// clang requires
+#define AUTO_LOCK_( type, mutex ) \
+ CAutoLockT< typename type > UNIQUE_ID( static_cast<const typename type &>( mutex ) )
+#endif
+
+#define AUTO_LOCK( mutex ) \
+ AUTO_LOCK_( CAutoLockTypeDeducer<sizeof(mutex)>::Type_t, mutex )
+
+
+#define AUTO_LOCK_FM( mutex ) \
+ AUTO_LOCK_( CAutoLockTypeDeducer<sizeof(CThreadFastMutex)>::Type_t, mutex )
+
+#define LOCAL_THREAD_LOCK_( tag ) \
+ ; \
+ static CThreadFastMutex autoMutex_##tag; \
+ AUTO_LOCK( autoMutex_##tag )
+
+#define LOCAL_THREAD_LOCK() \
+ LOCAL_THREAD_LOCK_(_)
+
+//-----------------------------------------------------------------------------
+//
+// Base class for event, semaphore and mutex objects.
+//
+//-----------------------------------------------------------------------------
+
+// TW_TIMEOUT must match WAIT_TIMEOUT definition
+#define TW_TIMEOUT 0x00000102
+// TW_FAILED must match WAIT_FAILED definition
+#define TW_FAILED 0xFFFFFFFF
+
+class PLATFORM_CLASS CThreadSyncObject
+{
+public:
+ ~CThreadSyncObject();
+
+ //-----------------------------------------------------
+ // Query if object is useful
+ //-----------------------------------------------------
+ bool operator!() const;
+
+ //-----------------------------------------------------
+ // Access handle
+ //-----------------------------------------------------
+#ifdef _WIN32
+ operator HANDLE() { return GetHandle(); }
+ const HANDLE GetHandle() const { return m_hSyncObject; }
+#endif
+ //-----------------------------------------------------
+ // Wait for a signal from the object
+ //-----------------------------------------------------
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+ //-----------------------------------------------------
+ // Wait for a signal from any of the specified objects.
+ //
+ // Returns the index of the object that signaled the event
+ // or THREADSYNC_TIMEOUT if the timeout was hit before the wait condition was met.
+ //
+ // Returns TW_FAILED if an incoming object is invalid.
+ //
+ // If bWaitAll=true, then it'll return 0 if all the objects were set.
+ //-----------------------------------------------------
+ static uint32 WaitForMultiple( int nObjects, CThreadSyncObject **ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+
+ // This builds a list of pointers and calls straight through to the other WaitForMultiple.
+ static uint32 WaitForMultiple( int nObjects, CThreadSyncObject *ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+
+protected:
+ CThreadSyncObject();
+ void AssertUseable();
+
+#ifdef _WIN32
+ HANDLE m_hSyncObject;
+ bool m_bCreatedHandle;
+#elif defined( _PS3 )
+ static sys_lwmutex_t m_staticMutex;
+ static uint32_t m_bstaticMutexInitialized;
+ static uint32_t m_bstaticMutexInitializing;
+#elif defined(POSIX)
+ pthread_mutex_t m_Mutex;
+ pthread_cond_t m_Condition;
+ bool m_bInitalized;
+ int m_cSet;
+ bool m_bManualReset;
+ bool m_bWakeForEvent;
+#else
+#error "Implement me"
+#endif
+
+private:
+ CThreadSyncObject( const CThreadSyncObject & );
+ CThreadSyncObject &operator=( const CThreadSyncObject & );
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// Wrapper for unnamed event objects
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSemaphore
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadSemaphore : public CThreadSyncObject
+{
+public:
+ CThreadSemaphore(int32 initialValue, int32 maxValue);
+
+ //-----------------------------------------------------
+ // Increases the count of the semaphore object by a specified
+ // amount. Wait() decreases the count by one on return.
+ //-----------------------------------------------------
+ bool Release(int32 releaseCount = 1, int32 * pPreviousCount = NULL );
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+private:
+ CThreadSemaphore(const CThreadSemaphore &);
+ CThreadSemaphore &operator=(const CThreadSemaphore &);
+#ifdef _PS3
+ bool AddWaitingThread();
+ void RemoveWaitingThread();
+ sys_semaphore_t m_Semaphore;
+ sys_semaphore_value_t m_sema_max_val;
+ uint32_t m_numWaitingThread;
+ uint32_t m_bInitalized;
+ uint32_t m_semaCount;
+#endif
+};
+
+#if defined( _WIN32 )
+
+//-----------------------------------------------------------------------------
+//
+// A mutex suitable for out-of-process, multi-processor usage
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadFullMutex : public CThreadSyncObject
+{
+public:
+ CThreadFullMutex( bool bEstablishInitialOwnership = false, const char * pszName = NULL );
+
+ //-----------------------------------------------------
+ // Release ownership of the mutex
+ //-----------------------------------------------------
+ bool Release();
+
+ // To match regular CThreadMutex:
+ void Lock() { Wait(); }
+ void Lock( unsigned timeout ) { Wait( timeout ); }
+ void Unlock() { Release(); }
+ bool AssertOwnedByCurrentThread() { return true; }
+ void SetTrace( bool ) {}
+
+private:
+ CThreadFullMutex( const CThreadFullMutex & );
+ CThreadFullMutex &operator=( const CThreadFullMutex & );
+};
+#endif
+
+enum NamedEventResult_t
+{
+ TT_EventDoesntExist = 0,
+ TT_EventNotSignaled,
+ TT_EventSignaled
+};
+#if defined( _PS3 )
+//---------------------------------------------------------------------------
+// CThreadEventWaitObject - the purpose of this class is to help implement
+// WaitForMultipleObejcts on PS3.
+//
+// Each event maintains a linked list of CThreadEventWaitObjects. When a
+// thread wants to wait on an event it passes the event a semaphore that
+// ptr to see the index of the event that triggered it
+//
+// The thread-specific mutex is to ensure that setting the index and setting the
+// semaphore are atomic
+//---------------------------------------------------------------------------
+
+class CThreadEventWaitObject
+{
+public:
+ CThreadEventWaitObject *m_pPrev, *m_pNext;
+ sys_semaphore_t *m_pSemaphore;
+ int m_index;
+ int *m_pFlag;
+
+ CThreadEventWaitObject() {}
+
+ void Init(sys_semaphore_t *pSem, int index, int *pFlag)
+ {
+ m_pSemaphore = pSem;
+ m_index = index;
+ m_pFlag = pFlag;
+ }
+
+ void Set();
+};
+#endif //_PS3
+
+class PLATFORM_CLASS CThreadEvent : public CThreadSyncObject
+{
+public:
+ CThreadEvent( bool fManualReset = false );
+#ifdef PLATFORM_WINDOWS
+ CThreadEvent( const char *name, bool initialState = false, bool bManualReset = false );
+ static NamedEventResult_t CheckNamedEvent( const char *name, uint32 dwTimeout = 0 );
+
+ CThreadEvent( HANDLE hHandle );
+#endif
+ //-----------------------------------------------------
+ // Set the state to signaled
+ //-----------------------------------------------------
+ bool Set();
+
+ //-----------------------------------------------------
+ // Set the state to nonsignaled
+ //-----------------------------------------------------
+ bool Reset();
+
+ //-----------------------------------------------------
+ // Check if the event is signaled
+ //-----------------------------------------------------
+ bool Check(); // Please, use for debugging only!
+
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+ // See CThreadSyncObject for definitions of these functions.
+ static uint32 WaitForMultiple( int nObjects, CThreadEvent **ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+ // To implement these, I need to check that casts are safe
+ static uint32 WaitForMultiple( int nObjects, CThreadEvent *ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+
+#ifdef _PS3
+ void RegisterWaitingThread(sys_semaphore_t *pSemaphore, int index, int *flag);
+ void UnregisterWaitingThread(sys_semaphore_t *pSemaphore);
+#endif
+
+protected:
+#ifdef _PS3
+ // These virtual functions need to be inline in order for the class to be exported from tier0.prx
+ virtual bool AddWaitingThread()
+ {
+ //This checks if the event is already signaled and if not creates a semaphore which will be signaled
+ //when the event is finally signaled.
+ bool result;
+
+ sys_lwmutex_lock(&m_staticMutex, 0);
+
+ if (m_bSet)
+ result=false;
+ else
+ {
+ result=true;
+
+ m_numWaitingThread++;
+
+ if ( m_numWaitingThread == 1 )
+ {
+ sys_semaphore_attribute_t semAttr;
+ sys_semaphore_attribute_initialize( semAttr );
+ int err = sys_semaphore_create( &m_Semaphore, &semAttr, 0, 256 );
+ Assert( err == CELL_OK );
+ m_bInitalized = true;
+ }
+ }
+
+ sys_lwmutex_unlock(&m_staticMutex);
+ return result;
+ }
+
+ virtual void RemoveWaitingThread()
+ {
+ sys_lwmutex_lock(&m_staticMutex, 0);
+
+ m_numWaitingThread--;
+
+ if ( m_numWaitingThread == 0)
+ {
+ int err = sys_semaphore_destroy( m_Semaphore );
+ Assert( err == CELL_OK );
+ m_bInitalized = false;
+ }
+
+ sys_lwmutex_unlock(&m_staticMutex);
+ }
+#endif
+private:
+ CThreadEvent( const CThreadEvent & );
+ CThreadEvent &operator=( const CThreadEvent & );
+#if defined( _PS3 )
+ uint32_t m_bSet;
+ bool m_bManualReset;
+
+ sys_semaphore_t m_Semaphore;
+ uint32_t m_numWaitingThread;
+ uint32_t m_bInitalized;
+
+ CThreadEventWaitObject m_waitObjects[CTHREADEVENT_MAX_WAITING_THREADS+2];
+ CThreadEventWaitObject *m_pWaitObjectsPool;
+ CThreadEventWaitObject *m_pWaitObjectsList;
+
+ CThreadEventWaitObject* LLUnlinkNode(CThreadEventWaitObject *node);
+ CThreadEventWaitObject* LLLinkNode(CThreadEventWaitObject* list, CThreadEventWaitObject *node);
+
+#endif
+};
+
+// Hard-wired manual event for use in array declarations
+class CThreadManualEvent : public CThreadEvent
+{
+public:
+ CThreadManualEvent()
+ : CThreadEvent( true )
+ {
+ }
+};
+
+PLATFORM_INTERFACE int ThreadWaitForObjects( int nEvents, const HANDLE *pHandles, bool bWaitAll = true, unsigned timeout = TT_INFINITE );
+inline int ThreadWaitForEvents( int nEvents, const CThreadEvent *pEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) { return ThreadWaitForObjects( nEvents, (const HANDLE *)pEvents, bWaitAll, timeout ); }
+
+//-----------------------------------------------------------------------------
+//
+// CThreadRWLock
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadRWLock
+{
+public:
+ CThreadRWLock();
+
+ void LockForRead();
+ void UnlockRead();
+ void LockForWrite();
+ void UnlockWrite();
+
+ void LockForRead() const { const_cast<CThreadRWLock *>(this)->LockForRead(); }
+ void UnlockRead() const { const_cast<CThreadRWLock *>(this)->UnlockRead(); }
+ void LockForWrite() const { const_cast<CThreadRWLock *>(this)->LockForWrite(); }
+ void UnlockWrite() const { const_cast<CThreadRWLock *>(this)->UnlockWrite(); }
+
+private:
+ void WaitForRead();
+
+#ifdef WIN32
+ CThreadFastMutex m_mutex;
+#else
+ CThreadMutex m_mutex;
+#endif
+ CThreadEvent m_CanWrite;
+ CThreadEvent m_CanRead;
+
+ int m_nWriters;
+ int m_nActiveReaders;
+ int m_nPendingReaders;
+};
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSpinRWLock
+//
+//-----------------------------------------------------------------------------
+
+#ifndef OLD_SPINRWLOCK
+class ALIGN8 PLATFORM_CLASS CThreadSpinRWLock
+{
+public:
+ CThreadSpinRWLock()
+ {
+ m_lockInfo.m_i32 = 0;
+ m_writerId = 0;
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ m_iWriteDepth = 0;
+#endif
+ }
+
+ bool IsLockedForWrite();
+ bool IsLockedForRead();
+
+ FORCEINLINE bool TryLockForWrite();
+ bool TryLockForWrite_UnforcedInline();
+
+ void LockForWrite();
+ void SpinLockForWrite();
+
+ FORCEINLINE bool TryLockForRead();
+ bool TryLockForRead_UnforcedInline();
+
+ void LockForRead();
+ void SpinLockForRead();
+
+ void UnlockWrite();
+ void UnlockRead();
+
+ bool TryLockForWrite() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForWrite(); }
+ bool TryLockForRead() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForRead(); }
+ void LockForRead() const { const_cast<CThreadSpinRWLock *>(this)->LockForRead(); }
+ void UnlockRead() const { const_cast<CThreadSpinRWLock *>(this)->UnlockRead(); }
+ void LockForWrite() const { const_cast<CThreadSpinRWLock *>(this)->LockForWrite(); }
+ void UnlockWrite() const { const_cast<CThreadSpinRWLock *>(this)->UnlockWrite(); }
+
+private:
+ enum
+ {
+ THREAD_SPIN = (8*1024)
+ };
+
+ union LockInfo_t
+ {
+ struct
+ {
+#if PLAT_LITTLE_ENDIAN
+ uint16 m_nReaders;
+ uint16 m_fWriting;
+#else
+ uint16 m_fWriting;
+ uint16 m_nReaders;
+#endif
+ };
+ uint32 m_i32;
+ };
+
+ LockInfo_t m_lockInfo;
+ uint32 m_writerId;
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ int m_iWriteDepth;
+ uint32 pad;
+#endif
+} ALIGN8_POST;
+
+#else
+
+/* (commented out to reduce distraction in colorized editor, remove entirely when new implementation settles)
+class ALIGN8 PLATFORM_CLASS CThreadSpinRWLock
+{
+public:
+ CThreadSpinRWLock() { COMPILE_TIME_ASSERT( sizeof( LockInfo_t ) == sizeof( int64 ) ); Assert( (intp)this % 8 == 0 ); memset( this, 0, sizeof( *this ) ); }
+
+ bool TryLockForWrite();
+ bool TryLockForRead();
+
+ void LockForRead();
+ void UnlockRead();
+ void LockForWrite();
+ void UnlockWrite();
+
+ bool TryLockForWrite() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForWrite(); }
+ bool TryLockForRead() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForRead(); }
+ void LockForRead() const { const_cast<CThreadSpinRWLock *>(this)->LockForRead(); }
+ void UnlockRead() const { const_cast<CThreadSpinRWLock *>(this)->UnlockRead(); }
+ void LockForWrite() const { const_cast<CThreadSpinRWLock *>(this)->LockForWrite(); }
+ void UnlockWrite() const { const_cast<CThreadSpinRWLock *>(this)->UnlockWrite(); }
+
+private:
+ // This structure is used as an atomic & exchangeable 64-bit value. It would probably be better to just have one 64-bit value
+ // and accessor functions that make/break it, but at this late stage of development, I'm just wrapping it into union
+ // Beware of endianness: on Xbox/PowerPC m_writerId is high-word of m_i64; on PC, it's low-dword of m_i64
+ union LockInfo_t
+ {
+ struct
+ {
+ uint32 m_writerId;
+ int m_nReaders;
+ };
+ int64 m_i64;
+ };
+
+ bool AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand );
+ bool TryLockForWrite( const uint32 threadId );
+ void SpinLockForWrite( const uint32 threadId );
+
+ volatile LockInfo_t m_lockInfo;
+ CInterlockedInt m_nWriters;
+} ALIGN8_POST;
+*/
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// A thread wrapper similar to a Java thread.
+//
+//-----------------------------------------------------------------------------
+#ifdef _PS3
+// Everything must be inline for this to work across PRX boundaries
+
+class CThread;
+PLATFORM_INTERFACE CThread *GetCurThreadPS3();
+PLATFORM_INTERFACE void SetCurThreadPS3( CThread * );
+PLATFORM_INTERFACE void AllocateThreadID( void );
+PLATFORM_INTERFACE void FreeThreadID( void );
+#endif
+
+class PLATFORM_CLASS CThread
+{
+public:
+ CThread();
+ virtual ~CThread();
+
+ //-----------------------------------------------------
+
+ const char *GetName();
+ void SetName( const char *pszName );
+
+ size_t CalcStackDepth( void *pStackVariable ) { return ((byte *)m_pStackBase - (byte *)pStackVariable); }
+
+ //-----------------------------------------------------
+ // Functions for the other threads
+ //-----------------------------------------------------
+
+ // Start thread running - error if already running
+ enum ThreadPriorityEnum_t
+ {
+#ifdef _PS3
+ PRIORITY_NORMAL = 1001,
+ PRIORITY_HIGH = 100,
+ PRIORITY_LOW = 2001,
+ PRIORITY_DEFAULT = 1001
+#else
+ PRIORITY_DEFAULT = 0,//THREAD_PRIORITY_NORMAL,
+ PRIORITY_NORMAL = 0,//THREAD_PRIORITY_NORMAL,
+ PRIORITY_HIGH = 1,//THREAD_PRIORITY_ABOVE_NORMAL,
+ PRIORITY_LOW = -1//THREAD_PRIORITY_BELOW_NORMAL
+#endif
+ };
+ virtual bool Start( unsigned nBytesStack = 0, ThreadPriorityEnum_t nPriority = PRIORITY_DEFAULT );
+
+ // Returns true if thread has been created and hasn't yet exited
+ bool IsAlive();
+
+ // This method causes the current thread to wait until this thread
+ // is no longer alive.
+ bool Join( unsigned timeout = TT_INFINITE );
+
+ // Access the thread handle directly
+ ThreadHandle_t GetThreadHandle();
+
+#ifdef _WIN32
+ uint GetThreadId();
+#endif
+
+ //-----------------------------------------------------
+
+ int GetResult();
+
+ //-----------------------------------------------------
+ // Functions for both this, and maybe, and other threads
+ //-----------------------------------------------------
+
+ // Forcibly, abnormally, but relatively cleanly stop the thread
+ void Stop( int exitCode = 0 );
+
+ // Get the priority
+ int GetPriority() const;
+
+ // Set the priority
+ bool SetPriority( int priority );
+
+ // Suspend a thread, can only call from the thread itself
+ unsigned Suspend();
+
+ // Resume a suspended thread
+ unsigned Resume();
+
+ // Check if thread is suspended
+ bool IsSuspended() { return !m_NotSuspendedEvent.Check(); }
+
+ // Force hard-termination of thread. Used for critical failures.
+ bool Terminate( int exitCode = 0 );
+
+ //-----------------------------------------------------
+ // Global methods
+ //-----------------------------------------------------
+
+ // Get the Thread object that represents the current thread, if any.
+ // Can return NULL if the current thread was not created using
+ // CThread
+ static CThread *GetCurrentCThread();
+
+ // Offer a context switch. Under Win32, equivalent to Sleep(0)
+#ifdef Yield
+#undef Yield
+#endif
+ static void Yield();
+
+ // This method causes the current thread to yield and not to be
+ // scheduled for further execution until a certain amount of real
+ // time has elapsed, more or less. Duration is in milliseconds
+ static void Sleep( unsigned duration );
+
+protected:
+
+ // Optional pre-run call, with ability to fail-create. Note Init()
+ // is forced synchronous with Start()
+ virtual bool Init();
+
+ // Thread will run this function on startup, must be supplied by
+ // derived class, performs the intended action of the thread.
+ virtual int Run() = 0;
+
+ // Called when the thread exits
+ virtual void OnExit();
+
+ // Allow for custom start waiting
+ virtual bool WaitForCreateComplete( CThreadEvent *pEvent );
+ const ThreadId_t GetThreadID() const { return (ThreadId_t)m_threadId; }
+
+#ifdef PLATFORM_WINDOWS
+ const ThreadHandle_t GetThreadHandle() const { return (ThreadHandle_t)m_hThread; }
+
+ static unsigned long __stdcall ThreadProc( void * pv );
+ typedef unsigned long (__stdcall *ThreadProc_t)( void * );
+#else
+ static void* ThreadProc( void * pv );
+ typedef void* (*ThreadProc_t)( void * pv );
+#endif
+
+ virtual ThreadProc_t GetThreadProc();
+ CThreadMutex m_Lock;
+ CThreadEvent m_ExitEvent; // Set right before the thread's function exits.
+
+private:
+ enum Flags
+ {
+ SUPPORT_STOP_PROTOCOL = 1 << 0
+ };
+
+ // Thread initially runs this. param is actually 'this'. function
+ // just gets this and calls ThreadProc
+ struct ThreadInit_t
+ {
+ CThread * pThread;
+ CThreadEvent *pInitCompleteEvent;
+ bool * pfInitSuccess;
+#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
+ void * ParentStackTrace[THREAD_PARENT_STACK_TRACE_LENGTH];
+#endif
+ };
+
+ // make copy constructor and assignment operator inaccessible
+ CThread( const CThread & );
+ CThread &operator=( const CThread & );
+
+#ifdef _WIN32
+ HANDLE m_hThread;
+ ThreadId_t m_threadId;
+#elif defined( _PS3 )
+ sys_ppu_thread_t m_threadId;
+ volatile sys_ppu_thread_t m_threadZombieId;
+
+ // Mutex and condition variable used by the Suspend / Resume logic
+ sys_mutex_t m_mutexSuspend;
+ sys_cond_t m_condSuspend;
+
+ //EAPS3 Event to indicate that a thread has terminated. This helps with the replacing of WaitForMultipleObjects
+ // on the PS3, since it waits for a thread to finish.
+ CThreadEvent m_threadEnd;
+#elif defined(_POSIX)
+ pthread_t m_threadId;
+ volatile pthread_t m_threadZombieId;
+#endif
+ int m_result;
+ char m_szName[32];
+ void * m_pStackBase;
+ unsigned m_flags;
+ CThreadManualEvent m_NotSuspendedEvent;
+};
+
+// The CThread implementation needs to be inlined for performance on the PS3 - It makes a difference of more than 1ms/frame
+// Since the dependency checker isn't smart enough to take an #ifdef _PS3 into account, all platforms will inline it.
+#ifdef _PS3
+#include "threadtools.inl"
+#endif
+
+//-----------------------------------------------------------------------------
+// Simple thread class encompasses the notion of a worker thread, handing
+// synchronized communication.
+//-----------------------------------------------------------------------------
+
+// These are internal reserved error results from a call attempt
+enum WTCallResult_t
+{
+ WTCR_FAIL = -1,
+ WTCR_TIMEOUT = -2,
+ WTCR_THREAD_GONE = -3,
+};
+
+class PLATFORM_CLASS CWorkerThread : public CThread
+{
+public:
+ CWorkerThread();
+
+ //-----------------------------------------------------
+ //
+ // Inter-thread communication
+ //
+ // Calls in either direction take place on the same "channel."
+ // Seperate functions are specified to make identities obvious
+ //
+ //-----------------------------------------------------
+
+ // Master: Signal the thread, and block for a response
+ int CallWorker( unsigned, unsigned timeout = TT_INFINITE, bool fBoostWorkerPriorityToMaster = true );
+
+ // Worker: Signal the thread, and block for a response
+ int CallMaster( unsigned, unsigned timeout = TT_INFINITE );
+
+ // Wait for the next request
+ bool WaitForCall( unsigned dwTimeout, unsigned *pResult = NULL );
+ bool WaitForCall( unsigned *pResult = NULL );
+
+ // Is there a request?
+ bool PeekCall( unsigned *pParam = NULL );
+
+ // Reply to the request
+ void Reply( unsigned );
+
+ // Wait for a reply in the case when CallWorker() with timeout != TT_INFINITE
+ int WaitForReply( unsigned timeout = TT_INFINITE );
+
+ // If you want to do WaitForMultipleObjects you'll need to include
+ // this handle in your wait list or you won't be responsive
+ CThreadEvent& GetCallHandle(); // (returns m_EventSend)
+
+ // Find out what the request was
+ unsigned GetCallParam() const;
+
+ // Boost the worker thread to the master thread, if worker thread is lesser, return old priority
+ int BoostPriority();
+
+protected:
+ typedef uint32 ( *WaitFunc_t)( uint32 nHandles, CThreadEvent** ppHandles, int bWaitAll, uint32 timeout );
+ int Call( unsigned, unsigned timeout, bool fBoost, WaitFunc_t = NULL );
+ int WaitForReply( unsigned timeout, WaitFunc_t );
+
+private:
+ CWorkerThread( const CWorkerThread & );
+ CWorkerThread &operator=( const CWorkerThread & );
+
+ CThreadEvent m_EventSend;
+ CThreadEvent m_EventComplete;
+
+ unsigned m_Param;
+ int m_ReturnVal;
+};
+
+
+// a unidirectional message queue. A queue of type T. Not especially high speed since each message
+// is malloced/freed. Note that if your message class has destructors/constructors, they MUST be
+// thread safe!
+template<class T> class CMessageQueue
+{
+ CThreadEvent SignalEvent; // signals presence of data
+ CThreadMutex QueueAccessMutex;
+
+ // the parts protected by the mutex
+ struct MsgNode
+ {
+ MsgNode *Next;
+ T Data;
+ };
+
+ MsgNode *Head;
+ MsgNode *Tail;
+
+public:
+ CMessageQueue( void )
+ {
+ Head = Tail = NULL;
+ }
+
+ // check for a message. not 100% reliable - someone could grab the message first
+ bool MessageWaiting( void )
+ {
+ return ( Head != NULL );
+ }
+
+ void WaitMessage( T *pMsg )
+ {
+ for(;;)
+ {
+ while( ! MessageWaiting() )
+ SignalEvent.Wait();
+ QueueAccessMutex.Lock();
+ if (! Head )
+ {
+ // multiple readers could make this null
+ QueueAccessMutex.Unlock();
+ continue;
+ }
+ *( pMsg ) = Head->Data;
+ MsgNode *remove_this = Head;
+ Head = Head->Next;
+ if (! Head) // if empty, fix tail ptr
+ Tail = NULL;
+ QueueAccessMutex.Unlock();
+ delete remove_this;
+ break;
+ }
+ }
+
+ void QueueMessage( T const &Msg)
+ {
+ MsgNode *new1=new MsgNode;
+ new1->Data=Msg;
+ new1->Next=NULL;
+ QueueAccessMutex.Lock();
+ if ( Tail )
+ {
+ Tail->Next=new1;
+ Tail = new1;
+ }
+ else
+ {
+ Head = new1;
+ Tail = new1;
+ }
+ SignalEvent.Set();
+ QueueAccessMutex.Unlock();
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// CThreadMutex. Inlining to reduce overhead and to allow client code
+// to decide debug status (tracing)
+//
+//-----------------------------------------------------------------------------
+
+#ifdef MSVC
+typedef struct _RTL_CRITICAL_SECTION RTL_CRITICAL_SECTION;
+typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
+
+#ifndef _X360
+extern "C"
+{
+ void __declspec(dllimport) __stdcall InitializeCriticalSection(CRITICAL_SECTION *);
+ void __declspec(dllimport) __stdcall EnterCriticalSection(CRITICAL_SECTION *);
+ void __declspec(dllimport) __stdcall LeaveCriticalSection(CRITICAL_SECTION *);
+ void __declspec(dllimport) __stdcall DeleteCriticalSection(CRITICAL_SECTION *);
+};
+#endif
+#endif
+
+//---------------------------------------------------------
+#if !defined(POSIX) || defined( _GAMECONSOLE )
+
+inline void CThreadMutex::Lock()
+{
+#if defined(_PS3)
+ #ifndef NO_THREAD_SYNC
+ sys_mutex_lock( m_Mutex, 0 );
+ #endif
+#else
+ #if defined( THREAD_MUTEX_TRACING_ENABLED )
+ uint thisThreadID = ThreadGetCurrentId();
+ if ( m_bTrace && m_currentOwnerID && ( m_currentOwnerID != thisThreadID ) )
+ Msg( _T( "Thread %u about to wait for lock %x owned by %u\n" ), ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID );
+ #endif
+
+ LockSilent();
+
+ #ifdef THREAD_MUTEX_TRACING_ENABLED
+ if (m_lockCount == 0)
+ {
+ // we now own it for the first time. Set owner information
+ m_currentOwnerID = thisThreadID;
+ if ( m_bTrace )
+ Msg( _T( "Thread %u now owns lock 0x%x\n" ), m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection );
+ }
+ m_lockCount++;
+ #endif
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Unlock()
+{
+#if defined( _PS3 )
+
+ #ifndef NO_THREAD_SYNC
+ sys_mutex_unlock( m_Mutex );
+ #endif
+
+#else
+ #ifdef THREAD_MUTEX_TRACING_ENABLED
+ AssertMsg( m_lockCount >= 1, "Invalid unlock of thread lock" );
+ m_lockCount--;
+ if (m_lockCount == 0)
+ {
+ if ( m_bTrace )
+ Msg( _T( "Thread %u releasing lock 0x%x\n" ), m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection );
+ m_currentOwnerID = 0;
+ }
+ #endif
+ UnlockSilent();
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::LockSilent()
+{
+ #ifdef MSVC
+ EnterCriticalSection((CRITICAL_SECTION *)&m_CriticalSection);
+ #else
+ DebuggerBreak(); // should not be called - not defined for this platform/compiler!!!
+ #endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::UnlockSilent()
+{
+ #ifdef MSVC
+ LeaveCriticalSection((CRITICAL_SECTION *)&m_CriticalSection);
+ #else
+ DebuggerBreak(); // should not be called - not defined for this platform/compiler!!!
+ #endif
+}
+
+//---------------------------------------------------------
+
+inline bool CThreadMutex::AssertOwnedByCurrentThread()
+{
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+#ifdef _WIN32
+ if (ThreadGetCurrentId() == m_currentOwnerID)
+ return true;
+ AssertMsg3( 0, "Expected thread %u as owner of lock 0x%x, but %u owns", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID );
+ return false;
+#elif defined( _PS3 )
+ return true;
+#endif
+#else
+ return true;
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::SetTrace( bool bTrace )
+{
+#ifdef _WIN32
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+ m_bTrace = bTrace;
+#endif
+#elif defined _PS3
+ //EAPS3
+#endif
+
+}
+
+//---------------------------------------------------------
+
+#elif defined(POSIX) && !defined( _GAMECONSOLE )
+
+inline CThreadMutex::CThreadMutex()
+{
+ // enable recursive locks as we need them
+ pthread_mutexattr_init( &m_Attr );
+ pthread_mutexattr_settype( &m_Attr, PTHREAD_MUTEX_RECURSIVE );
+ pthread_mutex_init( &m_Mutex, &m_Attr );
+}
+
+//---------------------------------------------------------
+
+inline CThreadMutex::~CThreadMutex()
+{
+ pthread_mutex_destroy( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Lock()
+{
+ pthread_mutex_lock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Unlock()
+{
+ pthread_mutex_unlock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::LockSilent()
+{
+ pthread_mutex_lock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::UnlockSilent()
+{
+ pthread_mutex_unlock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline bool CThreadMutex::AssertOwnedByCurrentThread()
+{
+ return true;
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::SetTrace(bool fTrace)
+{
+}
+
+#else
+#error
+#endif // POSIX
+
+//-----------------------------------------------------------------------------
+//
+// CThreadRWLock inline functions
+//
+//-----------------------------------------------------------------------------
+
+inline CThreadRWLock::CThreadRWLock()
+: m_CanRead( true ),
+ m_nWriters( 0 ),
+ m_nActiveReaders( 0 ),
+ m_nPendingReaders( 0 )
+{
+}
+
+inline void CThreadRWLock::LockForRead()
+{
+ m_mutex.Lock();
+ if ( m_nWriters)
+ {
+ WaitForRead();
+ }
+ m_nActiveReaders++;
+ m_mutex.Unlock();
+}
+
+inline void CThreadRWLock::UnlockRead()
+{
+ m_mutex.Lock();
+ m_nActiveReaders--;
+ if ( m_nActiveReaders == 0 && m_nWriters != 0 )
+ {
+ m_CanWrite.Set();
+ }
+ m_mutex.Unlock();
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSpinRWLock inline functions
+//
+//-----------------------------------------------------------------------------
+
+#ifndef OLD_SPINRWLOCK
+
+#if defined(TEST_THREAD_SPIN_RW_LOCK)
+#define RWLAssert( exp ) if ( exp ) ; else DebuggerBreak();
+#else
+#define RWLAssert( exp ) ((void)0)
+#endif
+
+inline bool CThreadSpinRWLock::IsLockedForWrite()
+{
+ return ( m_lockInfo.m_fWriting == 1 );
+}
+
+inline bool CThreadSpinRWLock::IsLockedForRead()
+{
+ return ( m_lockInfo.m_nReaders > 0 );
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForWrite()
+{
+ volatile LockInfo_t &curValue = m_lockInfo;
+ if ( !( curValue.m_i32 & 0x00010000 ) && ThreadInterlockedAssignIf( &curValue.m_i32, 0x00010000, 0 ) )
+ {
+ ThreadMemoryBarrier();
+ RWLAssert( m_iWriteDepth == 0 && m_writerId == 0 );
+ m_writerId = ThreadGetCurrentId();
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ m_iWriteDepth++;
+#endif
+ return true;
+ }
+
+ return false;
+}
+
+inline bool CThreadSpinRWLock::TryLockForWrite_UnforcedInline()
+{
+ if ( TryLockForWrite() )
+ {
+ return true;
+ }
+
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( m_writerId != ThreadGetCurrentId() )
+ {
+ return false;
+ }
+ m_iWriteDepth++;
+ return true;
+#else
+ return false;
+#endif
+}
+
+FORCEINLINE void CThreadSpinRWLock::LockForWrite()
+{
+ if ( !TryLockForWrite() )
+ {
+ SpinLockForWrite();
+ }
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForRead()
+{
+ volatile LockInfo_t &curValue = m_lockInfo;
+ if ( !( curValue.m_i32 & 0x00010000 ) ) // !m_lockInfo.m_fWriting
+ {
+ LockInfo_t oldValue;
+ LockInfo_t newValue;
+ oldValue.m_i32 = ( curValue.m_i32 & 0xffff );
+ newValue.m_i32 = oldValue.m_i32 + 1;
+
+ if ( ThreadInterlockedAssignIf( &m_lockInfo.m_i32, newValue.m_i32, oldValue.m_i32 ) )
+ {
+ ThreadMemoryBarrier();
+ RWLAssert( m_lockInfo.m_fWriting == 0 );
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool CThreadSpinRWLock::TryLockForRead_UnforcedInline()
+{
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( m_lockInfo.m_i32 & 0x00010000 ) // m_lockInfo.m_fWriting
+ {
+ if ( m_writerId == ThreadGetCurrentId() )
+ {
+ m_lockInfo.m_nReaders++;
+ return true;
+ }
+
+ return false;
+ }
+#endif
+ return TryLockForRead();
+}
+
+FORCEINLINE void CThreadSpinRWLock::LockForRead()
+{
+ if ( !TryLockForRead() )
+ {
+ SpinLockForRead();
+ }
+}
+
+FORCEINLINE void CThreadSpinRWLock::UnlockWrite()
+{
+ RWLAssert( m_writerId == ThreadGetCurrentId() );
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( --m_iWriteDepth == 0 )
+#endif
+ {
+ m_writerId = 0;
+ ThreadMemoryBarrier();
+ m_lockInfo.m_i32 = 0;
+ }
+}
+
+#ifndef REENTRANT_THREAD_SPIN_RW_LOCK
+FORCEINLINE
+#else
+inline
+#endif
+void CThreadSpinRWLock::UnlockRead()
+{
+ RWLAssert( m_writerId == 0 || ( m_writerId == ThreadGetCurrentId() && m_lockInfo.m_fWriting ) );
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( !( m_lockInfo.m_i32 & 0x00010000 ) ) // !m_lockInfo.m_fWriting
+#endif
+ {
+ ThreadMemoryBarrier();
+ ThreadInterlockedDecrement( &m_lockInfo.m_i32 );
+ RWLAssert( m_writerId == 0 && !m_lockInfo.m_fWriting );
+ }
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ else if ( m_writerId == ThreadGetCurrentId() )
+ {
+ m_lockInfo.m_nReaders--;
+ }
+ else
+ {
+ RWLAssert( 0 );
+ }
+#endif
+}
+
+#else
+/* (commented out to reduce distraction in colorized editor, remove entirely when new implementation settles)
+inline bool CThreadSpinRWLock::AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand )
+{
+ // Note: using unions guarantees no aliasing bugs. Casting structures through *(int64*)&
+ // may create hard-to-catch bugs because when you do that, compiler doesn't know that the newly computed pointer
+ // is actually aliased with LockInfo_t structure. It's rarely a problem in practice, but when it is, it's a royal pain to debug.
+ return ThreadInterlockedAssignIf64( &m_lockInfo.m_i64, newValue.m_i64, comperand.m_i64 );
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForWrite( const uint32 threadId )
+{
+ // In order to grab a write lock, there can be no readers and no owners of the write lock
+ if ( m_lockInfo.m_nReaders > 0 || ( m_lockInfo.m_writerId && m_lockInfo.m_writerId != threadId ) )
+ {
+ return false;
+ }
+
+ static const LockInfo_t oldValue = { {0, 0} };
+ LockInfo_t newValue = { { threadId, 0 } };
+ if ( AssignIf( newValue, oldValue ) )
+ {
+ ThreadMemoryBarrier();
+ return true;
+ }
+ return false;
+}
+
+inline bool CThreadSpinRWLock::TryLockForWrite()
+{
+ m_nWriters++;
+ if ( !TryLockForWrite( ThreadGetCurrentId() ) )
+ {
+ m_nWriters--;
+ return false;
+ }
+ return true;
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForRead()
+{
+ if ( m_nWriters != 0 )
+ {
+ return false;
+ }
+ // In order to grab a write lock, the number of readers must not change and no thread can own the write
+ LockInfo_t oldValue;
+ LockInfo_t newValue;
+
+ if( IsX360() || IsPS3() )
+ {
+ // this is the code equivalent to original code (see below) that doesn't cause LHS on Xbox360
+ // WARNING: This code assumes BIG Endian CPU
+ oldValue.m_i64 = uint32( m_lockInfo.m_nReaders );
+ newValue.m_i64 = oldValue.m_i64 + 1; // NOTE: when we have -1 (or 0xFFFFFFFF) readers, this will result in non-equivalent code
+ }
+ else
+ {
+ // this is the original code that worked here for a while
+ oldValue.m_nReaders = m_lockInfo.m_nReaders;
+ oldValue.m_writerId = 0;
+ newValue.m_nReaders = oldValue.m_nReaders + 1;
+ newValue.m_writerId = 0;
+ }
+
+ if ( AssignIf( newValue, oldValue ) )
+ {
+ ThreadMemoryBarrier();
+ return true;
+ }
+ return false;
+}
+
+inline void CThreadSpinRWLock::LockForWrite()
+{
+ const uint32 threadId = ThreadGetCurrentId();
+
+ m_nWriters++;
+
+ if ( !TryLockForWrite( threadId ) )
+ {
+ ThreadPause();
+ SpinLockForWrite( threadId );
+ }
+}
+*/
+#endif
+
+// read data from a memory address
+template<class T> FORCEINLINE T ReadVolatileMemory( T const *pPtr )
+{
+ volatile const T * pVolatilePtr = ( volatile const T * ) pPtr;
+ return *pVolatilePtr;
+}
+
+
+//-----------------------------------------------------------------------------
+
+#if defined( _WIN32 )
+#pragma warning(pop)
+#endif
+
+#if defined( _PS3 )
+BOOL SetEvent( CThreadEvent *pEvent );
+BOOL ResetEvent( CThreadEvent *pEvent );
+DWORD WaitForMultipleObjects(DWORD nCount, CThreadEvent **lppHandles, BOOL bWaitAll, DWORD dwMilliseconds );
+#endif // _PS3
+#endif // THREADTOOLS_H
diff --git a/external/vpc/public/tier0/threadtools.inl b/external/vpc/public/tier0/threadtools.inl
new file mode 100644
index 0000000..0afe97a
--- /dev/null
+++ b/external/vpc/public/tier0/threadtools.inl
@@ -0,0 +1,629 @@
+#ifndef THREADTOOLS_INL
+#define THREADTOOLS_INL
+
+// This file is included in threadtools.h for PS3 and threadtools.cpp for all other platforms
+//
+// Do not #include other files here
+
+#ifndef _PS3
+// this is defined in the .cpp for the PS3 to avoid introducing a dependency for files including the header
+CTHREADLOCALPTR(CThread) g_pCurThread;
+
+#define INLINE_ON_PS3
+#else
+// Inlining these functions on PS3 (which are called across PRX boundaries) saves us over 1ms per frame
+#define INLINE_ON_PS3 inline
+#endif
+
+INLINE_ON_PS3 CThread::CThread() :
+#ifdef _WIN32
+m_hThread( NULL ),
+m_threadId( 0 ),
+#elif defined( _PS3 ) || defined(_POSIX)
+m_threadId( 0 ),
+m_threadZombieId( 0 ) ,
+#endif
+m_result( 0 ),
+m_flags( 0 )
+{
+ m_szName[0] = 0;
+ m_NotSuspendedEvent.Set();
+}
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 CThread::~CThread()
+{
+#ifdef MSVC
+ if (m_hThread)
+#elif defined(POSIX) && !defined( _PS3 )
+ if ( m_threadId )
+#endif
+ {
+ if ( IsAlive() )
+ {
+ Msg( "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
+#ifdef _WIN32
+
+ DoNewAssertDialog( __FILE__, __LINE__, "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
+#endif
+ if ( GetCurrentCThread() == this )
+ {
+ Stop(); // BUGBUG: Alfred - this doesn't make sense, this destructor fires from the hosting thread not the thread itself!!
+ }
+ }
+ }
+#if defined(POSIX) || defined( _PS3 )
+ if ( m_threadZombieId )
+ {
+ // just clean up zombie threads immediately (the destructor is fired from the hosting thread)
+ Join();
+ }
+#endif
+}
+
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 const char *CThread::GetName()
+{
+ AUTO_LOCK( m_Lock );
+ if ( !m_szName[0] )
+ {
+#if defined( _WIN32 )
+ _snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/%p)", this, m_hThread );
+#elif defined( _PS3 )
+ snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p)", this );
+#elif defined( POSIX )
+ _snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/0x%x)", this, (uint)m_threadId );
+#endif
+ m_szName[sizeof(m_szName) - 1] = 0;
+ }
+ return m_szName;
+}
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 void CThread::SetName(const char *pszName)
+{
+ AUTO_LOCK( m_Lock );
+ strncpy( m_szName, pszName, sizeof(m_szName) - 1 );
+ m_szName[sizeof(m_szName) - 1] = 0;
+}
+
+//-----------------------------------------------------
+// Functions for the other threads
+//-----------------------------------------------------
+
+// Start thread running - error if already running
+INLINE_ON_PS3 bool CThread::Start( unsigned nBytesStack, ThreadPriorityEnum_t nPriority )
+{
+ AUTO_LOCK( m_Lock );
+
+ if ( IsAlive() )
+ {
+ AssertMsg( 0, "Tried to create a thread that has already been created!" );
+ return false;
+ }
+
+ bool bInitSuccess = false;
+ CThreadEvent createComplete;
+ ThreadInit_t init = { this, &createComplete, &bInitSuccess };
+
+#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
+ {
+ int iValidEntries = GetCallStack_Fast( init.ParentStackTrace, ARRAYSIZE( init.ParentStackTrace ), 0 );
+ for( int i = iValidEntries; i < ARRAYSIZE( init.ParentStackTrace ); ++i )
+ {
+ init.ParentStackTrace[i] = NULL;
+ }
+ }
+#endif
+
+#ifdef PLATFORM_WINDOWS
+ m_hThread = (HANDLE)CreateThread( NULL,
+ nBytesStack,
+ (LPTHREAD_START_ROUTINE)GetThreadProc(),
+ new ThreadInit_t(init),
+ 0,
+ (LPDWORD)&m_threadId );
+
+ if( nPriority != PRIORITY_DEFAULT )
+ {
+ SetThreadPriority( m_hThread, nPriority );
+ }
+
+ if ( !m_hThread )
+ {
+ AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
+ return false;
+ }
+#elif PLATFORM_PS3
+ // On the PS3, a stack size of 0 doesn't imply a default stack size, so we need to force it to our
+ // own default size.
+ if ( nBytesStack == 0 )
+ {
+ nBytesStack = PS3_SYS_PPU_THREAD_COMMON_STACK_SIZE;
+ }
+
+ //The thread is about to begin
+ m_threadEnd.Reset();
+
+ // sony documentation:
+ // "If the PPU thread is not joined by sys_ppu_thread_join() after exit,
+ // it should always be created as non-joinable (not specifying
+ // SYS_PPU_THREAD_CREATE_JOINABLE). Otherwise, some resources are left
+ // allocated after termination of the PPU thread as if memory leaks."
+ const char* threadName=m_szName;
+ if ( sys_ppu_thread_create( &m_threadId,
+ (void(*)(uint64_t))GetThreadProc(),
+ (uint64_t)(new ThreadInit_t( init )),
+ nPriority,
+ nBytesStack,
+ SYS_PPU_THREAD_CREATE_JOINABLE ,
+ threadName ) != CELL_OK )
+ {
+ AssertMsg1( 0, "Failed to create thread (error 0x%x)", errno );
+ return false;
+ }
+
+ bInitSuccess = true;
+#elif PLATFORM_POSIX
+ pthread_attr_t attr;
+ pthread_attr_init( &attr );
+ pthread_attr_setstacksize( &attr, MAX( nBytesStack, 1024u*1024 ) );
+ if ( pthread_create( &m_threadId, &attr, (void *(*)(void *))GetThreadProc(), new ThreadInit_t( init ) ) != 0 )
+ {
+ AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
+ return false;
+ }
+ bInitSuccess = true;
+#endif
+
+
+
+ if ( !WaitForCreateComplete( &createComplete ) )
+ {
+ Msg( "Thread failed to initialize\n" );
+#ifdef _WIN32
+ CloseHandle( m_hThread );
+ m_hThread = NULL;
+#elif defined( _PS3 )
+ m_threadEnd.Set();
+ m_threadId = NULL;
+ m_threadZombieId = 0;
+#endif
+
+ return false;
+ }
+
+ if ( !bInitSuccess )
+ {
+ Msg( "Thread failed to initialize\n" );
+#ifdef _WIN32
+ CloseHandle( m_hThread );
+ m_hThread = NULL;
+#elif defined(POSIX) && !defined( _PS3 )
+ m_threadId = 0;
+ m_threadZombieId = 0;
+#endif
+ return false;
+ }
+
+#ifdef _WIN32
+ if ( !m_hThread )
+ {
+ Msg( "Thread exited immediately\n" );
+ }
+#endif
+
+#ifdef _WIN32
+ AddThreadHandleToIDMap( m_hThread, m_threadId );
+ return !!m_hThread;
+#elif defined(POSIX)
+ return !!m_threadId;
+#endif
+}
+
+//---------------------------------------------------------
+//
+// Return true if the thread has been created and hasn't yet exited
+//
+
+INLINE_ON_PS3 bool CThread::IsAlive()
+{
+#ifdef PLATFORM_WINDOWS
+ DWORD dwExitCode;
+ return (
+ m_hThread
+ && GetExitCodeThread(m_hThread, &dwExitCode)
+ && dwExitCode == STILL_ACTIVE );
+#elif defined(POSIX)
+ return !!m_threadId;
+#endif
+}
+
+// This method causes the current thread to wait until this thread
+// is no longer alive.
+INLINE_ON_PS3 bool CThread::Join( unsigned timeout )
+{
+#ifdef _WIN32
+ if ( m_hThread )
+#elif defined(POSIX)
+ if ( m_threadId || m_threadZombieId )
+#endif
+ {
+ AssertMsg(GetCurrentCThread() != this, _T("Thread cannot be joined with self"));
+
+#ifdef _WIN32
+ return ThreadJoin( (ThreadHandle_t)m_hThread, timeout );
+#elif defined(POSIX)
+ bool ret = ThreadJoin( (ThreadHandle_t)(m_threadId ? m_threadId : m_threadZombieId), timeout );
+ m_threadZombieId = 0;
+ return ret;
+#endif
+ }
+ return true;
+}
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 ThreadHandle_t CThread::GetThreadHandle()
+{
+#ifdef _WIN32
+ return (ThreadHandle_t)m_hThread;
+#else
+ return (ThreadHandle_t)m_threadId;
+#endif
+}
+
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 int CThread::GetResult()
+{
+ return m_result;
+}
+
+//-----------------------------------------------------
+// Functions for both this, and maybe, and other threads
+//-----------------------------------------------------
+
+// Forcibly, abnormally, but relatively cleanly stop the thread
+//
+
+INLINE_ON_PS3 void CThread::Stop(int exitCode)
+{
+ if ( !IsAlive() )
+ return;
+
+ if ( GetCurrentCThread() == this )
+ {
+#if !defined( _PS3 )
+ m_result = exitCode;
+ if ( !( m_flags & SUPPORT_STOP_PROTOCOL ) )
+ {
+ OnExit();
+ g_pCurThread = NULL;
+
+#ifdef _WIN32
+ CloseHandle( m_hThread );
+ RemoveThreadHandleToIDMap( m_hThread );
+ m_hThread = NULL;
+#else
+ m_threadId = 0;
+ m_threadZombieId = 0;
+#endif
+ }
+ else
+ {
+ throw exitCode;
+ }
+#else
+ AssertMsg( false, "Called CThread::Stop() for a platform that doesn't have it!\n");
+#endif
+ }
+ else
+ AssertMsg( 0, "Only thread can stop self: Use a higher-level protocol");
+}
+
+//---------------------------------------------------------
+
+// Get the priority
+INLINE_ON_PS3 int CThread::GetPriority() const
+{
+#ifdef _WIN32
+ return GetThreadPriority(m_hThread);
+#elif defined( _PS3 )
+ return ThreadGetPriority( (ThreadHandle_t) m_threadId );
+#elif defined(POSIX)
+ struct sched_param thread_param;
+ int policy;
+ pthread_getschedparam( m_threadId, &policy, &thread_param );
+ return thread_param.sched_priority;
+#endif
+}
+
+//---------------------------------------------------------
+
+// Set the priority
+INLINE_ON_PS3 bool CThread::SetPriority(int priority)
+{
+#ifdef WIN32
+ return ThreadSetPriority( (ThreadHandle_t)m_hThread, priority );
+#else
+ return ThreadSetPriority( (ThreadHandle_t)m_threadId, priority );
+#endif
+}
+
+//---------------------------------------------------------
+
+// Suspend a thread
+INLINE_ON_PS3 unsigned CThread::Suspend()
+{
+ AssertMsg( ThreadGetCurrentId() == (ThreadId_t)m_threadId, "Cannot call CThread::Suspend from outside thread" );
+
+ if ( ThreadGetCurrentId() != (ThreadId_t)m_threadId )
+ {
+ DebuggerBreakIfDebugging();
+ }
+
+ m_NotSuspendedEvent.Reset();
+ m_NotSuspendedEvent.Wait();
+
+ return 0;
+}
+
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 unsigned CThread::Resume()
+{
+ if ( m_NotSuspendedEvent.Check() )
+ {
+ DevWarning( "Called Resume() on a thread that is not suspended!\n" );
+ }
+ m_NotSuspendedEvent.Set();
+ return 0;
+}
+
+//---------------------------------------------------------
+
+// Force hard-termination of thread. Used for critical failures.
+INLINE_ON_PS3 bool CThread::Terminate(int exitCode)
+{
+#if defined( _X360 )
+ AssertMsg( 0, "Cannot terminate a thread on the Xbox!" );
+ return false;
+#elif defined( _WIN32 )
+ // I hope you know what you're doing!
+ if (!TerminateThread(m_hThread, exitCode))
+ return false;
+ CloseHandle( m_hThread );
+ RemoveThreadHandleToIDMap( m_hThread );
+ m_hThread = NULL;
+#elif defined( _PS3 )
+ m_threadEnd.Set();
+ m_threadId = NULL;
+#elif defined(POSIX)
+ pthread_kill( m_threadId, SIGKILL );
+ m_threadId = 0;
+#endif
+ return true;
+}
+
+//-----------------------------------------------------
+// Global methods
+//-----------------------------------------------------
+
+// Get the Thread object that represents the current thread, if any.
+// Can return NULL if the current thread was not created using
+// CThread
+//
+
+INLINE_ON_PS3 CThread *CThread::GetCurrentCThread()
+{
+#ifdef _PS3
+ return GetCurThreadPS3();
+#else
+ return g_pCurThread;
+#endif
+}
+
+//---------------------------------------------------------
+//
+// Offer a context switch. Under Win32, equivalent to Sleep(0)
+//
+
+#ifdef Yield
+#undef Yield
+#endif
+INLINE_ON_PS3 void CThread::Yield()
+{
+#ifdef _WIN32
+ ::Sleep(0);
+#elif defined( _PS3 )
+ // sys_ppu_thread_yield doesn't seem to function properly, so sleep instead.
+ sys_timer_usleep( 60 );
+#elif defined(POSIX)
+ pthread_yield();
+#endif
+}
+
+//---------------------------------------------------------
+//
+// This method causes the current thread to yield and not to be
+// scheduled for further execution until a certain amount of real
+// time has elapsed, more or less. Duration is in milliseconds
+
+INLINE_ON_PS3 void CThread::Sleep( unsigned duration )
+{
+#ifdef _WIN32
+ ::Sleep(duration);
+#elif defined (_PS3)
+ sys_timer_usleep( duration * 1000 );
+#elif defined(POSIX)
+ usleep( duration * 1000 );
+#endif
+}
+
+//---------------------------------------------------------
+
+// Optional pre-run call, with ability to fail-create. Note Init()
+// is forced synchronous with Start()
+INLINE_ON_PS3 bool CThread::Init()
+{
+ return true;
+}
+
+//---------------------------------------------------------
+
+#if defined( _PS3 )
+INLINE_ON_PS3 int CThread::Run()
+{
+ return -1;
+}
+#endif // _PS3
+
+// Called when the thread exits
+INLINE_ON_PS3 void CThread::OnExit() { }
+
+// Allow for custom start waiting
+INLINE_ON_PS3 bool CThread::WaitForCreateComplete( CThreadEvent *pEvent )
+{
+ // Force serialized thread creation...
+ if (!pEvent->Wait(60000))
+ {
+ AssertMsg( 0, "Probably deadlock or failure waiting for thread to initialize." );
+ return false;
+ }
+ return true;
+}
+
+//---------------------------------------------------------
+INLINE_ON_PS3 CThread::ThreadProc_t CThread::GetThreadProc()
+{
+ return ThreadProc;
+}
+
+#ifdef PLATFORM_WINDOWS
+unsigned long STDCALL CThread::ThreadProc(LPVOID pv)
+#else
+INLINE_ON_PS3 void* CThread::ThreadProc(LPVOID pv)
+#endif
+{
+#if defined( POSIX ) || defined( _PS3 )
+ ThreadInit_t *pInit = reinterpret_cast<ThreadInit_t*>(pv);
+#else
+ std::auto_ptr<ThreadInit_t> pInit((ThreadInit_t *)pv);
+#endif
+
+#ifdef _X360
+ // Make sure all threads are consistent w.r.t floating-point math
+ SetupFPUControlWord();
+#endif
+ AllocateThreadID();
+
+ CThread *pThread = pInit->pThread;
+#ifdef _PS3
+ SetCurThreadPS3( pThread );
+#else
+ g_pCurThread = pThread;
+#endif
+
+ pThread->m_pStackBase = AlignValue( &pThread, 4096 );
+
+ pInit->pThread->m_result = -1;
+
+#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
+ CStackTop_ReferenceParentStack stackTop( pInit->ParentStackTrace, ARRAYSIZE( pInit->ParentStackTrace ) );
+#endif
+
+ bool bInitSuccess = true;
+ if ( pInit->pfInitSuccess )
+ *(pInit->pfInitSuccess) = false;
+
+#ifdef _PS3
+ *(pInit->pfInitSuccess) = pInit->pThread->Init();
+#else
+ try
+ {
+ bInitSuccess = pInit->pThread->Init();
+ }
+
+ catch (...)
+ {
+ pInit->pInitCompleteEvent->Set();
+ throw;
+ }
+#endif // _PS3
+
+ if ( pInit->pfInitSuccess )
+ *(pInit->pfInitSuccess) = bInitSuccess;
+ pInit->pInitCompleteEvent->Set();
+ if (!bInitSuccess)
+ return 0;
+
+ if ( !Plat_IsInDebugSession() && (pInit->pThread->m_flags & SUPPORT_STOP_PROTOCOL) )
+ {
+#ifndef _PS3
+ try
+#endif
+ {
+ pInit->pThread->m_result = pInit->pThread->Run();
+ }
+
+#ifndef _PS3
+ catch (...)
+ {
+ }
+#endif
+ }
+ else
+ {
+ pInit->pThread->m_result = pInit->pThread->Run();
+ }
+
+ pInit->pThread->OnExit();
+#ifdef _PS3
+ SetCurThreadPS3( NULL );
+#else
+ g_pCurThread = NULL;
+#endif
+ FreeThreadID();
+
+ AUTO_LOCK( pThread->m_Lock );
+#ifdef _WIN32
+ CloseHandle( pThread->m_hThread );
+ RemoveThreadHandleToIDMap( pThread->m_hThread );
+ pThread->m_hThread = NULL;
+#elif defined( _PS3 )
+ pThread->m_threadZombieId = pThread->m_threadId;
+ pThread->m_threadEnd.Set();
+ pThread->m_threadId = 0;
+#elif defined(POSIX)
+ pThread->m_threadZombieId = pThread->m_threadId;
+ pThread->m_threadId = 0;
+#else
+#error
+#endif
+
+ pThread->m_ExitEvent.Set();
+#ifdef _PS3
+ {
+ pThread->m_Lock.Unlock();
+ sys_ppu_thread_exit( pInit->pThread->m_result );
+ // reacquire the lock in case thread exit didn't actually exit the thread, so that
+ // AUTO_LOCK won't double-unlock the lock (to keep it paired)
+ pThread->m_Lock.Lock();
+ }
+#endif
+
+#if defined( POSIX )|| defined( _PS3 )
+ return (void*)pInit->pThread->m_result;
+#else
+ return pInit->pThread->m_result;
+#endif
+}
+
+#endif // THREADTOOLS_INL
diff --git a/external/vpc/public/tier0/tslist.h b/external/vpc/public/tier0/tslist.h
new file mode 100644
index 0000000..d8bc55e
--- /dev/null
+++ b/external/vpc/public/tier0/tslist.h
@@ -0,0 +1,858 @@
+//========== Copyright � 2005, Valve Corporation, All rights reserved. ========
+//
+// Purpose:
+//
+// LIFO from disassembly of Windows API and http://perso.wanadoo.fr/gmem/evenements/jim2002/articles/L17_Fober.pdf
+// FIFO from http://perso.wanadoo.fr/gmem/evenements/jim2002/articles/L17_Fober.pdf
+//
+//=============================================================================
+
+#ifndef TSLIST_H
+#define TSLIST_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#if ( defined( PLATFORM_X360 ) || defined( PLATFORM_WINDOWS_PC64 ) )
+#define USE_NATIVE_SLIST
+#endif
+
+#if defined( USE_NATIVE_SLIST ) && !defined( _X360 ) && !defined( _PS3 )
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+
+#if defined(PLATFORM_WINDOWS_PC64)
+
+#define TSLIST_HEAD_ALIGNMENT 16 //MEMORY_ALLOCATION_ALIGNMENT
+#define TSLIST_NODE_ALIGNMENT 16 //MEMORY_ALLOCATION_ALIGNMENT
+
+#define TSLIST_HEAD_ALIGN ALIGN16
+#define TSLIST_NODE_ALIGN ALIGN16
+#define TSLIST_HEAD_ALIGN_POST ALIGN16_POST
+#define TSLIST_NODE_ALIGN_POST ALIGN16_POST
+
+#else
+
+#define TSLIST_HEAD_ALIGNMENT 8
+#define TSLIST_NODE_ALIGNMENT 8
+
+#define TSLIST_HEAD_ALIGN ALIGN8
+#define TSLIST_NODE_ALIGN ALIGN8
+#define TSLIST_HEAD_ALIGN_POST ALIGN8_POST
+#define TSLIST_NODE_ALIGN_POST ALIGN8_POST
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE bool RunTSQueueTests( int nListSize = 10000, int nTests = 1 );
+PLATFORM_INTERFACE bool RunTSListTests( int nListSize = 10000, int nTests = 1 );
+
+//-----------------------------------------------------------------------------
+// Lock free list.
+//-----------------------------------------------------------------------------
+//#define USE_NATIVE_SLIST
+
+#ifdef USE_NATIVE_SLIST
+typedef SLIST_ENTRY TSLNodeBase_t;
+typedef SLIST_HEADER TSLHead_t;
+#else
+struct TSLIST_NODE_ALIGN TSLNodeBase_t
+{
+ TSLNodeBase_t *Next; // name to match Windows
+}
+TSLIST_NODE_ALIGN_POST;
+
+union TSLHead_t
+{
+ struct Value_t
+ {
+ TSLNodeBase_t *Next;
+ // <sergiy> Depth must be in the least significant halfword when atomically loading into register,
+ // to avoid carrying digits from Sequence. Carrying digits from Depth to Sequence is ok,
+ // because Sequence can be pretty much random. We could operate on both of them separately,
+ // but it could perhaps (?) lead to problems with store forwarding. I don't know 'cause I didn't
+ // performance-test or design original code, I'm just making it work on PowerPC.
+ #ifdef PLAT_BIG_ENDIAN
+ int16 Sequence;
+ int16 Depth;
+ #else
+ int16 Depth;
+ int16 Sequence;
+ #endif
+ } value;
+
+ struct Value32_t
+ {
+ TSLNodeBase_t *Next_do_not_use_me;
+ int32 DepthAndSequence;
+ } value32;
+
+ int64 value64;
+};
+#endif
+
+//-------------------------------------
+
+class TSLIST_HEAD_ALIGN CTSListBase
+{
+public:
+ CTSListBase()
+ {
+ if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( _T( "CTSListBase: Misaligned list\n" ) );
+ DebuggerBreak();
+ }
+
+#ifdef USE_NATIVE_SLIST
+ InitializeSListHead( &m_Head );
+#else
+ m_Head.value64 = (int64)0;
+#endif
+ }
+
+ ~CTSListBase()
+ {
+ Detach();
+ }
+
+ TSLNodeBase_t *Push( TSLNodeBase_t *pNode )
+ {
+#ifdef _DEBUG
+ if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 )
+ {
+ Error( _T( "CTSListBase: Misaligned node\n" ) );
+ DebuggerBreak();
+ }
+#endif
+
+#ifdef USE_NATIVE_SLIST
+#ifdef _X360
+ // integrated write-release barrier
+ return (TSLNodeBase_t *)InterlockedPushEntrySListRelease( &m_Head, pNode );
+#else
+ return (TSLNodeBase_t *)InterlockedPushEntrySList( &m_Head, pNode );
+#endif
+#else
+ TSLHead_t oldHead;
+ TSLHead_t newHead;
+
+ #if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
+ __lwsync(); // write-release barrier
+ #endif
+
+ for (;;)
+ {
+ oldHead.value64 = m_Head.value64;
+ pNode->Next = oldHead.value.Next;
+ newHead.value.Next = pNode;
+
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence + 0x10001;
+
+
+ if ( ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) )
+ {
+ break;
+ }
+ ThreadPause();
+ };
+
+ return (TSLNodeBase_t *)oldHead.value.Next;
+#endif
+ }
+
+ TSLNodeBase_t *Pop()
+ {
+#ifdef USE_NATIVE_SLIST
+#ifdef _X360
+ // integrated read-acquire barrier
+ TSLNodeBase_t *pNode = (TSLNodeBase_t *)InterlockedPopEntrySListAcquire( &m_Head );
+#else
+ TSLNodeBase_t *pNode = (TSLNodeBase_t *)InterlockedPopEntrySList( &m_Head );
+#endif
+ return pNode;
+#else
+ TSLHead_t oldHead;
+ TSLHead_t newHead;
+
+ for (;;)
+ {
+ oldHead.value64 = m_Head.value64;
+ if ( !oldHead.value.Next )
+ return NULL;
+
+ newHead.value.Next = oldHead.value.Next->Next;
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
+
+
+ if ( ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) )
+ {
+ #if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
+ __lwsync(); // read-acquire barrier
+ #endif
+ break;
+ }
+ ThreadPause();
+ };
+
+ return (TSLNodeBase_t *)oldHead.value.Next;
+#endif
+ }
+
+ TSLNodeBase_t *Detach()
+ {
+#ifdef USE_NATIVE_SLIST
+ TSLNodeBase_t *pBase = (TSLNodeBase_t *)InterlockedFlushSList( &m_Head );
+#if defined( _X360 ) || defined( _PS3 )
+ __lwsync(); // read-acquire barrier
+#endif
+ return pBase;
+#else
+ TSLHead_t oldHead;
+ TSLHead_t newHead;
+
+ do
+ {
+ ThreadPause();
+
+ oldHead.value64 = m_Head.value64;
+ if ( !oldHead.value.Next )
+ return NULL;
+
+ newHead.value.Next = NULL;
+ // <sergiy> the reason for AND'ing it instead of poking a short into memory
+ // is probably to avoid store forward issues, but I'm not sure because
+ // I didn't construct this code. In any case, leaving it as is on big-endian
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence & 0xffff0000;
+
+ } while( !ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) );
+
+ return (TSLNodeBase_t *)oldHead.value.Next;
+#endif
+ }
+
+ TSLHead_t *AccessUnprotected()
+ {
+ return &m_Head;
+ }
+
+ int Count() const
+ {
+#ifdef USE_NATIVE_SLIST
+ return QueryDepthSList( const_cast<TSLHead_t*>( &m_Head ) );
+#else
+ return m_Head.value.Depth;
+#endif
+ }
+
+private:
+ TSLHead_t m_Head;
+}
+TSLIST_HEAD_ALIGN_POST;
+
+//-------------------------------------
+
+template <typename T>
+class TSLIST_HEAD_ALIGN CTSSimpleList : public CTSListBase
+{
+public:
+ void Push( T *pNode )
+ {
+ Assert( sizeof(T) >= sizeof(TSLNodeBase_t) );
+ CTSListBase::Push( (TSLNodeBase_t *)pNode );
+ }
+
+ T *Pop()
+ {
+ return (T *)CTSListBase::Pop();
+ }
+}
+TSLIST_HEAD_ALIGN_POST;
+
+//-------------------------------------
+// this is a replacement for CTSList<> and CObjectPool<> that does not
+// have a per-item, per-alloc new/delete overhead
+// similar to CTSSimpleList except that it allocates it's own pool objects
+// and frees them on destruct. Also it does not overlay the TSNodeBase_t memory
+// on T's memory
+template< class T >
+class TSLIST_HEAD_ALIGN CTSPool : public CTSListBase
+{
+ // packs the node and the item (T) into a single struct and pools those
+ struct TSLIST_NODE_ALIGN simpleTSPoolStruct_t : public TSLNodeBase_t
+ {
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+public:
+
+ ~CTSPool()
+ {
+ simpleTSPoolStruct_t *pNode = NULL;
+ while ( 1 )
+ {
+ pNode = (simpleTSPoolStruct_t *)CTSListBase::Pop();
+ if ( !pNode )
+ break;
+ delete pNode;
+ }
+ }
+
+ void PutObject( T *pInfo )
+ {
+ char *pElem = (char *)pInfo;
+ pElem -= offsetof(simpleTSPoolStruct_t,elem);
+ simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)pElem;
+
+ CTSListBase::Push( pNode );
+ }
+
+ T *GetObject()
+ {
+ simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)CTSListBase::Pop();
+ if ( !pNode )
+ {
+ pNode = new simpleTSPoolStruct_t;
+ }
+ return &pNode->elem;
+ }
+
+ // omg windows sdk - why do you #define GetObject()?
+ FORCEINLINE T *Get()
+ {
+ return GetObject();
+ }
+
+} TSLIST_HEAD_ALIGN_POST;
+//-------------------------------------
+
+template <typename T>
+class TSLIST_HEAD_ALIGN CTSList : public CTSListBase
+{
+public:
+ struct TSLIST_NODE_ALIGN Node_t : public TSLNodeBase_t
+ {
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ T elem;
+
+ } TSLIST_NODE_ALIGN_POST;
+
+ ~CTSList()
+ {
+ Purge();
+ }
+
+ void Purge()
+ {
+ Node_t *pCurrent = Detach();
+ Node_t *pNext;
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ }
+
+ void RemoveAll()
+ {
+ Purge();
+ }
+
+ Node_t *Push( Node_t *pNode )
+ {
+ return (Node_t *)CTSListBase::Push( pNode );
+ }
+
+ Node_t *Pop()
+ {
+ return (Node_t *)CTSListBase::Pop();
+ }
+
+ void PushItem( const T &init )
+ {
+ Push( new Node_t( init ) );
+ }
+
+ bool PopItem( T *pResult)
+ {
+ Node_t *pNode = Pop();
+ if ( !pNode )
+ return false;
+ *pResult = pNode->elem;
+ delete pNode;
+ return true;
+ }
+
+ Node_t *Detach()
+ {
+ return (Node_t *)CTSListBase::Detach();
+ }
+
+} TSLIST_HEAD_ALIGN_POST;
+
+//-------------------------------------
+
+template <typename T>
+class TSLIST_HEAD_ALIGN CTSListWithFreeList : public CTSListBase
+{
+public:
+ struct TSLIST_NODE_ALIGN Node_t : public TSLNodeBase_t
+ {
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+ ~CTSListWithFreeList()
+ {
+ Purge();
+ }
+
+ void Purge()
+ {
+ Node_t *pCurrent = Detach();
+ Node_t *pNext;
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ pCurrent = (Node_t *)m_FreeList.Detach();
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ }
+
+ void RemoveAll()
+ {
+ Node_t *pCurrent = Detach();
+ Node_t *pNext;
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ m_FreeList.Push( pCurrent );
+ pCurrent = pNext;
+ }
+ }
+
+ Node_t *Push( Node_t *pNode )
+ {
+ return (Node_t *)CTSListBase::Push( pNode );
+ }
+
+ Node_t *Pop()
+ {
+ return (Node_t *)CTSListBase::Pop();
+ }
+
+ void PushItem( const T &init )
+ {
+ Node_t *pNode = (Node_t *)m_FreeList.Pop();
+ if ( !pNode )
+ {
+ pNode = new Node_t;
+ }
+ pNode->elem = init;
+ Push( pNode );
+ }
+
+ bool PopItem( T *pResult)
+ {
+ Node_t *pNode = Pop();
+ if ( !pNode )
+ return false;
+ *pResult = pNode->elem;
+ m_FreeList.Push( pNode );
+ return true;
+ }
+
+ Node_t *Detach()
+ {
+ return (Node_t *)CTSListBase::Detach();
+ }
+
+ void FreeNode( Node_t *pNode )
+ {
+ m_FreeList.Push( pNode );
+ }
+
+private:
+ CTSListBase m_FreeList;
+} TSLIST_HEAD_ALIGN_POST;
+
+//-----------------------------------------------------------------------------
+// Lock free queue
+//
+// A special consideration: the element type should be simple. This code
+// actually dereferences freed nodes as part of pop, but later detects
+// that. If the item in the queue is a complex type, only bad things can
+// come of that. Also, therefore, if you're using Push/Pop instead of
+// push item, be aware that the node memory cannot be freed until
+// all threads that might have been popping have completed the pop.
+// The PushItem()/PopItem() for handles this by keeping a persistent
+// free list. Dont mix Push/PushItem. Note also nodes will be freed at the end,
+// and are expected to have been allocated with operator new.
+//-----------------------------------------------------------------------------
+
+template <typename T, bool bTestOptimizer = false, bool bFreeList = true>
+class TSLIST_HEAD_ALIGN CTSQueue
+{
+public:
+ struct TSLIST_NODE_ALIGN Node_t
+ {
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ Node_t *pNext;
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+ union TSLIST_HEAD_ALIGN NodeLink_t
+ {
+ struct Value_t
+ {
+ Node_t *pNode;
+ int32 sequence;
+ } value;
+
+ int64 value64;
+ } TSLIST_HEAD_ALIGN_POST;
+
+ CTSQueue()
+ {
+ COMPILE_TIME_ASSERT( sizeof(Node_t) >= sizeof(TSLNodeBase_t) );
+ if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( "CTSQueue: Misaligned queue\n" );
+ DebuggerBreak();
+ }
+ if ( ((size_t)&m_Tail) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( "CTSQueue: Misaligned queue\n" );
+ DebuggerBreak();
+ }
+ m_Count = 0;
+ m_Head.value.sequence = m_Tail.value.sequence = 0;
+ m_Head.value.pNode = m_Tail.value.pNode = new Node_t; // list always contains a dummy node
+ m_Head.value.pNode->pNext = End();
+ }
+
+ ~CTSQueue()
+ {
+ Purge();
+ Assert( m_Count == 0 );
+ Assert( m_Head.value.pNode == m_Tail.value.pNode );
+ Assert( m_Head.value.pNode->pNext == End() );
+ delete m_Head.value.pNode;
+ }
+
+ // Note: Purge, RemoveAll, and Validate are *not* threadsafe
+ void Purge()
+ {
+ if ( IsDebug() )
+ {
+ Validate();
+ }
+
+ Node_t *pNode;
+ while ( ( pNode = Pop() ) != NULL )
+ {
+ delete pNode;
+ }
+
+ while ( bFreeList && ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL )
+ {
+ delete pNode;
+ }
+
+ Assert( m_Count == 0 );
+ Assert( m_Head.value.pNode == m_Tail.value.pNode );
+ Assert( m_Head.value.pNode->pNext == End() );
+
+ m_Head.value.sequence = m_Tail.value.sequence = 0;
+ }
+
+ void RemoveAll()
+ {
+ if ( IsDebug() )
+ {
+ Validate();
+ }
+
+ Node_t *pNode;
+ while ( bFreeList && ( pNode = Pop() ) != NULL )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ }
+
+ bool Validate()
+ {
+ bool bResult = true;
+ int nNodes = 0;
+
+ if ( m_Count == 0 )
+ {
+ if ( m_Head.value.pNode != m_Tail.value.pNode )
+ {
+ DebuggerBreakIfDebugging();
+ bResult = false;
+ }
+ }
+
+ Node_t *pNode = m_Head.value.pNode;
+ while ( pNode != End() )
+ {
+ nNodes++;
+ pNode = pNode->pNext;
+ }
+
+ nNodes--;// skip dummy node
+
+ if ( nNodes != m_Count )
+ {
+ DebuggerBreakIfDebugging();
+ bResult = false;
+ }
+
+ if ( !bResult )
+ {
+ Msg( "Corrupt CTSQueueDetected" );
+ }
+
+ return bResult;
+ }
+
+ void FinishPush( Node_t *pNode, const NodeLink_t &oldTail )
+ {
+ NodeLink_t newTail;
+
+ newTail.value.pNode = pNode;
+ newTail.value.sequence = oldTail.value.sequence + 1;
+
+ ThreadMemoryBarrier();
+
+ InterlockedCompareExchangeNodeLink( &m_Tail, newTail, oldTail );
+ }
+
+ Node_t *Push( Node_t *pNode )
+ {
+#ifdef _DEBUG
+ if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 )
+ {
+ Error( "CTSListBase: Misaligned node\n" );
+ DebuggerBreak();
+ }
+#endif
+
+ NodeLink_t oldTail;
+
+ pNode->pNext = End();
+
+ for (;;)
+ {
+ oldTail.value.sequence = m_Tail.value.sequence;
+ oldTail.value.pNode = m_Tail.value.pNode;
+ if ( InterlockedCompareExchangeNode( &(oldTail.value.pNode->pNext), pNode, End() ) == End() )
+ {
+ break;
+ }
+ else
+ {
+ // Another thread is trying to push, help it along
+ FinishPush( oldTail.value.pNode->pNext, oldTail );
+ }
+ }
+
+ FinishPush( pNode, oldTail ); // This can fail if another thread pushed between the sequence and node grabs above. Later pushes or pops corrects
+
+ m_Count++;
+
+ return oldTail.value.pNode;
+ }
+
+ Node_t *Pop()
+ {
+ #define TSQUEUE_BAD_NODE_LINK ( (Node_t *)INT_TO_POINTER( 0xdeadbeef ) )
+ NodeLink_t * volatile pHead = &m_Head;
+ NodeLink_t * volatile pTail = &m_Tail;
+ Node_t * volatile * pHeadNode = &m_Head.value.pNode;
+ volatile int * volatile pHeadSequence = &m_Head.value.sequence;
+ Node_t * volatile * pTailNode = &pTail->value.pNode;
+
+ NodeLink_t head;
+ NodeLink_t newHead;
+ Node_t *pNext;
+ int tailSequence;
+ T elem;
+
+ for (;;)
+ {
+ head.value.sequence = *pHeadSequence; // must grab sequence first, which allows condition below to ensure pNext is valid
+ ThreadMemoryBarrier(); // need a barrier to prevent reordering of these assignments
+ head.value.pNode = *pHeadNode;
+ tailSequence = pTail->value.sequence;
+ pNext = head.value.pNode->pNext;
+
+ if ( pNext && head.value.sequence == *pHeadSequence ) // Checking pNext only to force optimizer to not reorder the assignment to pNext and the compare of the sequence
+ {
+ if ( bTestOptimizer )
+ {
+ if ( pNext == TSQUEUE_BAD_NODE_LINK )
+ {
+ Msg( "Bad node link detected\n" );
+ continue;
+ }
+ }
+ if ( head.value.pNode == *pTailNode )
+ {
+ if ( pNext == End() )
+ {
+ return NULL;
+ }
+
+ // Another thread is trying to push, help it along
+ NodeLink_t &oldTail = head; // just reuse local memory for head to build old tail
+ oldTail.value.sequence = tailSequence; // reuse head pNode
+ FinishPush( pNext, oldTail );
+ }
+ else if ( pNext != End() )
+ {
+ elem = pNext->elem; // NOTE: next could be a freed node here, by design
+ newHead.value.pNode = pNext;
+ newHead.value.sequence = head.value.sequence + 1;
+ if ( InterlockedCompareExchangeNodeLink( pHead, newHead, head ) )
+ {
+ ThreadMemoryBarrier();
+
+ if ( bTestOptimizer )
+ {
+ head.value.pNode->pNext = TSQUEUE_BAD_NODE_LINK;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ m_Count--;
+ head.value.pNode->elem = elem;
+ return head.value.pNode;
+ }
+
+ void FreeNode( Node_t *pNode )
+ {
+ if ( bFreeList )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ else
+ {
+ delete pNode;
+ }
+ }
+
+ void PushItem( const T &init )
+ {
+ Node_t *pNode;
+ if ( bFreeList && ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL )
+ {
+ pNode->elem = init;
+ }
+ else
+ {
+ pNode = new Node_t( init );
+ }
+ Push( pNode );
+ }
+
+ bool PopItem( T *pResult)
+ {
+ Node_t *pNode = Pop();
+ if ( !pNode )
+ return false;
+ *pResult = pNode->elem;
+ if ( bFreeList )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ else
+ {
+ delete pNode;
+ }
+ return true;
+ }
+
+ int Count()
+ {
+ return m_Count;
+ }
+
+private:
+ Node_t *End() { return (Node_t *)this; } // just need a unique signifier
+
+#ifndef _WIN64
+ Node_t *InterlockedCompareExchangeNode( Node_t * volatile *ppNode, Node_t *value, Node_t *comperand )
+ {
+ return (Node_t *)::ThreadInterlockedCompareExchangePointer( (void **)ppNode, value, comperand );
+ }
+
+ bool InterlockedCompareExchangeNodeLink( NodeLink_t volatile *pLink, const NodeLink_t &value, const NodeLink_t &comperand )
+ {
+ return ThreadInterlockedAssignIf64( (int64 *)pLink, value.value64, comperand.value64 );
+ }
+
+#else
+ Node_t *InterlockedCompareExchangeNode( Node_t * volatile *ppNode, Node_t *value, Node_t *comperand )
+ {
+ AUTO_LOCK( m_ExchangeMutex );
+ Node_t *retVal = *ppNode;
+ if ( *ppNode == comperand )
+ *ppNode = value;
+ return retVal;
+ }
+
+ bool InterlockedCompareExchangeNodeLink( NodeLink_t volatile *pLink, const NodeLink_t &value, const NodeLink_t &comperand )
+ {
+ AUTO_LOCK( m_ExchangeMutex );
+ if ( pLink->value64 == comperand.value64 )
+ {
+ pLink->value64 = value.value64;
+ return true;
+ }
+ return false;
+ }
+
+ CThreadFastMutex m_ExchangeMutex;
+#endif
+
+ NodeLink_t m_Head;
+ NodeLink_t m_Tail;
+
+ CInterlockedInt m_Count;
+
+ CTSListBase m_FreeNodes;
+} TSLIST_HEAD_ALIGN_POST;
+
+#include "tier0/memdbgoff.h"
+
+#endif // TSLIST_H
diff --git a/external/vpc/public/tier0/validator.h b/external/vpc/public/tier0/validator.h
new file mode 100644
index 0000000..a3b336e
--- /dev/null
+++ b/external/vpc/public/tier0/validator.h
@@ -0,0 +1,73 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include "valobject.h"
+
+#ifndef VALIDATOR_H
+#define VALIDATOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#ifdef DBGFLAG_VALIDATE
+
+
+class CValidator
+{
+public:
+ // Constructors & destructors
+ CValidator( void );
+ ~CValidator( void );
+
+ // Call this each time we enter a new Validate function
+ void Push( tchar *pchType, void *pvObj, tchar *pchName );
+
+ // Call this each time we exit a Validate function
+ void Pop( void );
+
+ // Claim ownership of a memory block
+ void ClaimMemory( void *pvMem );
+
+ // Finish performing a check and perform necessary computations
+ void Finalize( void );
+
+ // Render our results to the console
+ void RenderObjects( int cubThreshold ); // Render all reported objects
+ void RenderLeaks( void ); // Render all memory leaks
+
+ // List manipulation functions:
+ CValObject *FindObject( void *pvObj ); // Returns CValObject containing pvObj, or NULL.
+ void DiffAgainst( CValidator *pOtherValidator ); // Removes any entries from this validator that are also present in the other.
+
+ // Accessors
+ bool BMemLeaks( void ) { return m_bMemLeaks; };
+ CValObject *PValObjectFirst( void ) { return m_pValObjectFirst; };
+
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+
+
+private:
+ CValObject *m_pValObjectFirst; // Linked list of all ValObjects
+ CValObject *m_pValObjectLast; // Last ValObject on the linked list
+
+ CValObject *m_pValObjectCur; // Object we're current processing
+
+ int m_cpvOwned; // Total # of blocks owned
+
+ int m_cpubLeaked; // # of leaked memory blocks
+ int m_cubLeaked; // Amount of leaked memory
+ bool m_bMemLeaks; // Has any memory leaked?
+};
+
+
+#endif // DBGFLAG_VALIDATE
+
+
+#endif // VALIDATOR_H
diff --git a/external/vpc/public/tier0/valobject.h b/external/vpc/public/tier0/valobject.h
new file mode 100644
index 0000000..8a2cbf0
--- /dev/null
+++ b/external/vpc/public/tier0/valobject.h
@@ -0,0 +1,72 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: CValObject is used for tracking individual objects that report
+// in to CValidator. Whenever a new object reports in (via CValidator::Push),
+// we create a new CValObject to aggregate stats for it.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VALOBJECT_H
+#define VALOBJECT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#ifdef DBGFLAG_VALIDATE
+class CValObject
+{
+public:
+ // Constructors & destructors
+ CValObject( void ) { };
+ ~CValObject( void );
+
+ void Init( tchar *pchType, void *pvObj, tchar *pchName, CValObject *pValObjectParent,
+ CValObject *pValObjectPrev );
+
+ // Our object has claimed ownership of a memory block
+ void ClaimMemoryBlock( void *pvMem );
+
+ // A child of ours has claimed ownership of a memory block
+ void ClaimChildMemoryBlock( int cubUser );
+
+ // Accessors
+ tchar *PchType( void ) { return m_rgchType; };
+ void *PvObj( void ) { return m_pvObj; };
+ tchar *PchName( void ) { return m_rgchName; };
+ CValObject *PValObjectParent( void ) { return m_pValObjectParent; };
+ int NLevel( void ) { return m_nLevel; };
+ CValObject *PValObjectNext( void ) { return m_pValObjectNext; };
+ int CpubMemSelf( void ) { return m_cpubMemSelf; };
+ int CubMemSelf( void ) { return m_cubMemSelf; };
+ int CpubMemTree( void ) { return m_cpubMemTree; };
+ int CubMemTree( void ) { return m_cubMemTree; };
+ int NUser( void ) { return m_nUser; };
+ void SetNUser( int nUser ) { m_nUser = nUser; };
+ void SetBNewSinceSnapshot( bool bNewSinceSnapshot ) { m_bNewSinceSnapshot = bNewSinceSnapshot; }
+ bool BNewSinceSnapshot( void ) { return m_bNewSinceSnapshot; }
+
+private:
+ bool m_bNewSinceSnapshot; // If this block is new since the snapshot.
+ tchar m_rgchType[64]; // Type of the object we represent
+ tchar m_rgchName[64]; // Name of this particular object
+ void *m_pvObj; // Pointer to the object we represent
+
+ CValObject *m_pValObjectParent; // Our parent object in the tree.
+ int m_nLevel; // Our depth in the tree
+
+ CValObject *m_pValObjectNext; // Next ValObject in the linked list
+
+ int m_cpubMemSelf; // # of memory blocks we own directly
+ int m_cubMemSelf; // Total size of the memory blocks we own directly
+
+ int m_cpubMemTree; // # of memory blocks owned by us and our children
+ int m_cubMemTree; // Total size of the memory blocks owned by us and our children
+
+ int m_nUser; // Field provided for use by our users
+};
+#endif // DBGFLAG_VALIDATE
+
+
+#endif // VALOBJECT_H
diff --git a/external/vpc/public/tier0/valve_off.h b/external/vpc/public/tier0/valve_off.h
new file mode 100644
index 0000000..954a140
--- /dev/null
+++ b/external/vpc/public/tier0/valve_off.h
@@ -0,0 +1,33 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This turns off all Valve-specific #defines. Because we sometimes
+// call external include files from inside .cpp files, we need to
+// wrap those includes like this:
+// #include "tier0/valve_off.h"
+// #include <external.h>
+// #include "tier0/valve_on.h"
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#ifdef STEAM
+
+//-----------------------------------------------------------------------------
+// Unicode-related #defines (see wchartypes.h)
+//-----------------------------------------------------------------------------
+#undef char
+
+
+//-----------------------------------------------------------------------------
+// Memory-related #defines
+//-----------------------------------------------------------------------------
+#undef malloc
+#undef realloc
+#undef _expand
+#undef free
+
+#endif // STEAM
+
+// Allow long to be used in 3rd-party headers
+#undef long \ No newline at end of file
diff --git a/external/vpc/public/tier0/valve_on.h b/external/vpc/public/tier0/valve_on.h
new file mode 100644
index 0000000..03ab0a7
--- /dev/null
+++ b/external/vpc/public/tier0/valve_on.h
@@ -0,0 +1,37 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This turns on all Valve-specific #defines. Because we sometimes
+// call external include files from inside .cpp files, we need to
+// wrap those includes like this:
+// #include "tier0/valve_off.h"
+// #include <external.h>
+// #include "tier0/valve_on.h"
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#ifdef STEAM
+//-----------------------------------------------------------------------------
+// Unicode-related #defines (see wchartypes.h)
+//-----------------------------------------------------------------------------
+#ifdef ENFORCE_WCHAR
+#define char DontUseChar_SeeWcharOn.h
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Memory-related #defines
+//-----------------------------------------------------------------------------
+#define malloc( cub ) HEY_DONT_USE_MALLOC_USE_PVALLOC
+#define realloc( pvOld, cub ) HEY_DONT_USE_REALLOC_USE_PVREALLOC
+#define _expand( pvOld, cub ) HEY_DONT_USE_EXPAND_USE_PVEXPAND
+#define free( pv ) HEY_DONT_USE_FREE_USE_FREEPV
+
+#endif
+
+
+// Long is evil because it's treated differently by different compilers
+#ifdef DISALLOW_USE_OF_LONG
+ #define long long_is_the_devil_stop_using_it_use_int32_or_int64
+#endif
diff --git a/external/vpc/public/tier0/vprof.h b/external/vpc/public/tier0/vprof.h
new file mode 100644
index 0000000..5208e21
--- /dev/null
+++ b/external/vpc/public/tier0/vprof.h
@@ -0,0 +1,1510 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Real-Time Hierarchical Profiling
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VPROF_H
+#define VPROF_H
+
+#include "tier0/dbg.h"
+#include "tier0/fasttimer.h"
+#include "tier0/l2cache.h"
+#include "tier0/threadtools.h"
+#include "tier0/vprof_sn.h"
+
+// VProf is enabled by default in all configurations -except- X360 Retail.
+#if !( defined( _GAMECONSOLE ) && defined( _CERT ) )
+#define VPROF_ENABLED
+#endif
+
+#if defined(_X360) && defined(VPROF_ENABLED)
+
+// PIX is always enabled in PROFILE build on X360
+#ifdef PROFILE
+#define VPROF_PIX 1
+#endif
+
+#include "tier0/pmc360.h"
+#ifndef USE_PIX
+#define VPROF_UNDO_PIX
+#undef _PIX_H_
+#undef PIXBeginNamedEvent
+#undef PIXEndNamedEvent
+#undef PIXSetMarker
+#undef PIXNameThread
+#define USE_PIX
+#include <pix.h>
+#undef USE_PIX
+#else
+#include <pix.h>
+#endif
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+
+// enable this to get detailed nodes beneath budget
+//#define VPROF_LEVEL 1
+
+#if defined(_X360) || defined(_PS3)
+#define VPROF_VXCONSOLE_EXISTS 1
+#endif
+
+#if defined(_X360) && defined(VPROF_PIX)
+#pragma comment( lib, "Xapilibi" )
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Profiling instrumentation macros
+//
+
+#define MAXCOUNTERS 256
+
+
+#ifdef VPROF_ENABLED
+
+#define VPROF_VTUNE_GROUP
+
+#define VPROF( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0)
+#define VPROF_ASSERT_ACCOUNTED( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, true, 0)
+#define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail(name,group, bAssertAccounted, budgetFlags)
+
+#define VPROF_BUDGET( name, group ) VPROF_BUDGET_FLAGS(name, group, BUDGETFLAG_OTHER)
+#define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF_(name, 0, group, false, flags)
+
+#define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag )
+#define VPROF_SCOPE_END() } while (0)
+
+#define VPROF_ONLY( expression ) ( expression )
+
+#define VPROF_ENTER_SCOPE( name ) g_VProfCurrentProfile.EnterScope( name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0 )
+#define VPROF_EXIT_SCOPE() g_VProfCurrentProfile.ExitScope()
+
+#define VPROF_BUDGET_GROUP_ID_UNACCOUNTED 0
+
+
+// Budgetgroup flags. These are used with VPROF_BUDGET_FLAGS.
+// These control which budget panels the groups show up in.
+// If a budget group uses VPROF_BUDGET, it gets the default
+// which is BUDGETFLAG_OTHER.
+#define BUDGETFLAG_CLIENT (1<<0) // Shows up in the client panel.
+#define BUDGETFLAG_SERVER (1<<1) // Shows up in the server panel.
+#define BUDGETFLAG_OTHER (1<<2) // Unclassified (the client shows these but the dedicated server doesn't).
+#define BUDGETFLAG_HIDDEN (1<<15)
+#define BUDGETFLAG_ALL 0xFFFF
+
+
+// NOTE: You can use strings instead of these defines. . they are defined here and added
+// in vprof.cpp so that they are always in the same order.
+#define VPROF_BUDGETGROUP_OTHER_UNACCOUNTED _T("Unaccounted")
+#define VPROF_BUDGETGROUP_WORLD_RENDERING _T("World Rendering")
+#define VPROF_BUDGETGROUP_DISPLACEMENT_RENDERING _T("Displacement_Rendering")
+#define VPROF_BUDGETGROUP_GAME _T("Game")
+#define VPROF_BUDGETGROUP_NPCS _T("NPCs")
+#define VPROF_BUDGETGROUP_SERVER_ANIM _T("Server Animation")
+#define VPROF_BUDGETGROUP_PHYSICS _T("Physics")
+#define VPROF_BUDGETGROUP_STATICPROP_RENDERING _T("Static_Prop_Rendering")
+#define VPROF_BUDGETGROUP_MODEL_RENDERING _T("Other_Model_Rendering")
+#define VPROF_BUDGETGROUP_MODEL_FAST_PATH_RENDERING _T("Fast Path Model Rendering")
+#define VPROF_BUDGETGROUP_BRUSH_FAST_PATH_RENDERING _T("Fast Path Brush Rendering")
+#define VPROF_BUDGETGROUP_BRUSHMODEL_RENDERING _T("Brush_Model_Rendering")
+#define VPROF_BUDGETGROUP_SHADOW_RENDERING _T("Shadow_Rendering")
+#define VPROF_BUDGETGROUP_DETAILPROP_RENDERING _T("Detail_Prop_Rendering")
+#define VPROF_BUDGETGROUP_PARTICLE_RENDERING _T("Particle/Effect_Rendering")
+#define VPROF_BUDGETGROUP_ROPES _T("Ropes")
+#define VPROF_BUDGETGROUP_DLIGHT_RENDERING _T("Dynamic_Light_Rendering")
+#define VPROF_BUDGETGROUP_OTHER_NETWORKING _T("Networking")
+#define VPROF_BUDGETGROUP_CLIENT_ANIMATION _T("Client_Animation")
+#define VPROF_BUDGETGROUP_OTHER_SOUND _T("Sound")
+#define VPROF_BUDGETGROUP_OTHER_VGUI _T("VGUI")
+#define VPROF_BUDGETGROUP_OTHER_FILESYSTEM _T("FileSystem")
+#define VPROF_BUDGETGROUP_PREDICTION _T("Prediction")
+#define VPROF_BUDGETGROUP_INTERPOLATION _T("Interpolation")
+#define VPROF_BUDGETGROUP_SWAP_BUFFERS _T("Swap_Buffers")
+#define VPROF_BUDGETGROUP_PLAYER _T("Player")
+#define VPROF_BUDGETGROUP_OCCLUSION _T("Occlusion")
+#define VPROF_BUDGETGROUP_OVERLAYS _T("Overlays")
+#define VPROF_BUDGETGROUP_TOOLS _T("Tools")
+#define VPROF_BUDGETGROUP_LIGHTCACHE _T("Light_Cache")
+#define VPROF_BUDGETGROUP_DISP_HULLTRACES _T("Displacement_Hull_Traces")
+#define VPROF_BUDGETGROUP_TEXTURE_CACHE _T("Texture_Cache")
+#define VPROF_BUDGETGROUP_REPLAY _T("Replay")
+#define VPROF_BUDGETGROUP_PARTICLE_SIMULATION _T("Particle Simulation")
+#define VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING _T("Flashlight Shadows")
+#define VPROF_BUDGETGROUP_CLIENT_SIM _T("Client Simulation") // think functions, tempents, etc.
+#define VPROF_BUDGETGROUP_STEAM _T("Steam")
+#define VPROF_BUDGETGROUP_CVAR_FIND _T("Cvar_Find")
+#define VPROF_BUDGETGROUP_CLIENTLEAFSYSTEM _T("ClientLeafSystem")
+#define VPROF_BUDGETGROUP_JOBS_COROUTINES _T("Jobs/Coroutines")
+
+#ifdef VPROF_VXCONSOLE_EXISTS
+// update flags
+#define VPROF_UPDATE_BUDGET 0x01 // send budget data every frame
+#define VPROF_UPDATE_TEXTURE_GLOBAL 0x02 // send global texture data every frame
+#define VPROF_UPDATE_TEXTURE_PERFRAME 0x04 // send perframe texture data every frame
+#endif
+
+//-------------------------------------
+
+#ifndef VPROF_LEVEL
+#define VPROF_LEVEL 0
+#endif
+
+#if !defined( VPROF_SN_LEVEL ) && !defined( _CERT )
+#define VPROF_SN_LEVEL 0
+#endif
+
+#define VPROF_0(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 0, group, assertAccounted, budgetFlags);
+
+#if VPROF_LEVEL > 0
+# define VPROF_1(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 1, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 0 && defined( _PS3 )
+# define VPROF_1(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+#if VPROF_LEVEL > 1
+#define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 2, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 1 && defined( _PS3 )
+# define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+#if VPROF_LEVEL > 2
+#define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 3, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 2 && defined( _PS3 )
+# define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+#if VPROF_LEVEL > 3
+#define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 4, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 3 && defined( _PS3 )
+# define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+//-------------------------------------
+
+#ifdef _MSC_VER
+#define VProfCode( code ) \
+ if ( 0 ) \
+ ; \
+ else \
+ { \
+ VPROF( __FUNCTION__ ": " #code ); \
+ code; \
+ }
+#else
+#define VProfCode( code ) \
+ if ( 0 ) \
+ ; \
+ else \
+ { \
+ VPROF( #code ); \
+ code; \
+ }
+#endif
+
+
+//-------------------------------------
+
+#define VPROF_INCREMENT_COUNTER(name,amount) do { static CVProfCounter _counter( name ); _counter.Increment( amount ); } while( 0 )
+#define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) do { static CVProfCounter _counter( name, group ); _counter.Increment( amount ); } while( 0 )
+#define VPROF_SET_COUNTER(name,amount) do { static CVProfCounter _counter( name ); _counter.Set( amount ); } while( 0 )
+#define VPROF_SET_GROUP_COUNTER(name,group,amount) do { static CVProfCounter _counter( name, group ); _counter.Set( amount ); } while( 0 )
+
+#else
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 0 )
+# define VPROF( name ) CVProfSnMarkerScope VProfSn_( name )
+# define VPROF_ASSERT_ACCOUNTED( name ) VPROF( name )
+# define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail( name, group, bAssertAccounted, budgetFlags )
+# define VPROF_0(name,group,assertAccounted,budgetFlags) VPROF( name )
+# define VPROF_BUDGET( name, group ) VPROF( name )
+# define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF( name )
+
+# define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag )
+# define VPROF_SCOPE_END() } while (0)
+
+# define VPROF_ONLY( expression ) ( expression )
+
+# define VPROF_ENTER_SCOPE( name ) g_pfnPushMarker( name )
+# define VPROF_EXIT_SCOPE() g_pfnPopMarker()
+# else
+# define VPROF( name ) ((void)0)
+# define VPROF_ASSERT_ACCOUNTED( name ) ((void)0)
+# define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) ((void)0)
+# define VPROF_0(name,group,assertAccounted,budgetFlags) ((void)0)
+# define VPROF_BUDGET( name, group ) ((void)0)
+# define VPROF_BUDGET_FLAGS( name, group, flags ) ((void)0)
+
+# define VPROF_SCOPE_BEGIN( tag ) do {
+# define VPROF_SCOPE_END() } while (0)
+
+# define VPROF_ONLY( expression ) ((void)0)
+
+# define VPROF_ENTER_SCOPE( name )
+# define VPROF_EXIT_SCOPE()
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 1 )
+# define VPROF_1(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 2 )
+# define VPROF_2(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 3 )
+# define VPROF_3(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 4 )
+# define VPROF_4(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+
+
+#define VPROF_INCREMENT_COUNTER(name,amount) ((void)0)
+#define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) ((void)0)
+#define VPROF_SET_COUNTER(name,amount) ((void)0)
+#define VPROF_SET_GROUP_COUNTER(name,group,amount) ((void)0)
+
+#define VPROF_TEST_SPIKE( msec ) ((void)0)
+
+#define VProfCode( code ) code
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifdef VPROF_ENABLED
+
+//-----------------------------------------------------------------------------
+//
+// A node in the call graph hierarchy
+//
+
+class PLATFORM_CLASS CVProfNode
+{
+friend class CVProfRecorder;
+friend class CVProfile;
+
+public:
+ CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags );
+ ~CVProfNode();
+
+ CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, int budgetFlags );
+ CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName );
+ CVProfNode *GetParent();
+ CVProfNode *GetSibling();
+ CVProfNode *GetPrevSibling();
+ CVProfNode *GetChild();
+
+ void MarkFrame();
+ void ResetPeak();
+
+ void Pause();
+ void Resume();
+ void Reset();
+
+ void EnterScope();
+ bool ExitScope();
+
+ const tchar *GetName();
+
+ int GetBudgetGroupID()
+ {
+ return m_BudgetGroupID;
+ }
+
+ // Only used by the record/playback stuff.
+ void SetBudgetGroupID( int id )
+ {
+ m_BudgetGroupID = id;
+ }
+
+ int GetCurCalls();
+ double GetCurTime();
+ int GetPrevCalls();
+ double GetPrevTime();
+ int GetTotalCalls();
+ double GetTotalTime();
+ double GetPeakTime();
+
+ double GetCurTimeLessChildren();
+ double GetPrevTimeLessChildren();
+ double GetTotalTimeLessChildren();
+
+ int GetPrevL2CacheMissLessChildren();
+ int GetPrevLoadHitStoreLessChildren();
+
+ void ClearPrevTime();
+
+ int GetL2CacheMisses();
+
+ // Not used in the common case...
+ void SetCurFrameTime( unsigned long milliseconds );
+
+ void SetClientData( int iClientData ) { m_iClientData = iClientData; }
+ int GetClientData() const { return m_iClientData; }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+
+// Used by vprof record/playback.
+private:
+
+ void SetUniqueNodeID( int id )
+ {
+ m_iUniqueNodeID = id;
+ }
+
+ int GetUniqueNodeID() const
+ {
+ return m_iUniqueNodeID;
+ }
+
+ static int s_iCurrentUniqueNodeID;
+
+
+private:
+ const tchar *m_pszName;
+ CFastTimer m_Timer;
+
+ // L2 Cache data.
+ int m_iPrevL2CacheMiss;
+ int m_iCurL2CacheMiss;
+ int m_iTotalL2CacheMiss;
+
+#ifndef _X360
+ // L2 Cache data.
+ CL2Cache m_L2Cache;
+#else // 360:
+
+ unsigned int m_iBitFlags; // see enum below for settings
+ CPMCData m_PMCData;
+ int m_iPrevLoadHitStores;
+ int m_iCurLoadHitStores;
+ int m_iTotalLoadHitStores;
+
+ public:
+ enum FlagBits
+ {
+ kRecordL2 = 0x01,
+ kCPUTrace = 0x02, ///< cause a PIX trace inside this node.
+ };
+ // call w/ true to enable L2 and LHS recording; false to turn it off
+ inline void EnableL2andLHS(bool enable)
+ {
+ if (enable)
+ m_iBitFlags |= kRecordL2;
+ else
+ m_iBitFlags &= (~kRecordL2);
+ }
+
+ inline bool IsL2andLHSEnabled( void )
+ {
+ return (m_iBitFlags & kRecordL2) != 0;
+ }
+
+ int GetLoadHitStores();
+
+ private:
+
+#endif
+
+ int m_nRecursions;
+
+ unsigned m_nCurFrameCalls;
+ CCycleCount m_CurFrameTime;
+
+ unsigned m_nPrevFrameCalls;
+ CCycleCount m_PrevFrameTime;
+
+ unsigned m_nTotalCalls;
+ CCycleCount m_TotalTime;
+
+ CCycleCount m_PeakTime;
+
+ CVProfNode *m_pParent;
+ CVProfNode *m_pChild;
+ CVProfNode *m_pSibling;
+
+ int m_BudgetGroupID;
+
+ int m_iClientData;
+ int m_iUniqueNodeID;
+};
+
+//-----------------------------------------------------------------------------
+//
+// Coordinator and root node of the profile hierarchy tree
+//
+
+enum VProfReportType_t
+{
+ VPRT_SUMMARY = ( 1 << 0 ),
+ VPRT_HIERARCHY = ( 1 << 1 ),
+ VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY = ( 1 << 2 ),
+ VPRT_LIST_BY_TIME = ( 1 << 3 ),
+ VPRT_LIST_BY_TIME_LESS_CHILDREN = ( 1 << 4 ),
+ VPRT_LIST_BY_AVG_TIME = ( 1 << 5 ),
+ VPRT_LIST_BY_AVG_TIME_LESS_CHILDREN = ( 1 << 6 ),
+ VPRT_LIST_BY_PEAK_TIME = ( 1 << 7 ),
+ VPRT_LIST_BY_PEAK_OVER_AVERAGE = ( 1 << 8 ),
+ VPRT_LIST_TOP_ITEMS_ONLY = ( 1 << 9 ),
+
+ VPRT_FULL = (0xffffffff & ~(VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY|VPRT_LIST_TOP_ITEMS_ONLY)),
+};
+
+enum CounterGroup_t
+{
+ COUNTER_GROUP_DEFAULT=0,
+ COUNTER_GROUP_NO_RESET, // The engine doesn't reset these counters. Usually, they are used
+ // like global variables that can be accessed across modules.
+ COUNTER_GROUP_TEXTURE_GLOBAL, // Global texture usage counters (totals for what is currently in memory).
+ COUNTER_GROUP_TEXTURE_PER_FRAME, // Per-frame texture usage counters.
+ COUNTER_GROUP_GRAPHICS_PER_FRAME, // Misc graphics counters that are reset each frame
+};
+
+class PLATFORM_CLASS CVProfile
+{
+public:
+ CVProfile();
+ ~CVProfile();
+
+ void Term();
+
+ //
+ // Runtime operations
+ //
+
+ void Start();
+ void Stop();
+
+ void SetTargetThreadId( unsigned id ) { m_TargetThreadId = id; }
+ unsigned GetTargetThreadId() { return m_TargetThreadId; }
+ bool InTargetThread() { return ( m_TargetThreadId == ThreadGetCurrentId() ); }
+
+#ifdef VPROF_VXCONSOLE_EXISTS
+ enum VXConsoleReportMode_t
+ {
+ VXCONSOLE_REPORT_TIME = 0,
+ VXCONSOLE_REPORT_L2CACHE_MISSES,
+ VXCONSOLE_REPORT_LOAD_HIT_STORE,
+ VXCONSOLE_REPORT_COUNT,
+ };
+
+ void VXProfileStart();
+ void VXProfileUpdate();
+ void VXEnableUpdateMode( int event, bool bEnable );
+ void VXSendNodes( void );
+
+ void PMCDisableAllNodes(CVProfNode *pStartNode = NULL); ///< turn off l2 and lhs recording for everywhere
+ bool PMCEnableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node
+ bool PMCDisableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node
+
+ void DumpEnabledPMCNodes( void );
+
+ void VXConsoleReportMode( VXConsoleReportMode_t mode );
+ void VXConsoleReportScale( VXConsoleReportMode_t mode, float flScale );
+#endif
+
+#ifdef _X360
+
+
+ // the CPU trace mode is actually a small state machine; it can be off, primed for
+ // single capture, primed for everything-in-a-frame capture, or currently in everything-in-a-frame
+ // capture.
+ enum CPUTraceState
+ {
+ kDisabled,
+ kFirstHitNode, // record from the first time we hit the node until that node ends
+ kAllNodesInFrame_WaitingForMark, // we're going to record all the times a node is hit in a frame, but are waiting for the frame to start
+ kAllNodesInFrame_Recording, // we're recording all hits on a node this frame.
+
+ // Same as above, but going to record for > 1 frame
+ kAllNodesInFrame_WaitingForMarkMultiFrame, // we're going to record all the times a node is hit in a frame, but are waiting for the frame to start
+ kAllNodesInFrame_RecordingMultiFrame,
+ };
+
+ // Global switch to turn CPU tracing on or off at all. The idea is you set up a node first,
+ // then trigger tracing by throwing this to true. It'll reset back to false after the trace
+ // happens.
+ inline CPUTraceState GetCPUTraceMode();
+ inline void SetCPUTraceEnabled( CPUTraceState enabled, bool bTraceCompleteEvent = false, int nNumFrames = -1 );
+ inline void IncrementMultiTraceIndex(); // tick up the counter that gets appended to the multi-per-frame traces
+ inline unsigned int GetMultiTraceIndex(); // return the counter
+ void CPUTraceDisableAllNodes( CVProfNode *pStartNode = NULL ); // disable the cpu trace flag wherever it may be
+ CVProfNode *CPUTraceEnableForNode( const tchar *pszNodeName ); // enable cpu trace on this node only, disabling it wherever else it may be on.
+ CVProfNode *CPUTraceGetEnabledNode( CVProfNode *pStartNode = NULL ); // return the node enabled for CPU tracing, or NULL.
+ const char *GetCPUTraceFilename(); // get the filename the trace should write into.
+ const char *SetCPUTraceFilename( const char *filename ); // set the filename the trace should write into. (don't specify the extension; I'll do that.)
+ inline bool TraceCompleteEvent( void );
+
+#ifdef _X360
+ void LatchMultiFrame( int64 cycles );
+ void SpewWorstMultiFrame();
+#endif
+
+#endif
+
+ void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted );
+ void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags );
+ void ExitScope();
+
+ void MarkFrame();
+ void ResetPeaks();
+
+ void Pause();
+ void Resume();
+ void Reset();
+
+ bool IsEnabled() const;
+ int GetDetailLevel() const;
+
+ bool AtRoot() const;
+
+ //
+ // Queries
+ //
+
+#ifdef VPROF_VTUNE_GROUP
+# define MAX_GROUP_STACK_DEPTH 1024
+
+ void EnableVTuneGroup( const tchar *pGroupName )
+ {
+ m_nVTuneGroupID = BudgetGroupNameToBudgetGroupID( pGroupName );
+ m_bVTuneGroupEnabled = true;
+ }
+ void DisableVTuneGroup( void )
+ {
+ m_bVTuneGroupEnabled = false;
+ }
+
+ inline void PushGroup( int nGroupID );
+ inline void PopGroup( void );
+#endif
+
+ int NumFramesSampled() { return m_nFrames; }
+ double GetPeakFrameTime();
+ double GetTotalTimeSampled();
+ double GetTimeLastFrame();
+
+ CVProfNode *GetRoot();
+ CVProfNode *FindNode( CVProfNode *pStartNode, const tchar *pszNode );
+ CVProfNode *GetCurrentNode();
+
+ void OutputReport( int type = VPRT_FULL, const tchar *pszStartNode = NULL, int budgetGroupID = -1 );
+
+ const tchar *GetBudgetGroupName( int budgetGroupID );
+ int GetBudgetGroupFlags( int budgetGroupID ) const; // Returns a combination of BUDGETFLAG_ defines.
+ int GetNumBudgetGroups( void );
+ void GetBudgetGroupColor( int budgetGroupID, int &r, int &g, int &b, int &a );
+ int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName );
+ int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName, int budgetFlagsToORIn );
+ void RegisterNumBudgetGroupsChangedCallBack( void (*pCallBack)(void) );
+
+ int BudgetGroupNameToBudgetGroupIDNoCreate( const tchar *pBudgetGroupName ) { return FindBudgetGroupName( pBudgetGroupName ); }
+
+ void HideBudgetGroup( int budgetGroupID, bool bHide = true );
+ void HideBudgetGroup( const tchar *pszName, bool bHide = true ) { HideBudgetGroup( BudgetGroupNameToBudgetGroupID( pszName), bHide ); }
+
+ int *FindOrCreateCounter( const tchar *pName, CounterGroup_t eCounterGroup=COUNTER_GROUP_DEFAULT );
+ void ResetCounters( CounterGroup_t eCounterGroup );
+
+ int GetNumCounters( void ) const;
+
+ const tchar *GetCounterName( int index ) const;
+ int GetCounterValue( int index ) const;
+ const tchar *GetCounterNameAndValue( int index, int &val ) const;
+ CounterGroup_t GetCounterGroup( int index ) const;
+
+ // Performance monitoring events.
+ void PMEInitialized( bool bInit ) { m_bPMEInit = bInit; }
+ void PMEEnable( bool bEnable ) { m_bPMEEnabled = bEnable; }
+
+#ifdef _X360
+ bool UsePME( void ) { return ( CPMCData::IsInitialized() && m_bPMEEnabled ); }
+#elif defined( _PS3 )
+ inline bool UsePME( void ) { return false; }
+#else
+ bool UsePME( void ) { return ( m_bPMEInit && m_bPMEEnabled ); }
+#endif
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+protected:
+
+ void FreeNodes_R( CVProfNode *pNode );
+
+#ifdef VPROF_VTUNE_GROUP
+ bool VTuneGroupEnabled()
+ {
+ return m_bVTuneGroupEnabled;
+ }
+ int VTuneGroupID()
+ {
+ return m_nVTuneGroupID;
+ }
+#endif
+
+ void SumTimes( const tchar *pszStartNode, int budgetGroupID );
+ void SumTimes( CVProfNode *pNode, int budgetGroupID );
+ void DumpNodes( CVProfNode *pNode, int indent, bool bAverageAndCountOnly );
+ int FindBudgetGroupName( const tchar *pBudgetGroupName );
+ int AddBudgetGroupName( const tchar *pBudgetGroupName, int budgetFlags );
+
+#ifdef VPROF_VTUNE_GROUP
+ bool m_bVTuneGroupEnabled;
+ int m_nVTuneGroupID;
+ int m_GroupIDStack[MAX_GROUP_STACK_DEPTH];
+ int m_GroupIDStackDepth;
+#endif
+ int m_enabled;
+ bool m_fAtRoot; // tracked for efficiency of the "not profiling" case
+ CVProfNode *m_pCurNode;
+ CVProfNode m_Root;
+ int m_nFrames;
+ int m_ProfileDetailLevel;
+ int m_pausedEnabledDepth;
+
+ class CBudgetGroup
+ {
+ public:
+ tchar *m_pName;
+ int m_BudgetFlags;
+ };
+
+ CBudgetGroup *m_pBudgetGroups;
+ int m_nBudgetGroupNamesAllocated;
+ int m_nBudgetGroupNames;
+ void (*m_pNumBudgetGroupsChangedCallBack)(void);
+
+ // Performance monitoring events.
+ bool m_bPMEInit;
+ bool m_bPMEEnabled;
+
+ int m_Counters[MAXCOUNTERS];
+ char m_CounterGroups[MAXCOUNTERS]; // (These are CounterGroup_t's).
+ tchar *m_CounterNames[MAXCOUNTERS];
+ int m_NumCounters;
+
+#ifdef VPROF_VXCONSOLE_EXISTS
+ int m_UpdateMode;
+ int m_nFramesRemaining;
+ int m_nFrameCount;
+ int64 m_WorstCycles;
+ char m_WorstTraceFilename[128];
+ char m_CPUTraceFilename[128];
+ unsigned int m_iSuccessiveTraceIndex;
+ VXConsoleReportMode_t m_ReportMode;
+ float m_pReportScale[VXCONSOLE_REPORT_COUNT];
+ bool m_bTraceCompleteEvent;
+#endif
+#ifdef _X360
+ CPUTraceState m_iCPUTraceEnabled;
+#endif
+
+ unsigned m_TargetThreadId;
+};
+
+//-------------------------------------
+
+PLATFORM_INTERFACE CVProfile g_VProfCurrentProfile;
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE bool g_VProfSignalSpike;
+
+class CVProfSpikeDetector
+{
+public:
+ CVProfSpikeDetector( float spike ) :
+ m_timeLast( GetTimeLast() )
+ {
+ m_spike = spike;
+ m_Timer.Start();
+ }
+
+ ~CVProfSpikeDetector()
+ {
+ m_Timer.End();
+ if ( Plat_FloatTime() - m_timeLast > 2.0 )
+ {
+ m_timeLast = Plat_FloatTime();
+ if ( m_Timer.GetDuration().GetMillisecondsF() > m_spike )
+ {
+ g_VProfSignalSpike = true;
+ }
+ }
+ }
+
+private:
+ static float &GetTimeLast() { static float timeLast = 0; return timeLast; }
+ CFastTimer m_Timer;
+ float m_spike;
+ float &m_timeLast;
+};
+
+
+// Macro to signal a local spike. Meant as temporary instrumentation, do not leave in code
+#define VPROF_TEST_SPIKE( msec ) CVProfSpikeDetector UNIQUE_ID( msec )
+
+//-----------------------------------------------------------------------------
+
+#ifdef VPROF_VTUNE_GROUP
+inline void CVProfile::PushGroup( int nGroupID )
+{
+ // There is always at least one item on the stack since we force
+ // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED.
+ Assert( m_GroupIDStackDepth > 0 );
+ Assert( m_GroupIDStackDepth < MAX_GROUP_STACK_DEPTH );
+ m_GroupIDStack[m_GroupIDStackDepth] = nGroupID;
+ m_GroupIDStackDepth++;
+ if( m_GroupIDStack[m_GroupIDStackDepth-2] != nGroupID &&
+ VTuneGroupEnabled() &&
+ nGroupID == VTuneGroupID() )
+ {
+ vtune( true );
+ }
+}
+#endif // VPROF_VTUNE_GROUP
+
+#ifdef VPROF_VTUNE_GROUP
+inline void CVProfile::PopGroup( void )
+{
+ m_GroupIDStackDepth--;
+ // There is always at least one item on the stack since we force
+ // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED.
+ Assert( m_GroupIDStackDepth > 0 );
+ if( m_GroupIDStack[m_GroupIDStackDepth] != m_GroupIDStack[m_GroupIDStackDepth+1] &&
+ VTuneGroupEnabled() &&
+ m_GroupIDStack[m_GroupIDStackDepth+1] == VTuneGroupID() )
+ {
+ vtune( false );
+ }
+}
+#endif // VPROF_VTUNE_GROUP
+
+//-----------------------------------------------------------------------------
+
+
+class CVProfScope: public CVProfSnMarkerScope
+{
+public:
+ CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags );
+ ~CVProfScope();
+
+private:
+ bool m_bEnabled;
+};
+
+//-----------------------------------------------------------------------------
+//
+// CVProfNode, inline methods
+//
+
+inline CVProfNode::CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags )
+ : m_pszName( pszName ),
+ m_nCurFrameCalls( 0 ),
+ m_nPrevFrameCalls( 0 ),
+ m_nRecursions( 0 ),
+ m_pParent( pParent ),
+ m_pChild( NULL ),
+ m_pSibling( NULL ),
+ m_iClientData( -1 )
+#ifdef _X360
+ , m_iBitFlags( 0 )
+#endif
+{
+ m_iUniqueNodeID = s_iCurrentUniqueNodeID++;
+
+ if ( m_iUniqueNodeID > 0 )
+ {
+ m_BudgetGroupID = g_VProfCurrentProfile.BudgetGroupNameToBudgetGroupID( pBudgetGroupName, budgetFlags );
+ }
+ else
+ {
+ m_BudgetGroupID = 0; // "m_Root" can't call BudgetGroupNameToBudgetGroupID because g_VProfCurrentProfile not yet initialized
+ }
+
+ Reset();
+
+ if( m_pParent && ( m_BudgetGroupID == VPROF_BUDGET_GROUP_ID_UNACCOUNTED ) )
+ {
+ m_BudgetGroupID = m_pParent->GetBudgetGroupID();
+ }
+}
+
+
+//-------------------------------------
+
+inline CVProfNode *CVProfNode::GetParent()
+{
+ Assert( m_pParent );
+ return m_pParent;
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfNode::GetSibling()
+{
+ return m_pSibling;
+}
+
+//-------------------------------------
+// Hacky way to the previous sibling, only used from vprof panel at the moment,
+// so it didn't seem like it was worth the memory waste to add the reverse
+// link per node.
+
+inline CVProfNode *CVProfNode::GetPrevSibling()
+{
+ CVProfNode* p = GetParent();
+
+ if(!p)
+ return NULL;
+
+ CVProfNode* s;
+ for( s = p->GetChild();
+ s && ( s->GetSibling() != this );
+ s = s->GetSibling() )
+ ;
+
+ return s;
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfNode::GetChild()
+{
+ return m_pChild;
+}
+
+//-------------------------------------
+
+inline const tchar *CVProfNode::GetName()
+{
+ return m_pszName;
+}
+
+//-------------------------------------
+
+inline int CVProfNode::GetTotalCalls()
+{
+ return m_nTotalCalls;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetTotalTime()
+{
+ return m_TotalTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline int CVProfNode::GetCurCalls()
+{
+ return m_nCurFrameCalls;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetCurTime()
+{
+ return m_CurFrameTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline int CVProfNode::GetPrevCalls()
+{
+ return m_nPrevFrameCalls;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetPrevTime()
+{
+ return m_PrevFrameTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetPeakTime()
+{
+ return m_PeakTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetTotalTimeLessChildren()
+{
+ double result = GetTotalTime();
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->GetTotalTime();
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetCurTimeLessChildren()
+{
+ double result = GetCurTime();
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->GetCurTime();
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+inline double CVProfNode::GetPrevTimeLessChildren()
+{
+ double result = GetPrevTime();
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->GetPrevTime();
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+inline int CVProfNode::GetPrevL2CacheMissLessChildren()
+{
+ int result = m_iPrevL2CacheMiss;
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->m_iPrevL2CacheMiss;
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+inline int CVProfNode::GetPrevLoadHitStoreLessChildren()
+{
+#ifndef _X360
+ return 0;
+#else
+ int result = m_iPrevLoadHitStores;
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->m_iPrevLoadHitStores;
+ pChild = pChild->GetSibling();
+ }
+ return result;
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+inline void CVProfNode::ClearPrevTime()
+{
+ m_PrevFrameTime.Init();
+}
+
+//-----------------------------------------------------------------------------
+inline int CVProfNode::GetL2CacheMisses( void )
+{
+#ifndef _X360
+ return m_L2Cache.GetL2CacheMisses();
+#else
+ return m_iTotalL2CacheMiss;
+#endif
+}
+
+#ifdef _X360
+inline int CVProfNode::GetLoadHitStores( void )
+{
+ return m_iTotalLoadHitStores;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// CVProfile, inline methods
+//
+
+//-------------------------------------
+
+inline bool CVProfile::IsEnabled() const
+{
+ return ( m_enabled != 0 );
+}
+
+//-------------------------------------
+
+inline int CVProfile::GetDetailLevel() const
+{
+ return m_ProfileDetailLevel;
+}
+
+
+//-------------------------------------
+
+inline bool CVProfile::AtRoot() const
+{
+ return m_fAtRoot;
+}
+
+//-------------------------------------
+
+inline void CVProfile::Start()
+{
+ if ( ++m_enabled == 1 )
+ {
+ m_Root.EnterScope();
+#ifdef VPROF_VXCONSOLE_EXISTS
+ VXProfileStart();
+#endif
+#ifdef _X360
+ CPMCData::InitializeOnceProgramWide();
+#endif
+ }
+}
+
+//-------------------------------------
+
+inline void CVProfile::Stop()
+{
+ if ( --m_enabled == 0 )
+ m_Root.ExitScope();
+}
+
+//-------------------------------------
+
+inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags )
+{
+ if ( ( m_enabled != 0 || !m_fAtRoot ) && InTargetThread() ) // if became disabled, need to unwind back to root before stopping
+ {
+ // Only account for vprof stuff on the primary thread.
+ //if( !Plat_IsPrimaryThread() )
+ // return;
+
+ if ( pszName != m_pCurNode->GetName() )
+ {
+ m_pCurNode = m_pCurNode->GetSubNode( pszName, detailLevel, pBudgetGroupName, budgetFlags );
+ }
+ m_pBudgetGroups[m_pCurNode->GetBudgetGroupID()].m_BudgetFlags |= budgetFlags;
+
+#if defined( _DEBUG ) && !defined( _X360 )
+ // 360 doesn't want this to allow tier0 debug/release .def files to match
+ if ( bAssertAccounted )
+ {
+ // FIXME
+ AssertOnce( m_pCurNode->GetBudgetGroupID() != 0 );
+ }
+#endif
+ m_pCurNode->EnterScope();
+ m_fAtRoot = false;
+ }
+#if defined(_X360) && defined(VPROF_PIX)
+ if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
+ PIXBeginNamedEvent( 0, pszName );
+#endif
+}
+
+inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted )
+{
+ EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, BUDGETFLAG_OTHER );
+}
+
+//-------------------------------------
+
+inline void CVProfile::ExitScope()
+{
+#if defined(_X360) && defined(VPROF_PIX)
+/*
+#ifdef PIXBeginNamedEvent
+#error
+#endif
+*/
+ if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
+ PIXEndNamedEvent();
+#endif
+ if ( ( !m_fAtRoot || m_enabled != 0 ) && InTargetThread() )
+ {
+ // Only account for vprof stuff on the primary thread.
+ //if( !Plat_IsPrimaryThread() )
+ // return;
+
+ // ExitScope will indicate whether we should back up to our parent (we may
+ // be profiling a recursive function)
+ if (m_pCurNode->ExitScope())
+ {
+ m_pCurNode = m_pCurNode->GetParent();
+ }
+ m_fAtRoot = ( m_pCurNode == &m_Root );
+ }
+}
+
+//-------------------------------------
+
+inline void CVProfile::Pause()
+{
+ m_pausedEnabledDepth = m_enabled;
+ m_enabled = 0;
+ if ( !AtRoot() )
+ m_Root.Pause();
+}
+
+//-------------------------------------
+
+inline void CVProfile::Resume()
+{
+ m_enabled = m_pausedEnabledDepth;
+ if ( !AtRoot() )
+ m_Root.Resume();
+}
+
+//-------------------------------------
+
+inline void CVProfile::Reset()
+{
+ m_Root.Reset();
+ m_nFrames = 0;
+}
+
+//-------------------------------------
+
+inline void CVProfile::ResetPeaks()
+{
+ m_Root.ResetPeak();
+}
+
+//-------------------------------------
+
+inline void CVProfile::MarkFrame()
+{
+ if ( m_enabled )
+ {
+ ++m_nFrames;
+ m_Root.ExitScope();
+ m_Root.MarkFrame();
+ m_Root.EnterScope();
+
+#ifdef _X360
+ // update the CPU trace state machine if enabled
+ switch ( GetCPUTraceMode() )
+ {
+ case kAllNodesInFrame_WaitingForMark:
+ // mark! Start recording a zillion traces.
+ m_iCPUTraceEnabled = kAllNodesInFrame_Recording;
+ break;
+ case kAllNodesInFrame_WaitingForMarkMultiFrame:
+ m_iCPUTraceEnabled = kAllNodesInFrame_RecordingMultiFrame;
+ break;
+ case kAllNodesInFrame_Recording:
+ // end of frame. stop recording if no more frames needed
+ m_iCPUTraceEnabled = kDisabled;
+ Msg("Frame ended. Recording no more CPU traces\n");
+
+ break;
+ case kAllNodesInFrame_RecordingMultiFrame:
+ // end of frame. stop recording if no more frames needed
+ if ( --m_nFramesRemaining == 0 )
+ {
+ m_iCPUTraceEnabled = kDisabled;
+ Msg("Frames ended. Recording no more CPU traces\n");
+
+ SpewWorstMultiFrame();
+ }
+
+ ++m_nFrameCount;
+
+ break;
+ default:
+ // no default
+ break;
+ }
+#endif
+ }
+}
+
+//-------------------------------------
+
+inline double CVProfile::GetTotalTimeSampled()
+{
+ return m_Root.GetTotalTime();
+}
+
+//-------------------------------------
+
+inline double CVProfile::GetPeakFrameTime()
+{
+ return m_Root.GetPeakTime();
+}
+
+//-------------------------------------
+
+inline double CVProfile::GetTimeLastFrame()
+{
+ return m_Root.GetCurTime();
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfile::GetRoot()
+{
+ return &m_Root;
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfile::GetCurrentNode()
+{
+ return m_pCurNode;
+}
+
+
+inline const tchar *CVProfile::GetBudgetGroupName( int budgetGroupID )
+{
+ Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames );
+ return m_pBudgetGroups[budgetGroupID].m_pName;
+}
+
+inline int CVProfile::GetBudgetGroupFlags( int budgetGroupID ) const
+{
+ Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames );
+ return m_pBudgetGroups[budgetGroupID].m_BudgetFlags;
+}
+
+#ifdef _X360
+
+inline CVProfile::CPUTraceState CVProfile::GetCPUTraceMode()
+{
+ return m_iCPUTraceEnabled;
+}
+
+inline void CVProfile::SetCPUTraceEnabled( CPUTraceState enabled, bool bTraceCompleteEvent /*=true*/, int nNumFrames /*= -1*/ )
+{
+ m_iCPUTraceEnabled = enabled;
+ m_bTraceCompleteEvent = bTraceCompleteEvent;
+ if ( nNumFrames != -1 )
+ {
+ m_nFramesRemaining = nNumFrames;
+ m_nFrameCount = 0;
+ m_WorstCycles = 0;
+ m_WorstTraceFilename[ 0 ] = 0;
+ }
+}
+
+inline void CVProfile::IncrementMultiTraceIndex()
+{
+ ++m_iSuccessiveTraceIndex;
+}
+
+inline unsigned int CVProfile::GetMultiTraceIndex()
+{
+ return m_iSuccessiveTraceIndex;
+}
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+
+inline CVProfScope::CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ):
+ CVProfSnMarkerScope( pszName ),
+ m_bEnabled( g_VProfCurrentProfile.IsEnabled() )
+{
+ if ( m_bEnabled )
+ {
+ g_VProfCurrentProfile.EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, budgetFlags );
+ }
+}
+
+//-------------------------------------
+
+inline CVProfScope::~CVProfScope()
+{
+ if ( m_bEnabled )
+ {
+ g_VProfCurrentProfile.ExitScope();
+ }
+}
+
+class CVProfCounter
+{
+public:
+ CVProfCounter( const tchar *pName, CounterGroup_t group=COUNTER_GROUP_DEFAULT )
+ {
+ m_pCounter = g_VProfCurrentProfile.FindOrCreateCounter( pName, group );
+ Assert( m_pCounter );
+ }
+ ~CVProfCounter()
+ {
+ }
+ void Increment( int val )
+ {
+ Assert( m_pCounter );
+ *m_pCounter += val;
+ }
+ void Set( int val )
+ {
+ Assert( m_pCounter );
+ *m_pCounter = val;
+ }
+private:
+ int *m_pCounter;
+};
+
+#endif
+
+#ifdef _X360
+
+#include "xbox/xbox_console.h"
+#include "tracerecording.h"
+#include "tier1/fmtstr.h"
+#pragma comment( lib, "tracerecording.lib" )
+#pragma comment( lib, "xbdm.lib" )
+
+class CPIXRecorder
+{
+public:
+ CPIXRecorder() : m_bActive( false ) {}
+ ~CPIXRecorder() { Stop(); }
+
+ void Start( const char *pszFilename = "capture" )
+ {
+ if ( !m_bActive )
+ {
+ if ( !XTraceStartRecording( CFmtStr( "e:\\%s.pix2", pszFilename ) ) )
+ {
+ Msg( "XTraceStartRecording failed, error code %d\n", GetLastError() );
+ }
+ else
+ {
+ m_bActive = true;
+ }
+ }
+ }
+
+ void Stop()
+ {
+ if ( m_bActive )
+ {
+ m_bActive = false;
+ if ( XTraceStopRecording() )
+ {
+ Msg( "CPU trace finished.\n" );
+ // signal VXConsole that trace is completed
+ XBX_rTraceComplete();
+ }
+ }
+ }
+
+private:
+ bool m_bActive;
+};
+
+#define VPROF_BEGIN_PIX_BLOCK( convar ) \
+ { \
+ bool bRunPix = 0; \
+ static CFastTimer PIXTimer; \
+ extern ConVar convar; \
+ ConVar &PIXConvar = convar; \
+ CPIXRecorder PIXRecorder; \
+ { \
+ PIXLabel: \
+ if ( bRunPix ) \
+ { \
+ PIXRecorder.Start(); \
+ } \
+ else \
+ { \
+ if ( PIXConvar.GetBool() ) \
+ { \
+ PIXTimer.Start(); \
+ } \
+ } \
+ {
+
+
+#define VPROF_END_PIX_BLOCK() \
+ } \
+ \
+ if ( !bRunPix ) \
+ { \
+ if ( PIXConvar.GetBool() ) \
+ { \
+ PIXTimer.End(); \
+ if ( PIXTimer.GetDuration().GetMillisecondsF() > PIXConvar.GetFloat() ) \
+ { \
+ PIXConvar.SetValue( 0 ); \
+ bRunPix = true; \
+ goto PIXLabel; \
+ } \
+ } \
+ } \
+ else \
+ { \
+ PIXRecorder.Stop(); \
+ } \
+ } \
+ }
+#else
+#define VPROF_BEGIN_PIX_BLOCK( PIXConvar ) {
+#define VPROF_END_PIX_BLOCK() }
+#endif
+
+
+#ifdef VPROF_UNDO_PIX
+#undef USE_PIX
+#undef _PIX_H_
+#undef PIXBeginNamedEvent
+#undef PIXEndNamedEvent
+#undef PIXSetMarker
+#undef PIXNameThread
+#include <pix.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
+
+//=============================================================================
diff --git a/external/vpc/public/tier0/vprof_sn.h b/external/vpc/public/tier0/vprof_sn.h
new file mode 100644
index 0000000..ecf776f
--- /dev/null
+++ b/external/vpc/public/tier0/vprof_sn.h
@@ -0,0 +1,31 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+#ifndef TIER_V0PROF_SN_HDR
+#define TIER_V0PROF_SN_HDR
+
+// enable this to get detailed SN Tuner markers. PS3 specific
+#if defined( SN_TARGET_PS3 ) && !defined(_CERT)
+#define VPROF_SN_LEVEL 0
+
+extern "C" void(*g_pfnPushMarker)( const char * pName );
+extern "C" void(*g_pfnPopMarker)();
+
+class CVProfSnMarkerScope
+{
+public:
+ CVProfSnMarkerScope( const char * pszName )
+ {
+ g_pfnPushMarker( pszName );
+ }
+ ~CVProfSnMarkerScope()
+ {
+ g_pfnPopMarker( );
+ }
+};
+
+#else
+
+class CVProfSnMarkerScope { public: CVProfSnMarkerScope( const char * ) {} };
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/external/vpc/public/tier0/wchartypes.h b/external/vpc/public/tier0/wchartypes.h
new file mode 100644
index 0000000..8446b68
--- /dev/null
+++ b/external/vpc/public/tier0/wchartypes.h
@@ -0,0 +1,101 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: All of our code is completely Unicode. Instead of char, you should
+// use wchar, uint8, or char8, as explained below.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#ifndef WCHARTYPES_H
+#define WCHARTYPES_H
+#ifdef _WIN32
+#pragma once
+#endif
+#include "stddef.h"
+#ifdef _INC_TCHAR
+#error ("Must include tier0 type headers before tchar.h")
+#endif
+
+// Temporarily turn off Valve defines
+#include "tier0/valve_off.h"
+
+#if !defined(_WCHAR_T_DEFINED) && !defined( __WCHAR_TYPE__ ) && !defined(GNUC)
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+// char8
+// char8 is equivalent to char, and should be used when you really need a char
+// (for example, when calling an external function that's declared to take
+// chars).
+typedef char char8;
+
+// uint8
+// uint8 is equivalent to byte (but is preferred over byte for clarity). Use this
+// whenever you mean a byte (for example, one byte of a network packet).
+// uint8 itself is defined in platform.h
+typedef unsigned char BYTE;
+typedef unsigned char byte;
+
+// wchar
+// wchar is a single character of text (currently 16 bits, as all of our text is
+// Unicode). Use this whenever you mean a piece of text (for example, in a string).
+typedef wchar_t wchar;
+//typedef char wchar;
+
+// __WFILE__
+// This is a Unicode version of __FILE__
+#define WIDEN2(x) L ## x
+#define WIDEN(x) WIDEN2(x)
+#define __WFILE__ WIDEN(__FILE__)
+
+#ifdef STEAM
+#ifndef _UNICODE
+#define FORCED_UNICODE
+#endif
+#define _UNICODE
+#endif
+
+#if defined( POSIX ) || defined( _PS3 )
+#define _tcsstr strstr
+#define _tcsicmp stricmp
+#define _tcscmp strcmp
+#define _tcscpy strcpy
+#define _tcsncpy strncpy
+#define _tcsrchr strrchr
+#define _tcslen strlen
+#define _tfopen fopen
+#define _stprintf sprintf
+#define _ftprintf fprintf
+#define _vsntprintf _vsnprintf
+#define _tprintf printf
+#define _sntprintf _snprintf
+#define _T(s) s
+#else
+#include <tchar.h>
+#endif
+
+#if defined(_UNICODE)
+typedef wchar tchar;
+#define tstring wstring
+#define __TFILE__ __WFILE__
+#define TCHAR_IS_WCHAR
+#else
+typedef char tchar;
+#define tstring string
+#define __TFILE__ __FILE__
+#define TCHAR_IS_CHAR
+#endif
+
+#ifdef FORCED_UNICODE
+#undef _UNICODE
+#endif
+
+// Turn valve defines back on
+#include "tier0/valve_on.h"
+
+
+#endif // WCHARTYPES
+
+
diff --git a/external/vpc/public/tier0/win32consoleio.h b/external/vpc/public/tier0/win32consoleio.h
new file mode 100644
index 0000000..92b3914
--- /dev/null
+++ b/external/vpc/public/tier0/win32consoleio.h
@@ -0,0 +1,32 @@
+//======= Copyright � 1996-2006, Valve Corporation, All rights reserved. ======
+//
+// Purpose: Win32 Console API helpers
+//
+//=============================================================================
+#ifndef WIN32_CONSOLE_IO_H
+#define WIN32_CONSOLE_IO_H
+
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+// Function to attach a console for I/O to a Win32 GUI application in a reasonably smart fashion.
+PLATFORM_INTERFACE bool SetupWin32ConsoleIO();
+
+// Win32 Console Color API Helpers, originally from cmdlib.
+
+struct Win32ConsoleColorContext_t
+{
+ int m_InitialColor;
+ uint16 m_LastColor;
+ uint16 m_BadColor;
+ uint16 m_BackgroundFlags;
+};
+
+PLATFORM_INTERFACE void InitWin32ConsoleColorContext( Win32ConsoleColorContext_t *pContext );
+
+PLATFORM_INTERFACE uint16 SetWin32ConsoleColor( Win32ConsoleColorContext_t *pContext, int nRed, int nGreen, int nBlue, int nIntensity );
+
+PLATFORM_INTERFACE void RestoreWin32ConsoleColor( Win32ConsoleColorContext_t *pContext, uint16 prevColor );
+
+#endif
diff --git a/external/vpc/public/tier0/xbox_codeline_defines.h b/external/vpc/public/tier0/xbox_codeline_defines.h
new file mode 100644
index 0000000..3f7b544
--- /dev/null
+++ b/external/vpc/public/tier0/xbox_codeline_defines.h
@@ -0,0 +1,16 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef XBOX_CODELINE_DEFINES_H
+#define XBOX_CODELINE_DEFINES_H
+
+
+// In the regular src_main codeline, we leave this out.
+//#define IN_XBOX_CODELINE
+
+
+#endif // XBOX_CODELINE_DEFINES_H
diff --git a/external/vpc/public/tier1/byteswap.h b/external/vpc/public/tier1/byteswap.h
new file mode 100644
index 0000000..b4dea77
--- /dev/null
+++ b/external/vpc/public/tier1/byteswap.h
@@ -0,0 +1,268 @@
+//========= Copyright � 1996-2006, Valve LLC, All rights reserved. ============
+//
+// Purpose: Low level byte swapping routines.
+//
+// $NoKeywords: $
+//=============================================================================
+#ifndef BYTESWAP_H
+#define BYTESWAP_H
+#if defined(_WIN32)
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "datamap.h" // needed for typedescription_t. note datamap.h is tier1 as well.
+
+class CByteswap
+{
+public:
+ CByteswap()
+ {
+ // Default behavior sets the target endian to match the machine native endian (no swap).
+ SetTargetBigEndian( IsMachineBigEndian() );
+ }
+
+ //-----------------------------------------------------------------------------
+ // Write a single field.
+ //-----------------------------------------------------------------------------
+ void SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField );
+
+ //-----------------------------------------------------------------------------
+ // Write a block of fields. Works a bit like the saverestore code.
+ //-----------------------------------------------------------------------------
+ void SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap );
+
+ // Swaps fields for the templated type to the output buffer.
+ template<typename T> inline void SwapFieldsToTargetEndian( T* pOutputBuffer, void *pBaseData, unsigned int objectCount = 1 )
+ {
+ for ( unsigned int i = 0; i < objectCount; ++i, ++pOutputBuffer )
+ {
+ SwapFieldsToTargetEndian( (void*)pOutputBuffer, pBaseData, &T::m_DataMap );
+ pBaseData = (byte*)pBaseData + sizeof(T);
+ }
+ }
+
+ // Swaps fields for the templated type in place.
+ template<typename T> inline void SwapFieldsToTargetEndian( T* pOutputBuffer, unsigned int objectCount = 1 )
+ {
+ SwapFieldsToTargetEndian<T>( pOutputBuffer, (void*)pOutputBuffer, objectCount );
+ }
+
+ //-----------------------------------------------------------------------------
+ // True if the current machine is detected as big endian.
+ // (Endienness is effectively detected at compile time when optimizations are
+ // enabled)
+ //-----------------------------------------------------------------------------
+ static bool IsMachineBigEndian()
+ {
+ short nIsBigEndian = 1;
+
+ // if we are big endian, the first byte will be a 0, if little endian, it will be a one.
+ return (bool)(0 == *(char *)&nIsBigEndian );
+ }
+
+ //-----------------------------------------------------------------------------
+ // Sets the target byte ordering we are swapping to or from.
+ //
+ // Braindead Endian Reference:
+ // x86 is LITTLE Endian
+ // PowerPC is BIG Endian
+ //-----------------------------------------------------------------------------
+ inline void SetTargetBigEndian( bool bigEndian )
+ {
+ m_bBigEndian = bigEndian;
+ m_bSwapBytes = IsMachineBigEndian() != bigEndian;
+ }
+
+ // Changes target endian
+ inline void FlipTargetEndian( void )
+ {
+ m_bSwapBytes = !m_bSwapBytes;
+ m_bBigEndian = !m_bBigEndian;
+ }
+
+ // Forces byte swapping state, regardless of endianess
+ inline void ActivateByteSwapping( bool bActivate )
+ {
+ SetTargetBigEndian( IsMachineBigEndian() != bActivate );
+ }
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the target machine is the same as this one in endianness.
+ //
+ // Used to determine when a byteswap needs to take place.
+ //-----------------------------------------------------------------------------
+ inline bool IsSwappingBytes( void ) // Are bytes being swapped?
+ {
+ return m_bSwapBytes;
+ }
+
+ inline bool IsTargetBigEndian( void ) // What is the current target endian?
+ {
+ return m_bBigEndian;
+ }
+
+ //-----------------------------------------------------------------------------
+ // IsByteSwapped()
+ //
+ // When supplied with a chunk of input data and a constant or magic number
+ // (in native format) determines the endienness of the current machine in
+ // relation to the given input data.
+ //
+ // Returns:
+ // 1 if input is the same as nativeConstant.
+ // 0 if input is byteswapped relative to nativeConstant.
+ // -1 if input is not the same as nativeConstant and not byteswapped either.
+ //
+ // ( This is useful for detecting byteswapping in magic numbers in structure
+ // headers for example. )
+ //-----------------------------------------------------------------------------
+ template<typename T> inline int SourceIsNativeEndian( T input, T nativeConstant )
+ {
+ // If it's the same, it isn't byteswapped:
+ if( input == nativeConstant )
+ return 1;
+
+ int output;
+ LowLevelByteSwap<T>( &output, &input );
+ if( output == nativeConstant )
+ return 0;
+
+ Assert( 0 ); // if we get here, input is neither a swapped nor unswapped version of nativeConstant.
+ return -1;
+ }
+
+ //-----------------------------------------------------------------------------
+ // Swaps an input buffer full of type T into the given output buffer.
+ //
+ // Swaps [count] items from the inputBuffer to the outputBuffer.
+ // If inputBuffer is omitted or NULL, then it is assumed to be the same as
+ // outputBuffer - effectively swapping the contents of the buffer in place.
+ //-----------------------------------------------------------------------------
+ template<typename T> inline void SwapBuffer( T* outputBuffer, T* inputBuffer = NULL, int count = 1 )
+ {
+ Assert( count >= 0 );
+ Assert( outputBuffer );
+
+ // Fail gracefully in release:
+ if( count <=0 || !outputBuffer )
+ return;
+
+ // Optimization for the case when we are swapping in place.
+ if( inputBuffer == NULL )
+ {
+ inputBuffer = outputBuffer;
+ }
+
+ // Swap everything in the buffer:
+ for( int i = 0; i < count; i++ )
+ {
+ LowLevelByteSwap<T>( &outputBuffer[i], &inputBuffer[i] );
+ }
+ }
+
+ //-----------------------------------------------------------------------------
+ // Swaps an input buffer full of type T into the given output buffer.
+ //
+ // Swaps [count] items from the inputBuffer to the outputBuffer.
+ // If inputBuffer is omitted or NULL, then it is assumed to be the same as
+ // outputBuffer - effectively swapping the contents of the buffer in place.
+ //-----------------------------------------------------------------------------
+ template<typename T> inline void SwapBufferToTargetEndian( T* outputBuffer, T* inputBuffer = NULL, int count = 1 )
+ {
+ Assert( count >= 0 );
+ Assert( outputBuffer );
+
+ // Fail gracefully in release:
+ if( count <=0 || !outputBuffer )
+ return;
+
+ // Optimization for the case when we are swapping in place.
+ if( inputBuffer == NULL )
+ {
+ inputBuffer = outputBuffer;
+ }
+
+ // Are we already the correct endienness? ( or are we swapping 1 byte items? )
+ if( !m_bSwapBytes || ( sizeof(T) == 1 ) )
+ {
+ // If we were just going to swap in place then return.
+ if( !inputBuffer )
+ return;
+
+ // Otherwise copy the inputBuffer to the outputBuffer:
+ if ( outputBuffer != inputBuffer )
+ memcpy( outputBuffer, inputBuffer, count * sizeof( T ) );
+ return;
+
+ }
+
+ // Swap everything in the buffer:
+ for( int i = 0; i < count; i++ )
+ {
+ LowLevelByteSwap<T>( &outputBuffer[i], &inputBuffer[i] );
+ }
+ }
+
+private:
+ //-----------------------------------------------------------------------------
+ // The lowest level byte swapping workhorse of doom. output always contains the
+ // swapped version of input. ( Doesn't compare machine to target endianness )
+ //-----------------------------------------------------------------------------
+ template<typename T> static void LowLevelByteSwap( T *output, T *input )
+ {
+ T temp = *output;
+#if defined( _X360 )
+ // Intrinsics need the source type to be fixed-point
+ DWORD* word = (DWORD*)input;
+ switch( sizeof(T) )
+ {
+ case 8:
+ {
+ __storewordbytereverse( *(word+1), 0, &temp );
+ __storewordbytereverse( *(word+0), 4, &temp );
+ }
+ break;
+
+ case 4:
+ __storewordbytereverse( *word, 0, &temp );
+ break;
+
+ case 2:
+ __storeshortbytereverse( *input, 0, &temp );
+ break;
+
+ case 1:
+ V_memcpy( &temp, input, 1 );
+ break;
+
+ default:
+ Assert( "Invalid size in CByteswap::LowLevelByteSwap" && 0 );
+ }
+#else
+ for( unsigned int i = 0; i < sizeof(T); i++ )
+ {
+ ((unsigned char* )&temp)[i] = ((unsigned char*)input)[sizeof(T)-(i+1)];
+ }
+#endif
+ V_memcpy( output, &temp, sizeof(T) );
+ }
+
+#if defined( _X360 )
+ // specialized for void * to get 360 XDK compile working despite changelist 281331
+ //-----------------------------------------------------------------------------
+ // The lowest level byte swapping workhorse of doom. output always contains the
+ // swapped version of input. ( Doesn't compare machine to target endianness )
+ //-----------------------------------------------------------------------------
+ template<> static void LowLevelByteSwap( void **output, void **input )
+ {
+ AssertMsgOnce( sizeof(void *) == sizeof(unsigned int) , "void *'s on this platform are not four bytes!" );
+ __storewordbytereverse( *reinterpret_cast<unsigned int *>(input), 0, output );
+ }
+#endif
+
+ unsigned int m_bSwapBytes : 1;
+ unsigned int m_bBigEndian : 1;
+};
+
+#endif /* !BYTESWAP_H */
diff --git a/external/vpc/public/tier1/characterset.h b/external/vpc/public/tier1/characterset.h
new file mode 100644
index 0000000..42ef2c3
--- /dev/null
+++ b/external/vpc/public/tier1/characterset.h
@@ -0,0 +1,43 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: Shared code for parsing / searching for characters in a string
+// using lookup tables
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef CHARACTERSET_H
+#define CHARACTERSET_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+struct characterset_t
+{
+ char set[256];
+};
+
+
+// This is essentially a strpbrk() using a precalculated lookup table
+//-----------------------------------------------------------------------------
+// Purpose: builds a simple lookup table of a group of important characters
+// Input : *pSetBuffer - pointer to the buffer for the group
+// *pSetString - list of characters to flag
+//-----------------------------------------------------------------------------
+extern void CharacterSetBuild( characterset_t *pSetBuffer, const char *pSetString );
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pSetBuffer - pre-build group buffer
+// character - character to lookup
+// Output : int - 1 if the character was in the set
+//-----------------------------------------------------------------------------
+#define IN_CHARACTERSET( SetBuffer, character ) ((SetBuffer).set[(unsigned char)(character)])
+
+
+#endif // CHARACTERSET_H
diff --git a/external/vpc/public/tier1/checksum_crc.h b/external/vpc/public/tier1/checksum_crc.h
new file mode 100644
index 0000000..4c82376
--- /dev/null
+++ b/external/vpc/public/tier1/checksum_crc.h
@@ -0,0 +1,31 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generic CRC functions
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifndef CHECKSUM_CRC_H
+#define CHECKSUM_CRC_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+typedef uint32 CRC32_t;
+
+void CRC32_Init( CRC32_t *pulCRC );
+void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *p, int len );
+void CRC32_Final( CRC32_t *pulCRC );
+CRC32_t CRC32_GetTableEntry( unsigned int slot );
+
+inline CRC32_t CRC32_ProcessSingleBuffer( const void *p, int len )
+{
+ CRC32_t crc;
+
+ CRC32_Init( &crc );
+ CRC32_ProcessBuffer( &crc, p, len );
+ CRC32_Final( &crc );
+
+ return crc;
+}
+
+#endif // CHECKSUM_CRC_H
diff --git a/external/vpc/public/tier1/checksum_md5.h b/external/vpc/public/tier1/checksum_md5.h
new file mode 100644
index 0000000..3692cf1
--- /dev/null
+++ b/external/vpc/public/tier1/checksum_md5.h
@@ -0,0 +1,33 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Generic MD5 hashing algo
+//
+//=============================================================================//
+
+#ifndef CHECKSUM_MD5_H
+#define CHECKSUM_MD5_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// 16 bytes == 128 bit digest
+#define MD5_DIGEST_LENGTH 16
+
+// MD5 Hash
+typedef struct
+{
+ unsigned int buf[4];
+ unsigned int bits[2];
+ unsigned char in[64];
+} MD5Context_t;
+
+void MD5Init( MD5Context_t *context );
+void MD5Update( MD5Context_t *context, unsigned char const *buf, unsigned int len );
+void MD5Final( unsigned char digest[ MD5_DIGEST_LENGTH ], MD5Context_t *context );
+
+char *MD5_Print(unsigned char *digest, int hashlen );
+
+unsigned int MD5_PseudoRandom(unsigned int nSeed);
+
+#endif // CHECKSUM_MD5_H
diff --git a/external/vpc/public/tier1/convar.h b/external/vpc/public/tier1/convar.h
new file mode 100644
index 0000000..d67a5d4
--- /dev/null
+++ b/external/vpc/public/tier1/convar.h
@@ -0,0 +1,975 @@
+//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef CONVAR_H
+#define CONVAR_H
+
+#if _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "tier1/iconvar.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlstring.h"
+#include "color.h"
+#include "icvar.h"
+
+#ifdef _WIN32
+#define FORCEINLINE_CVAR FORCEINLINE
+#elif POSIX
+#define FORCEINLINE_CVAR inline
+#elif defined(_PS3)
+#define FORCEINLINE_CVAR __attribute__((always_inline)) FORCEINLINE
+#else
+#error "implement me"
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Uncomment me to test for threading issues for material system convars
+// NOTE: You want to disable all threading when you do this
+// +host_thread_mode 0 +r_threaded_particles 0 +sv_parallel_packentities 0 +sv_disable_querycache 0
+//-----------------------------------------------------------------------------
+//#define CONVAR_TEST_MATERIAL_THREAD_CONVARS 1
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class ConVar;
+class CCommand;
+class ConCommand;
+class ConCommandBase;
+struct characterset_t;
+
+
+
+//-----------------------------------------------------------------------------
+// Any executable that wants to use ConVars need to implement one of
+// these to hook up access to console variables.
+//-----------------------------------------------------------------------------
+class IConCommandBaseAccessor
+{
+public:
+ // Flags is a combination of FCVAR flags in cvar.h.
+ // hOut is filled in with a handle to the variable.
+ virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Helper method for console development
+//-----------------------------------------------------------------------------
+#if defined( USE_VXCONSOLE )
+void ConVar_PublishToVXConsole();
+#else
+inline void ConVar_PublishToVXConsole() {}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Called when a ConCommand needs to execute
+//-----------------------------------------------------------------------------
+typedef void ( *FnCommandCallbackV1_t )( void );
+typedef void ( *FnCommandCallback_t )( const CCommand &command );
+
+#define COMMAND_COMPLETION_MAXITEMS 64
+#define COMMAND_COMPLETION_ITEM_LENGTH 64
+
+//-----------------------------------------------------------------------------
+// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
+//-----------------------------------------------------------------------------
+typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
+
+
+//-----------------------------------------------------------------------------
+// Interface version
+//-----------------------------------------------------------------------------
+class ICommandCallback
+{
+public:
+ virtual void CommandCallback( const CCommand &command ) = 0;
+};
+
+class ICommandCompletionCallback
+{
+public:
+ virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: The base console invoked command/cvar interface
+//-----------------------------------------------------------------------------
+class ConCommandBase
+{
+ friend class CCvar;
+ friend class ConVar;
+ friend class ConCommand;
+ friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
+ friend void ConVar_PublishToVXConsole();
+
+ // FIXME: Remove when ConVar changes are done
+ friend class CDefaultCvar;
+
+public:
+ ConCommandBase( void );
+ ConCommandBase( const char *pName, const char *pHelpString = 0,
+ int flags = 0 );
+
+ virtual ~ConCommandBase( void );
+
+ virtual bool IsCommand( void ) const;
+
+ // Check flag
+ virtual bool IsFlagSet( int flag ) const;
+ // Set flag
+ virtual void AddFlags( int flags );
+ // Clear flag
+ virtual void RemoveFlags( int flags );
+
+ virtual int GetFlags() const;
+
+ // Return name of cvar
+ virtual const char *GetName( void ) const;
+
+ // Return help text for cvar
+ virtual const char *GetHelpText( void ) const;
+
+ // Deal with next pointer
+ const ConCommandBase *GetNext( void ) const;
+ ConCommandBase *GetNext( void );
+
+ virtual bool IsRegistered( void ) const;
+
+ // Returns the DLL identifier
+ virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
+
+protected:
+ virtual void Create( const char *pName, const char *pHelpString = 0,
+ int flags = 0 );
+
+ // Used internally by OneTimeInit to initialize/shutdown
+ virtual void Init();
+ void Shutdown();
+
+ // Internal copy routine ( uses new operator from correct module )
+ char *CopyString( const char *from );
+
+private:
+ // Next ConVar in chain
+ // Prior to register, it points to the next convar in the DLL.
+ // Once registered, though, m_pNext is reset to point to the next
+ // convar in the global list
+ ConCommandBase *m_pNext;
+
+ // Has the cvar been added to the global list?
+ bool m_bRegistered;
+
+ // Static data
+ const char *m_pszName;
+ const char *m_pszHelpString;
+
+ // ConVar flags
+ int m_nFlags;
+
+protected:
+ // ConVars add themselves to this list for the executable.
+ // Then ConVar_Register runs through all the console variables
+ // and registers them into a global list stored in vstdlib.dll
+ static ConCommandBase *s_pConCommandBases;
+
+ // ConVars in this executable use this 'global' to access values.
+ static IConCommandBaseAccessor *s_pAccessor;
+};
+
+
+//-----------------------------------------------------------------------------
+// Command tokenizer
+//-----------------------------------------------------------------------------
+class CCommand
+{
+public:
+ CCommand();
+ CCommand( int nArgC, const char **ppArgV );
+ bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
+ void Reset();
+
+ int ArgC() const;
+ const char **ArgV() const;
+ const char *ArgS() const; // All args that occur after the 0th arg, in string form
+ const char *GetCommandString() const; // The entire command in string form, including the 0th arg
+ const char *operator[]( int nIndex ) const; // Gets at arguments
+ const char *Arg( int nIndex ) const; // Gets at arguments
+
+ // Helper functions to parse arguments to commands.
+ const char* FindArg( const char *pName ) const;
+ int FindArgInt( const char *pName, int nDefaultVal ) const;
+
+ static int MaxCommandLength();
+ static characterset_t* DefaultBreakSet();
+
+private:
+ enum
+ {
+ COMMAND_MAX_ARGC = 64,
+ COMMAND_MAX_LENGTH = 512,
+ };
+
+ int m_nArgc;
+ int m_nArgv0Size;
+ char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
+ char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
+ const char* m_ppArgv[ COMMAND_MAX_ARGC ];
+};
+
+inline int CCommand::MaxCommandLength()
+{
+ return COMMAND_MAX_LENGTH - 1;
+}
+
+inline int CCommand::ArgC() const
+{
+ return m_nArgc;
+}
+
+inline const char **CCommand::ArgV() const
+{
+ return m_nArgc ? (const char**)m_ppArgv : NULL;
+}
+
+inline const char *CCommand::ArgS() const
+{
+ return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
+}
+
+inline const char *CCommand::GetCommandString() const
+{
+ return m_nArgc ? m_pArgSBuffer : "";
+}
+
+inline const char *CCommand::Arg( int nIndex ) const
+{
+ // FIXME: Many command handlers appear to not be particularly careful
+ // about checking for valid argc range. For now, we're going to
+ // do the extra check and return an empty string if it's out of range
+ if ( nIndex < 0 || nIndex >= m_nArgc )
+ return "";
+ return m_ppArgv[nIndex];
+}
+
+inline const char *CCommand::operator[]( int nIndex ) const
+{
+ return Arg( nIndex );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: The console invoked command
+//-----------------------------------------------------------------------------
+class ConCommand : public ConCommandBase
+{
+friend class CCvar;
+
+public:
+ typedef ConCommandBase BaseClass;
+
+ ConCommand( const char *pName, FnCommandCallbackV1_t callback,
+ const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
+ ConCommand( const char *pName, FnCommandCallback_t callback,
+ const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
+ ConCommand( const char *pName, ICommandCallback *pCallback,
+ const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
+
+ virtual ~ConCommand( void );
+
+ virtual bool IsCommand( void ) const;
+
+ virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
+
+ virtual bool CanAutoComplete( void );
+
+ // Invoke the function
+ virtual void Dispatch( const CCommand &command );
+
+private:
+ // NOTE: To maintain backward compat, we have to be very careful:
+ // All public virtual methods must appear in the same order always
+ // since engine code will be calling into this code, which *does not match*
+ // in the mod code; it's using slightly different, but compatible versions
+ // of this class. Also: Be very careful about adding new fields to this class.
+ // Those fields will not exist in the version of this class that is instanced
+ // in mod code.
+
+ // Call this function when executing the command
+ union
+ {
+ FnCommandCallbackV1_t m_fnCommandCallbackV1;
+ FnCommandCallback_t m_fnCommandCallback;
+ ICommandCallback *m_pCommandCallback;
+ };
+
+ union
+ {
+ FnCommandCompletionCallback m_fnCompletionCallback;
+ ICommandCompletionCallback *m_pCommandCompletionCallback;
+ };
+
+ bool m_bHasCompletionCallback : 1;
+ bool m_bUsingNewCommandCallback : 1;
+ bool m_bUsingCommandCallbackInterface : 1;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: A console variable
+//-----------------------------------------------------------------------------
+class ConVar : public ConCommandBase, public IConVar
+{
+friend class CCvar;
+friend class ConVarRef;
+friend class SplitScreenConVarRef;
+
+public:
+ typedef ConCommandBase BaseClass;
+
+ ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
+
+ ConVar( const char *pName, const char *pDefaultValue, int flags,
+ const char *pHelpString );
+ ConVar( const char *pName, const char *pDefaultValue, int flags,
+ const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
+ ConVar( const char *pName, const char *pDefaultValue, int flags,
+ const char *pHelpString, FnChangeCallback_t callback );
+ ConVar( const char *pName, const char *pDefaultValue, int flags,
+ const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
+ FnChangeCallback_t callback );
+
+ virtual ~ConVar( void );
+
+ virtual bool IsFlagSet( int flag ) const;
+ virtual const char* GetHelpText( void ) const;
+ virtual bool IsRegistered( void ) const;
+ virtual const char *GetName( void ) const;
+ // Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars
+ virtual const char *GetBaseName( void ) const;
+ virtual int GetSplitScreenPlayerSlot() const;
+
+ virtual void AddFlags( int flags );
+ virtual int GetFlags() const;
+ virtual bool IsCommand( void ) const;
+
+ // Install a change callback (there shouldn't already be one....)
+ void InstallChangeCallback( FnChangeCallback_t callback, bool bInvoke = true );
+ void RemoveChangeCallback( FnChangeCallback_t callbackToRemove );
+
+ int GetChangeCallbackCount() const { return m_pParent->m_fnChangeCallbacks.Count(); }
+ FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; }
+
+ // Retrieve value
+ FORCEINLINE_CVAR float GetFloat( void ) const;
+ FORCEINLINE_CVAR int GetInt( void ) const;
+ FORCEINLINE_CVAR Color GetColor( void ) const;
+ FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
+ FORCEINLINE_CVAR char const *GetString( void ) const;
+
+ // Compiler driven selection for template use
+ template <typename T> T Get( void ) const;
+ template <typename T> T Get( T * ) const;
+
+ // Any function that allocates/frees memory needs to be virtual or else you'll have crashes
+ // from alloc/free across dll/exe boundaries.
+
+ // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
+ virtual void SetValue( const char *value );
+ virtual void SetValue( float value );
+ virtual void SetValue( int value );
+ virtual void SetValue( Color value );
+
+ // Reset to default value
+ void Revert( void );
+
+ // True if it has a min/max setting
+ bool HasMin() const;
+ bool HasMax() const;
+
+ bool GetMin( float& minVal ) const;
+ bool GetMax( float& maxVal ) const;
+
+ float GetMinValue() const;
+ float GetMaxValue() const;
+
+ const char *GetDefault( void ) const;
+ void SetDefault( const char *pszDefault );
+
+ // Value
+ struct CVValue_t
+ {
+ char *m_pszString;
+ int m_StringLength;
+
+ // Values
+ float m_fValue;
+ int m_nValue;
+ };
+
+ FORCEINLINE_CVAR CVValue_t &GetRawValue()
+ {
+ return m_Value;
+ }
+ FORCEINLINE_CVAR const CVValue_t &GetRawValue() const
+ {
+ return m_Value;
+ }
+
+private:
+ bool InternalSetColorFromString( const char *value );
+ // Called by CCvar when the value of a var is changing.
+ virtual void InternalSetValue(const char *value);
+ // For CVARs marked FCVAR_NEVER_AS_STRING
+ virtual void InternalSetFloatValue( float fNewValue );
+ virtual void InternalSetIntValue( int nValue );
+ virtual void InternalSetColorValue( Color value );
+
+ virtual bool ClampValue( float& value );
+ virtual void ChangeStringValue( const char *tempVal, float flOldValue );
+
+ virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
+ const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
+ bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
+
+ // Used internally by OneTimeInit to initialize.
+ virtual void Init();
+
+protected:
+
+ // This either points to "this" or it points to the original declaration of a ConVar.
+ // This allows ConVars to exist in separate modules, and they all use the first one to be declared.
+ // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
+ ConVar *m_pParent;
+
+ // Static data
+ const char *m_pszDefaultValue;
+
+ CVValue_t m_Value;
+
+ // Min/Max values
+ bool m_bHasMin;
+ float m_fMinVal;
+ bool m_bHasMax;
+ float m_fMaxVal;
+
+ // Call this function when ConVar changes
+ CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a float
+// Output : float
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
+{
+#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
+ Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
+#endif
+ return m_pParent->m_Value.m_fValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as an int
+// Output : int
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR int ConVar::GetInt( void ) const
+{
+#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
+ Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
+#endif
+ return m_pParent->m_Value.m_nValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a color
+// Output : Color
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR Color ConVar::GetColor( void ) const
+{
+#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
+ Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
+#endif
+ unsigned char *pColorElement = ((unsigned char *)&m_pParent->m_Value.m_nValue);
+ return Color( pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3] );
+}
+
+
+//-----------------------------------------------------------------------------
+
+template <> FORCEINLINE_CVAR float ConVar::Get<float>( void ) const { return GetFloat(); }
+template <> FORCEINLINE_CVAR int ConVar::Get<int>( void ) const { return GetInt(); }
+template <> FORCEINLINE_CVAR bool ConVar::Get<bool>( void ) const { return GetBool(); }
+template <> FORCEINLINE_CVAR const char * ConVar::Get<const char *>( void ) const { return GetString(); }
+template <> FORCEINLINE_CVAR float ConVar::Get<float>( float *p ) const { return ( *p = GetFloat() ); }
+template <> FORCEINLINE_CVAR int ConVar::Get<int>( int *p ) const { return ( *p = GetInt() ); }
+template <> FORCEINLINE_CVAR bool ConVar::Get<bool>( bool *p ) const { return ( *p = GetBool() ); }
+template <> FORCEINLINE_CVAR const char * ConVar::Get<const char *>( char const **p ) const { return ( *p = GetString() ); }
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
+// Output : const char *
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
+{
+#ifdef CONVAR_TEST_MATERIAL_THREAD_CONVARS
+ Assert( ThreadInMainThread() || IsFlagSet( FCVAR_MATERIAL_THREAD_MASK | FCVAR_ACCESSIBLE_FROM_THREADS ) );
+#endif
+ if ( m_nFlags & FCVAR_NEVER_AS_STRING )
+ return "FCVAR_NEVER_AS_STRING";
+
+ char const *str = m_pParent->m_Value.m_pszString;
+ return str ? str : "";
+}
+
+class CSplitScreenAddedConVar : public ConVar
+{
+ typedef ConVar BaseClass;
+public:
+ CSplitScreenAddedConVar( int nSplitScreenSlot, const char *pName, const ConVar *pBaseVar ) :
+ BaseClass
+ (
+ pName,
+ pBaseVar->GetDefault(),
+ // Keep basevar flags, except remove _SS and add _SS_ADDED instead
+ ( pBaseVar->GetFlags() & ~FCVAR_SS ) | FCVAR_SS_ADDED,
+ pBaseVar->GetHelpText(),
+ pBaseVar->HasMin(),
+ pBaseVar->GetMinValue(),
+ pBaseVar->HasMax(),
+ pBaseVar->GetMaxValue()
+ ),
+ m_pBaseVar( pBaseVar ),
+ m_nSplitScreenSlot( nSplitScreenSlot )
+ {
+ for ( int i = 0; i < pBaseVar->GetChangeCallbackCount(); ++i )
+ {
+ InstallChangeCallback( pBaseVar->GetChangeCallback( i ), false );
+ }
+ Assert( nSplitScreenSlot >= 1 );
+ Assert( nSplitScreenSlot < MAX_SPLITSCREEN_CLIENTS );
+ Assert( m_pBaseVar );
+ Assert( IsFlagSet( FCVAR_SS_ADDED ) );
+ Assert( !IsFlagSet( FCVAR_SS ) );
+ }
+
+ const ConVar *GetBaseVar() const;
+ virtual const char *GetBaseName() const;
+ void SetSplitScreenPlayerSlot( int nSlot );
+ virtual int GetSplitScreenPlayerSlot() const;
+
+protected:
+
+ const ConVar *m_pBaseVar;
+ int m_nSplitScreenSlot;
+};
+
+FORCEINLINE_CVAR const ConVar *CSplitScreenAddedConVar::GetBaseVar() const
+{
+ Assert( m_pBaseVar );
+ return m_pBaseVar;
+}
+
+FORCEINLINE_CVAR const char *CSplitScreenAddedConVar::GetBaseName() const
+{
+ Assert( m_pBaseVar );
+ return m_pBaseVar->GetName();
+}
+
+FORCEINLINE_CVAR void CSplitScreenAddedConVar::SetSplitScreenPlayerSlot( int nSlot )
+{
+ m_nSplitScreenSlot = nSlot;
+}
+
+FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const
+{
+ return m_nSplitScreenSlot;
+}
+
+//-----------------------------------------------------------------------------
+// Used to read/write convars that already exist (replaces the FindVar method)
+//-----------------------------------------------------------------------------
+class ConVarRef
+{
+public:
+ ConVarRef( const char *pName );
+ ConVarRef( const char *pName, bool bIgnoreMissing );
+ ConVarRef( IConVar *pConVar );
+
+ void Init( const char *pName, bool bIgnoreMissing );
+ bool IsValid() const;
+ bool IsFlagSet( int nFlags ) const;
+ IConVar *GetLinkedConVar();
+
+ // Get/Set value
+ float GetFloat( void ) const;
+ int GetInt( void ) const;
+ Color GetColor( void ) const;
+ bool GetBool() const { return !!GetInt(); }
+ const char *GetString( void ) const;
+
+ void SetValue( const char *pValue );
+ void SetValue( float flValue );
+ void SetValue( int nValue );
+ void SetValue( Color value );
+ void SetValue( bool bValue );
+
+ const char *GetName() const;
+
+ const char *GetDefault() const;
+
+ const char *GetBaseName() const;
+
+ int GetSplitScreenPlayerSlot() const;
+
+private:
+ // High-speed method to read convar data
+ IConVar *m_pConVar;
+ ConVar *m_pConVarState;
+};
+
+
+//-----------------------------------------------------------------------------
+// Did we find an existing convar of that name?
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
+{
+ return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
+}
+
+FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
+{
+ return m_pConVar;
+}
+
+FORCEINLINE_CVAR const char *ConVarRef::GetName() const
+{
+ return m_pConVar->GetName();
+}
+
+FORCEINLINE_CVAR const char *ConVarRef::GetBaseName() const
+{
+ return m_pConVar->GetBaseName();
+}
+
+FORCEINLINE_CVAR int ConVarRef::GetSplitScreenPlayerSlot() const
+{
+ return m_pConVar->GetSplitScreenPlayerSlot();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a float
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
+{
+ return m_pConVarState->m_Value.m_fValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as an int
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
+{
+ return m_pConVarState->m_Value.m_nValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a color
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR Color ConVarRef::GetColor( void ) const
+{
+ return m_pConVarState->GetColor();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
+{
+ Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
+ return m_pConVarState->m_Value.m_pszString;
+}
+
+
+FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
+{
+ m_pConVar->SetValue( pValue );
+}
+
+FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
+{
+ m_pConVar->SetValue( flValue );
+}
+
+FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
+{
+ m_pConVar->SetValue( nValue );
+}
+
+FORCEINLINE_CVAR void ConVarRef::SetValue( Color value )
+{
+ m_pConVar->SetValue( value );
+}
+
+FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
+{
+ m_pConVar->SetValue( bValue ? 1 : 0 );
+}
+
+FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
+{
+ return m_pConVarState->m_pszDefaultValue;
+}
+
+//-----------------------------------------------------------------------------
+// Helper for referencing splitscreen convars (i.e., "name" and "name2")
+//-----------------------------------------------------------------------------
+class SplitScreenConVarRef
+{
+public:
+ SplitScreenConVarRef( const char *pName );
+ SplitScreenConVarRef( const char *pName, bool bIgnoreMissing );
+ SplitScreenConVarRef( IConVar *pConVar );
+
+ void Init( const char *pName, bool bIgnoreMissing );
+ bool IsValid() const;
+ bool IsFlagSet( int nFlags ) const;
+
+ // Get/Set value
+ float GetFloat( int nSlot ) const;
+ int GetInt( int nSlot ) const;
+ Color GetColor( int nSlot ) const;
+ bool GetBool( int nSlot ) const { return !!GetInt( nSlot ); }
+ const char *GetString( int nSlot ) const;
+
+ void SetValue( int nSlot, const char *pValue );
+ void SetValue( int nSlot, float flValue );
+ void SetValue( int nSlot, int nValue );
+ void SetValue( int nSlot, Color value );
+ void SetValue( int nSlot, bool bValue );
+
+ const char *GetName( int nSlot ) const;
+
+ const char *GetDefault() const;
+
+ const char *GetBaseName() const;
+
+private:
+ struct cv_t
+ {
+ IConVar *m_pConVar;
+ ConVar *m_pConVarState;
+ };
+
+ cv_t m_Info[ MAX_SPLITSCREEN_CLIENTS ];
+};
+
+//-----------------------------------------------------------------------------
+// Did we find an existing convar of that name?
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR bool SplitScreenConVarRef::IsFlagSet( int nFlags ) const
+{
+ return ( m_Info[ 0 ].m_pConVar->IsFlagSet( nFlags ) != 0 );
+}
+
+FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetName( int nSlot ) const
+{
+ return m_Info[ nSlot ].m_pConVar->GetName();
+}
+
+FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetBaseName() const
+{
+ return m_Info[ 0 ].m_pConVar->GetBaseName();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a float
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR float SplitScreenConVarRef::GetFloat( int nSlot ) const
+{
+ return m_Info[ nSlot ].m_pConVarState->m_Value.m_fValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as an int
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR int SplitScreenConVarRef::GetInt( int nSlot ) const
+{
+ return m_Info[ nSlot ].m_pConVarState->m_Value.m_nValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as an int
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR Color SplitScreenConVarRef::GetColor( int nSlot ) const
+{
+ return m_Info[ nSlot ].m_pConVarState->GetColor();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
+//-----------------------------------------------------------------------------
+FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetString( int nSlot ) const
+{
+ Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
+ return m_Info[ nSlot ].m_pConVarState->m_Value.m_pszString;
+}
+
+
+FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, const char *pValue )
+{
+ m_Info[ nSlot ].m_pConVar->SetValue( pValue );
+}
+
+FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, float flValue )
+{
+ m_Info[ nSlot ].m_pConVar->SetValue( flValue );
+}
+
+FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, int nValue )
+{
+ m_Info[ nSlot ].m_pConVar->SetValue( nValue );
+}
+
+FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, Color value )
+{
+ m_Info[ nSlot ].m_pConVar->SetValue( value );
+}
+
+FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, bool bValue )
+{
+ m_Info[ nSlot ].m_pConVar->SetValue( bValue ? 1 : 0 );
+}
+
+FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetDefault() const
+{
+ return m_Info[ 0 ].m_pConVarState->m_pszDefaultValue;
+}
+
+//-----------------------------------------------------------------------------
+// Called by the framework to register ConCommands with the ICVar
+//-----------------------------------------------------------------------------
+void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
+void ConVar_Unregister( );
+
+
+//-----------------------------------------------------------------------------
+// Utility methods
+//-----------------------------------------------------------------------------
+void ConVar_PrintDescription( const ConCommandBase *pVar );
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Utility class to quickly allow ConCommands to call member methods
+//-----------------------------------------------------------------------------
+#pragma warning (disable : 4355 )
+
+template< class T >
+class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
+{
+ typedef ConCommand BaseClass;
+ typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
+ typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
+
+public:
+ CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
+ int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
+ BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
+ {
+ m_pOwner = pOwner;
+ m_Func = callback;
+ m_CompletionFunc = completionFunc;
+ }
+
+ ~CConCommandMemberAccessor()
+ {
+ Shutdown();
+ }
+
+ void SetOwner( T* pOwner )
+ {
+ m_pOwner = pOwner;
+ }
+
+ virtual void CommandCallback( const CCommand &command )
+ {
+ Assert( m_pOwner && m_Func );
+ (m_pOwner->*m_Func)( command );
+ }
+
+ virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
+ {
+ Assert( m_pOwner && m_CompletionFunc );
+ return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
+ }
+
+private:
+ T* m_pOwner;
+ FnMemberCommandCallback_t m_Func;
+ FnMemberCommandCompletionCallback_t m_CompletionFunc;
+};
+
+#pragma warning ( default : 4355 )
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Utility macros to quicky generate a simple console command
+//-----------------------------------------------------------------------------
+#define CON_COMMAND( name, description ) \
+ static void name( const CCommand &args ); \
+ static ConCommand name##_command( #name, name, description ); \
+ static void name( const CCommand &args )
+
+#define CON_COMMAND_F( name, description, flags ) \
+ static void name( const CCommand &args ); \
+ static ConCommand name##_command( #name, name, description, flags ); \
+ static void name( const CCommand &args )
+
+#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
+ static void name( const CCommand &args ); \
+ static ConCommand name##_command( #name, name, description, flags, completion ); \
+ static void name( const CCommand &args )
+
+#define CON_COMMAND_EXTERN( name, _funcname, description ) \
+ void _funcname( const CCommand &args ); \
+ static ConCommand name##_command( #name, _funcname, description ); \
+ void _funcname( const CCommand &args )
+
+#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
+ void _funcname( const CCommand &args ); \
+ static ConCommand name##_command( #name, _funcname, description, flags ); \
+ void _funcname( const CCommand &args )
+
+#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
+ void _funcname( const CCommand &args ); \
+ friend class CCommandMemberInitializer_##_funcname; \
+ class CCommandMemberInitializer_##_funcname \
+ { \
+ public: \
+ CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
+ { \
+ m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
+ } \
+ private: \
+ CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
+ }; \
+ \
+ CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
+
+
+#endif // CONVAR_H
diff --git a/external/vpc/public/tier1/convar_serverbounded.h b/external/vpc/public/tier1/convar_serverbounded.h
new file mode 100644
index 0000000..3616239
--- /dev/null
+++ b/external/vpc/public/tier1/convar_serverbounded.h
@@ -0,0 +1,53 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Helper class for cvars that have restrictions on their value.
+//
+//=============================================================================//
+
+#ifndef CONVAR_SERVERBOUNDED_H
+#define CONVAR_SERVERBOUNDED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+// This class is used to virtualize a ConVar's value, so the client can restrict its
+// value while connected to a server. When using this across modules, it's important
+// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value.
+//
+// NOTE: FCVAR_USERINFO vars are not virtualized before they are sent to the server
+// (we have no way to detect if the virtualized value would change), so
+// if you want to use a bounded cvar's value on the server, you must rebound it
+// the same way the client does.
+class ConVar_ServerBounded : public ConVar
+{
+public:
+ ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString )
+ : ConVar( pName, pDefaultValue, flags, pHelpString )
+ {
+ }
+
+ ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback_t callback )
+ : ConVar( pName, pDefaultValue, flags, pHelpString, callback )
+ {
+ }
+
+ ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax )
+ : ConVar( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ) {}
+
+ // You must implement GetFloat.
+ virtual float GetFloat() const = 0;
+
+ // You can optionally implement these.
+ virtual int GetInt() const { return (int)GetFloat(); }
+ virtual bool GetBool() const { return ( GetInt() != 0 ); }
+
+ // Use this to get the underlying cvar's value.
+ float GetBaseFloatValue() const
+ {
+ return ConVar::GetFloat();
+ }
+};
+
+
+#endif // CONVAR_SERVERBOUNDED_H
diff --git a/external/vpc/public/tier1/exprevaluator.h b/external/vpc/public/tier1/exprevaluator.h
new file mode 100644
index 0000000..89dffc6
--- /dev/null
+++ b/external/vpc/public/tier1/exprevaluator.h
@@ -0,0 +1,74 @@
+//===== Copyright � 1996-2006, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: ExprSimplifier builds a binary tree from an infix expression (in the
+// form of a character array).
+//
+//===========================================================================//
+
+#ifndef EXPREVALUATOR_H
+#define EXPREVALUATOR_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+static const char OR_OP = '|';
+static const char AND_OP = '&';
+static const char NOT_OP = '!';
+
+#define MAX_IDENTIFIER_LEN 128
+enum Kind {CONDITIONAL, NOT, LITERAL};
+
+struct ExprNode
+{
+ ExprNode *left; // left sub-expression
+ ExprNode *right; // right sub-expression
+ Kind kind; // kind of node this is
+ union
+ {
+ char cond; // the conditional
+ bool value; // the value
+ } data;
+};
+
+typedef ExprNode *ExprTree;
+
+// callback to evaluate a $<symbol> during evaluation, return true or false
+typedef bool (*GetSymbolProc_t)( const char *pKey );
+typedef void (*SyntaxErrorProc_t)( const char *pReason );
+
+class CExpressionEvaluator
+{
+public:
+ CExpressionEvaluator();
+ ~CExpressionEvaluator();
+ bool Evaluate( bool &result, const char *pInfixExpression, GetSymbolProc_t pGetSymbolProc = 0, SyntaxErrorProc_t pSyntaxErrorProc = 0 );
+
+private:
+ CExpressionEvaluator( CExpressionEvaluator& ); // prevent copy constructor being used
+
+ char GetNextToken( void );
+ void FreeNode( ExprNode *pNode );
+ ExprNode *AllocateNode( void );
+ void FreeTree( ExprTree &node );
+ bool IsConditional( bool &bCondition, const char token );
+ bool IsNotOp( const char token );
+ bool IsIdentifierOrConstant( const char token );
+ bool MakeExprNode( ExprTree &tree, char token, Kind kind, ExprTree left, ExprTree right );
+ bool MakeFactor( ExprTree &tree );
+ bool MakeTerm( ExprTree &tree );
+ bool MakeExpression( ExprTree &tree );
+ bool BuildExpression( void );
+ bool SimplifyNode( ExprTree &node );
+
+ ExprTree m_ExprTree; // Tree representation of the expression
+ char m_CurToken; // Current token read from the input expression
+ const char *m_pExpression; // Array of the expression characters
+ int m_CurPosition; // Current position in the input expression
+ char m_Identifier[MAX_IDENTIFIER_LEN]; // Stores the identifier string
+ GetSymbolProc_t m_pGetSymbolProc;
+ SyntaxErrorProc_t m_pSyntaxErrorProc;
+ bool m_bSetup;
+};
+
+#endif
diff --git a/external/vpc/public/tier1/fmtstr.h b/external/vpc/public/tier1/fmtstr.h
new file mode 100644
index 0000000..476f4c5
--- /dev/null
+++ b/external/vpc/public/tier1/fmtstr.h
@@ -0,0 +1,179 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A simple class for performing safe and in-expression sprintf-style
+// string formatting
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef FMTSTR_H
+#define FMTSTR_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+#include "tier1/strtools.h"
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//=============================================================================
+
+// using macro to be compatable with GCC
+#define FmtStrVSNPrintf( szBuf, nBufSize, bQuietTruncation, ppszFormat ) \
+ do \
+ { \
+ int result; \
+ va_list arg_ptr; \
+ bool bTruncated = false; \
+ static int scAsserted = 0; \
+ \
+ va_start(arg_ptr, (*(ppszFormat))); \
+ result = V_vsnprintfRet( (szBuf), (nBufSize)-1, (*(ppszFormat)), arg_ptr, &bTruncated ); \
+ va_end(arg_ptr); \
+ \
+ (szBuf)[(nBufSize)-1] = 0; \
+ if ( bTruncated && !(bQuietTruncation) && scAsserted < 5 ) \
+ { \
+ Assert( !bTruncated ); \
+ scAsserted++; \
+ } \
+ } \
+ while (0)
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: String formatter with specified size
+//
+
+template <int SIZE_BUF>
+class CFmtStrN
+{
+public:
+ CFmtStrN()
+ {
+ InitQuietTruncation();
+ m_szBuf[0] = 0;
+ m_nLength = 0;
+ }
+
+ // Standard C formatting
+ CFmtStrN(const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
+ {
+ InitQuietTruncation();
+ FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat);
+ FixLength();
+ }
+
+ // Use this for pass-through formatting
+ CFmtStrN(const char ** ppszFormat, ...)
+ {
+ InitQuietTruncation();
+ FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat);
+ FixLength();
+ }
+
+ // Explicit reformat
+ const char *sprintf(const char *pszFormat, ...) FMTFUNCTION( 2, 3 )
+ {
+ InitQuietTruncation();
+ FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, &pszFormat);
+ FixLength();
+ return m_szBuf;
+ }
+
+ // Use this for pass-through formatting
+ void VSprintf(const char **ppszFormat, ...)
+ {
+ InitQuietTruncation();
+ FmtStrVSNPrintf(m_szBuf, SIZE_BUF, m_bQuietTruncation, ppszFormat);
+ FixLength();
+ }
+
+ // Use for access
+ operator const char *() const { return m_szBuf; }
+ char *Access() { return m_szBuf; }
+ CFmtStrN<SIZE_BUF> & operator=( const char *pchValue ) { sprintf( pchValue ); return *this; }
+ CFmtStrN<SIZE_BUF> & operator+=( const char *pchValue ) { Append( pchValue ); return *this; }
+ int Length() const { return m_nLength; }
+
+ void Clear() { m_szBuf[0] = 0; m_nLength = 0; }
+
+ void AppendFormat( const char *pchFormat, ... ) { char *pchEnd = m_szBuf + m_nLength; FmtStrVSNPrintf( pchEnd, SIZE_BUF - m_nLength, m_bQuietTruncation, &pchFormat ); FixLength(); }
+ void AppendFormatV( const char *pchFormat, va_list args );
+ void Append( const char *pchValue ) { AppendFormat( pchValue ); }
+
+ void AppendIndent( uint32 unCount, char chIndent = '\t' );
+protected:
+ virtual void InitQuietTruncation()
+ {
+#ifdef _DEBUG
+ m_bQuietTruncation = false;
+#else
+ m_bQuietTruncation = true; // Force quiet for release builds
+#endif
+ }
+
+ bool m_bQuietTruncation;
+
+ void FixLength() { m_nLength = V_strlen(m_szBuf); }
+private:
+ char m_szBuf[SIZE_BUF];
+ int m_nLength;
+
+};
+
+
+// Version which will not assert if strings are truncated
+
+template <int SIZE_BUF>
+class CFmtStrQuietTruncationN : public CFmtStrN<SIZE_BUF>
+{
+protected:
+ virtual void InitQuietTruncation() { this->m_bQuietTruncation = true; }
+};
+
+
+template< int SIZE_BUF >
+void CFmtStrN<SIZE_BUF>::AppendIndent( uint32 unCount, char chIndent )
+{
+ Assert( Length() + unCount < SIZE_BUF );
+ if( Length() + unCount >= SIZE_BUF )
+ unCount = SIZE_BUF - (1+Length());
+ for ( uint32 x = 0; x < unCount; x++ )
+ {
+ m_szBuf[ m_nLength++ ] = chIndent;
+ }
+ m_szBuf[ m_nLength ] = '\0';
+}
+
+template< int SIZE_BUF >
+void CFmtStrN<SIZE_BUF>::AppendFormatV( const char *pchFormat, va_list args )
+{
+ int cubPrinted = V_vsnprintf( m_szBuf+Length(), SIZE_BUF - Length(), pchFormat, args );
+ m_nLength += cubPrinted;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Default-sized string formatter
+//
+
+#define FMTSTR_STD_LEN 1024
+
+typedef CFmtStrN<FMTSTR_STD_LEN> CFmtStr;
+typedef CFmtStrQuietTruncationN<FMTSTR_STD_LEN> CFmtStrQuietTruncation;
+typedef CFmtStrN<1024> CFmtStr1024;
+typedef CFmtStrN<8192> CFmtStrMax;
+
+//=============================================================================
+
+const int k_cchFormattedDate = 64;
+const int k_cchFormattedTime = 32;
+bool BGetLocalFormattedTime( time_t timeVal, char *pchDate, int cubDate, char *pchTime, int cubTime );
+
+#endif // FMTSTR_H
diff --git a/external/vpc/public/tier1/functors.h b/external/vpc/public/tier1/functors.h
new file mode 100644
index 0000000..5b74787
--- /dev/null
+++ b/external/vpc/public/tier1/functors.h
@@ -0,0 +1,920 @@
+//========== Copyright © 2006, Valve Corporation, All rights reserved. ========
+//
+// Purpose: Implements a generic infrastucture for functors combining
+// a number of techniques to provide transparent parameter type
+// deduction and packaging. Supports both member and non-member functions.
+//
+// See also: http://en.wikipedia.org/wiki/Function_object
+//
+// Note that getting into the guts of this file is not for the
+// feint of heart. The core concept here is that the compiler can
+// figure out all the parameter types.
+//
+// E.g.:
+//
+// struct CMyClass
+// {
+// void foo( int i) {}
+// };
+//
+// int bar(int i) { return i; }
+//
+// CMyClass myInstance;
+//
+// CFunctor *pFunctor = CreateFunctor( &myInstance, CMyClass::foo, 8675 );
+// CFunctor *pFunctor2 = CreateFunctor( &bar, 309 );
+//
+// void CallEm()
+// {
+// (*pFunctor)();
+// (*pFunctor2)();
+// }
+//
+//=============================================================================
+
+#ifndef FUNCTORS_H
+#define FUNCTORS_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#include "tier1/refcount.h"
+#include "tier1/utlenvelope.h"
+#include <typeinfo>
+
+
+//-----------------------------------------------------------------------------
+//
+// Macros used as basis for template generation. Just ignore the man behind the
+// curtain
+//
+//-----------------------------------------------------------------------------
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_0
+#define FUNC_TEMPLATE_ARG_PARAMS_0
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_0
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_0
+#define FUNC_ARG_MEMBERS_0
+#define FUNC_ARG_FORMAL_PARAMS_0
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_0
+#define FUNC_CALL_ARGS_INIT_0
+#define FUNC_SOLO_CALL_ARGS_INIT_0
+#define FUNC_CALL_MEMBER_ARGS_0
+#define FUNC_CALL_ARGS_0
+#define FUNC_CALL_DATA_ARGS_0( _var )
+#define FUNC_FUNCTOR_CALL_ARGS_0
+#define FUNC_TEMPLATE_FUNC_PARAMS_0
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_0
+#define FUNC_VALIDATION_STRING_0 V_snprintf( pString, nBufLen, "method( void )" );
+#define FUNC_SEPARATOR_0
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_1 typename ARG_TYPE_1
+#define FUNC_TEMPLATE_ARG_PARAMS_1 , typename ARG_TYPE_1
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_1 , ARG_TYPE_1
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_1 ARG_TYPE_1
+#define FUNC_ARG_MEMBERS_1 ARG_TYPE_1 m_arg1
+#define FUNC_ARG_FORMAL_PARAMS_1 , const ARG_TYPE_1 &arg1
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_1 const ARG_TYPE_1 &arg1
+#define FUNC_CALL_ARGS_INIT_1 , m_arg1( arg1 )
+#define FUNC_SOLO_CALL_ARGS_INIT_1 : m_arg1( arg1 )
+#define FUNC_CALL_MEMBER_ARGS_1 m_arg1
+#define FUNC_CALL_ARGS_1 arg1
+#define FUNC_CALL_DATA_ARGS_1( _var ) _var->m_arg1
+#define FUNC_FUNCTOR_CALL_ARGS_1 , arg1
+#define FUNC_TEMPLATE_FUNC_PARAMS_1 , typename FUNC_ARG_TYPE_1
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_1 FUNC_ARG_TYPE_1
+#define FUNC_VALIDATION_STRING_1 V_snprintf( pString, nBufLen, "method( %s )", typeid( ARG_TYPE_1 ).name() );
+#define FUNC_SEPARATOR_1 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_2 typename ARG_TYPE_1, typename ARG_TYPE_2
+#define FUNC_TEMPLATE_ARG_PARAMS_2 , typename ARG_TYPE_1, typename ARG_TYPE_2
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_2 , ARG_TYPE_1, ARG_TYPE_2
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_2 ARG_TYPE_1, ARG_TYPE_2
+#define FUNC_ARG_MEMBERS_2 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2
+#define FUNC_ARG_FORMAL_PARAMS_2 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_2 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2
+#define FUNC_CALL_ARGS_INIT_2 , m_arg1( arg1 ), m_arg2( arg2 )
+#define FUNC_SOLO_CALL_ARGS_INIT_2 : m_arg1( arg1 ), m_arg2( arg2 )
+#define FUNC_CALL_MEMBER_ARGS_2 m_arg1, m_arg2
+#define FUNC_CALL_ARGS_2 arg1, arg2
+#define FUNC_CALL_DATA_ARGS_2( _var ) _var->m_arg1, _var->m_arg2
+#define FUNC_FUNCTOR_CALL_ARGS_2 , arg1, arg2
+#define FUNC_TEMPLATE_FUNC_PARAMS_2 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_2 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2
+#define FUNC_VALIDATION_STRING_2 V_snprintf( pString, nBufLen, "method( %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name() );
+#define FUNC_SEPARATOR_2 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_3 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3
+#define FUNC_TEMPLATE_ARG_PARAMS_3 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_3 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_3 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3
+#define FUNC_ARG_MEMBERS_3 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3
+#define FUNC_ARG_FORMAL_PARAMS_3 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_3 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3
+#define FUNC_CALL_ARGS_INIT_3 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 )
+#define FUNC_SOLO_CALL_ARGS_INIT_3 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 )
+#define FUNC_CALL_MEMBER_ARGS_3 m_arg1, m_arg2, m_arg3
+#define FUNC_CALL_ARGS_3 arg1, arg2, arg3
+#define FUNC_CALL_DATA_ARGS_3( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3
+#define FUNC_FUNCTOR_CALL_ARGS_3 , arg1, arg2, arg3
+#define FUNC_TEMPLATE_FUNC_PARAMS_3 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_3 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3
+#define FUNC_VALIDATION_STRING_3 V_snprintf( pString, nBufLen, "method( %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name() );
+#define FUNC_SEPARATOR_3 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_4 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4
+#define FUNC_TEMPLATE_ARG_PARAMS_4 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_4 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_4 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4
+#define FUNC_ARG_MEMBERS_4 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4
+#define FUNC_ARG_FORMAL_PARAMS_4 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_4 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4
+#define FUNC_CALL_ARGS_INIT_4 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 )
+#define FUNC_SOLO_CALL_ARGS_INIT_4 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 )
+#define FUNC_CALL_MEMBER_ARGS_4 m_arg1, m_arg2, m_arg3, m_arg4
+#define FUNC_CALL_ARGS_4 arg1, arg2, arg3, arg4
+#define FUNC_CALL_DATA_ARGS_4( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4
+#define FUNC_FUNCTOR_CALL_ARGS_4 , arg1, arg2, arg3, arg4
+#define FUNC_TEMPLATE_FUNC_PARAMS_4 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_4 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4
+#define FUNC_VALIDATION_STRING_4 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name() );
+#define FUNC_SEPARATOR_4 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_5 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5
+#define FUNC_TEMPLATE_ARG_PARAMS_5 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_5 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_5 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5
+#define FUNC_ARG_MEMBERS_5 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5
+#define FUNC_ARG_FORMAL_PARAMS_5 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_5 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5
+#define FUNC_CALL_ARGS_INIT_5 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 )
+#define FUNC_SOLO_CALL_ARGS_INIT_5 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 )
+#define FUNC_CALL_MEMBER_ARGS_5 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5
+#define FUNC_CALL_ARGS_5 arg1, arg2, arg3, arg4, arg5
+#define FUNC_CALL_DATA_ARGS_5( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5
+#define FUNC_FUNCTOR_CALL_ARGS_5 , arg1, arg2, arg3, arg4, arg5
+#define FUNC_TEMPLATE_FUNC_PARAMS_5 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_5 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5
+#define FUNC_VALIDATION_STRING_5 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name() );
+#define FUNC_SEPARATOR_5 ,
+
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_6 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6
+#define FUNC_TEMPLATE_ARG_PARAMS_6 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_6 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_6 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6
+#define FUNC_ARG_MEMBERS_6 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6
+#define FUNC_ARG_FORMAL_PARAMS_6 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_6 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6
+#define FUNC_CALL_ARGS_INIT_6 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 )
+#define FUNC_SOLO_CALL_ARGS_INIT_6 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 )
+#define FUNC_CALL_MEMBER_ARGS_6 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6
+#define FUNC_CALL_ARGS_6 arg1, arg2, arg3, arg4, arg5, arg6
+#define FUNC_CALL_DATA_ARGS_6( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6
+#define FUNC_FUNCTOR_CALL_ARGS_6 , arg1, arg2, arg3, arg4, arg5, arg6
+#define FUNC_TEMPLATE_FUNC_PARAMS_6 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_6 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6
+#define FUNC_VALIDATION_STRING_6 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name() );
+#define FUNC_SEPARATOR_6 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_7 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7
+#define FUNC_TEMPLATE_ARG_PARAMS_7 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_7 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_7 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7
+#define FUNC_ARG_MEMBERS_7 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7;
+#define FUNC_ARG_FORMAL_PARAMS_7 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_7 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7
+#define FUNC_CALL_ARGS_INIT_7 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 )
+#define FUNC_SOLO_CALL_ARGS_INIT_7 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 )
+#define FUNC_CALL_MEMBER_ARGS_7 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7
+#define FUNC_CALL_ARGS_7 arg1, arg2, arg3, arg4, arg5, arg6, arg7
+#define FUNC_CALL_DATA_ARGS_7( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7
+#define FUNC_FUNCTOR_CALL_ARGS_7 , arg1, arg2, arg3, arg4, arg5, arg6, arg7
+#define FUNC_TEMPLATE_FUNC_PARAMS_7 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_7 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7
+#define FUNC_VALIDATION_STRING_7 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name() );
+#define FUNC_SEPARATOR_7 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_8 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8
+#define FUNC_TEMPLATE_ARG_PARAMS_8 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_8 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_8 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8
+#define FUNC_ARG_MEMBERS_8 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8;
+#define FUNC_ARG_FORMAL_PARAMS_8 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_8 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8
+#define FUNC_CALL_ARGS_INIT_8 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 )
+#define FUNC_SOLO_CALL_ARGS_INIT_8 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 )
+#define FUNC_CALL_MEMBER_ARGS_8 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8
+#define FUNC_CALL_ARGS_8 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
+#define FUNC_CALL_DATA_ARGS_8( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8
+#define FUNC_FUNCTOR_CALL_ARGS_8 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
+#define FUNC_TEMPLATE_FUNC_PARAMS_8 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_8 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8
+#define FUNC_VALIDATION_STRING_8 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name() );
+#define FUNC_SEPARATOR_8 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_9 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9
+#define FUNC_TEMPLATE_ARG_PARAMS_9 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_9 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_9 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9
+#define FUNC_ARG_MEMBERS_9 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9;
+#define FUNC_ARG_FORMAL_PARAMS_9 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_9 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9
+#define FUNC_CALL_ARGS_INIT_9 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 )
+#define FUNC_SOLO_CALL_ARGS_INIT_9 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 )
+#define FUNC_CALL_MEMBER_ARGS_9 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9
+#define FUNC_CALL_ARGS_9 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
+#define FUNC_CALL_DATA_ARGS_9( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9
+#define FUNC_FUNCTOR_CALL_ARGS_9 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
+#define FUNC_TEMPLATE_FUNC_PARAMS_9 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_9 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9
+#define FUNC_VALIDATION_STRING_9 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name() );
+#define FUNC_SEPARATOR_9 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_10 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10
+#define FUNC_TEMPLATE_ARG_PARAMS_10 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_10 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_10 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10
+#define FUNC_ARG_MEMBERS_10 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10;
+#define FUNC_ARG_FORMAL_PARAMS_10 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_10 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10
+#define FUNC_CALL_ARGS_INIT_10 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 )
+#define FUNC_SOLO_CALL_ARGS_INIT_10 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 )
+#define FUNC_CALL_MEMBER_ARGS_10 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10
+#define FUNC_CALL_ARGS_10 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10
+#define FUNC_CALL_DATA_ARGS_10( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10
+#define FUNC_FUNCTOR_CALL_ARGS_10 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10
+#define FUNC_TEMPLATE_FUNC_PARAMS_10 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_10 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10
+#define FUNC_VALIDATION_STRING_10 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name() );
+#define FUNC_SEPARATOR_10 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_11 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11
+#define FUNC_TEMPLATE_ARG_PARAMS_11 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_11 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_11 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11
+#define FUNC_ARG_MEMBERS_11 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11
+#define FUNC_ARG_FORMAL_PARAMS_11 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_11 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11
+#define FUNC_CALL_ARGS_INIT_11 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 )
+#define FUNC_SOLO_CALL_ARGS_INIT_11 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 )
+#define FUNC_CALL_MEMBER_ARGS_11 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11
+#define FUNC_CALL_ARGS_11 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11
+#define FUNC_CALL_DATA_ARGS_11( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11
+#define FUNC_FUNCTOR_CALL_ARGS_11 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11
+#define FUNC_TEMPLATE_FUNC_PARAMS_11 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_11 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11
+#define FUNC_VALIDATION_STRING_11 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name() );
+#define FUNC_SEPARATOR_11 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_12 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12
+#define FUNC_TEMPLATE_ARG_PARAMS_12 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_12 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_12 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12
+#define FUNC_ARG_MEMBERS_12 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12
+#define FUNC_ARG_FORMAL_PARAMS_12 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_12 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12
+#define FUNC_CALL_ARGS_INIT_12 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 )
+#define FUNC_SOLO_CALL_ARGS_INIT_12 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 )
+#define FUNC_CALL_MEMBER_ARGS_12 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12
+#define FUNC_CALL_ARGS_12 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12
+#define FUNC_CALL_DATA_ARGS_12( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11, _var->m_arg12
+#define FUNC_FUNCTOR_CALL_ARGS_12 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12
+#define FUNC_TEMPLATE_FUNC_PARAMS_12 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_12 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12
+#define FUNC_VALIDATION_STRING_12 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name(), typeid( ARG_TYPE_12 ).name() );
+#define FUNC_SEPARATOR_12 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_13 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13
+#define FUNC_TEMPLATE_ARG_PARAMS_13 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_13 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_13 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13
+#define FUNC_ARG_MEMBERS_13 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12; ARG_TYPE_13 m_arg13
+#define FUNC_ARG_FORMAL_PARAMS_13 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_13 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13
+#define FUNC_CALL_ARGS_INIT_13 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 )
+#define FUNC_SOLO_CALL_ARGS_INIT_13 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 )
+#define FUNC_CALL_MEMBER_ARGS_13 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13
+#define FUNC_CALL_ARGS_13 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13
+#define FUNC_CALL_DATA_ARGS_13( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11, _var->m_arg12, _var->m_arg13
+#define FUNC_FUNCTOR_CALL_ARGS_13 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13
+#define FUNC_TEMPLATE_FUNC_PARAMS_13 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12, typename FUNC_ARG_TYPE_13
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_13 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12, FUNC_ARG_TYPE_13
+#define FUNC_VALIDATION_STRING_13 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name(), typeid( ARG_TYPE_12 ).name(), typeid( ARG_TYPE_13 ).name() );
+#define FUNC_SEPARATOR_13 ,
+
+#define FUNC_SOLO_TEMPLATE_ARG_PARAMS_14 typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13, typename ARG_TYPE_14
+#define FUNC_TEMPLATE_ARG_PARAMS_14 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13, typename ARG_TYPE_14
+#define FUNC_BASE_TEMPLATE_ARG_PARAMS_14 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13, ARG_TYPE_14
+#define FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_14 ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13, ARG_TYPE_14
+#define FUNC_ARG_MEMBERS_14 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12; ARG_TYPE_13 m_arg13; ARG_TYPE_14 m_arg14
+#define FUNC_ARG_FORMAL_PARAMS_14 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13, const ARG_TYPE_14 &arg14
+#define FUNC_PROXY_ARG_FORMAL_PARAMS_14 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13, const ARG_TYPE_14 &arg14
+#define FUNC_CALL_ARGS_INIT_14 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 ), m_arg14( arg14 )
+#define FUNC_SOLO_CALL_ARGS_INIT_14 : m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 ), m_arg14( arg14 )
+#define FUNC_CALL_MEMBER_ARGS_14 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14
+#define FUNC_CALL_ARGS_14 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14
+#define FUNC_CALL_DATA_ARGS_14( _var ) _var->m_arg1, _var->m_arg2, _var->m_arg3, _var->m_arg4, _var->m_arg5, _var->m_arg6, _var->m_arg7, _var->m_arg8, _var->m_arg9, _var->m_arg10, _var->m_arg11, _var->m_arg12, _var->m_arg13, _var->m_arg14
+#define FUNC_FUNCTOR_CALL_ARGS_14 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14
+#define FUNC_TEMPLATE_FUNC_PARAMS_14 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12, typename FUNC_ARG_TYPE_13, typename FUNC_ARG_TYPE_14
+#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_14 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12, FUNC_ARG_TYPE_13, FUNC_ARG_TYPE_14
+#define FUNC_VALIDATION_STRING_14 V_snprintf( pString, nBufLen, "method( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )", typeid( ARG_TYPE_1 ).name(), typeid( ARG_TYPE_2 ).name(), typeid( ARG_TYPE_3 ).name(), typeid( ARG_TYPE_4 ).name(), typeid( ARG_TYPE_5 ).name(), typeid( ARG_TYPE_6 ).name(), typeid( ARG_TYPE_7 ).name(), typeid( ARG_TYPE_8 ).name(), typeid( ARG_TYPE_9 ).name(), typeid( ARG_TYPE_10 ).name(), typeid( ARG_TYPE_11 ).name(), typeid( ARG_TYPE_12 ).name(), typeid( ARG_TYPE_13 ).name(), typeid( ARG_TYPE_14 ).name() );
+#define FUNC_SEPARATOR_14 ,
+
+#define FUNC_GENERATE_ALL_BUT0( INNERMACRONAME ) \
+ INNERMACRONAME(1); \
+ INNERMACRONAME(2); \
+ INNERMACRONAME(3); \
+ INNERMACRONAME(4); \
+ INNERMACRONAME(5); \
+ INNERMACRONAME(6); \
+ INNERMACRONAME(7); \
+ INNERMACRONAME(8); \
+ INNERMACRONAME(9); \
+ INNERMACRONAME(10);\
+ INNERMACRONAME(11);\
+ INNERMACRONAME(12);\
+ INNERMACRONAME(13);\
+ INNERMACRONAME(14)
+
+#define FUNC_GENERATE_ALL( INNERMACRONAME ) \
+ INNERMACRONAME(0); \
+ FUNC_GENERATE_ALL_BUT0( INNERMACRONAME )
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Base class of all function objects
+//
+//-----------------------------------------------------------------------------
+abstract_class CFunctor : public IRefCounted
+{
+public:
+ CFunctor()
+ {
+#ifdef DEBUG
+ m_nUserID = 0;
+#endif
+ }
+ virtual ~CFunctor() {}
+ virtual void operator()() = 0;
+
+ unsigned m_nUserID; // For debugging
+};
+
+
+//-----------------------------------------------------------------------------
+// NOTE: Functor data + functor callback are tied together
+// The basic idea is that someone creates the functor data. At a later point,
+// the functor data is passed to a functor callback. Validation strings
+// are compared in debug builds to ensure the data matches the callback
+//-----------------------------------------------------------------------------
+abstract_class CFunctorData : public IRefCounted
+{
+public:
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const = 0;
+};
+
+abstract_class CFunctorCallback : public IRefCounted
+{
+public:
+ virtual bool IsEqual( CFunctorCallback *pSrc ) const = 0;
+ virtual void operator()( CFunctorData *pData ) = 0;
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const = 0;
+ virtual const char *GetImplClassName() const = 0;
+ virtual const void *GetTarget() const = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// When calling through a functor, care needs to be taken to not pass objects that might go away.
+// Since this code determines the type to store in the functor based on the actual arguments,
+// this is achieved by changing the point of call.
+//
+// See also CUtlEnvelope
+//-----------------------------------------------------------------------------
+// convert a reference to a passable value
+template <typename T>
+inline T RefToVal(const T &item)
+{
+ return item;
+}
+
+
+//-----------------------------------------------------------------------------
+// This class can be used to pass into a functor a proxy object for a pointer
+// to be resolved later. For example, you can execute a "call" on a resource
+// whose actual value is not known until a later time
+//-----------------------------------------------------------------------------
+template <typename T>
+class CLateBoundPtr
+{
+public:
+ CLateBoundPtr( T **ppObject )
+ : m_ppObject( ppObject )
+ {
+ }
+
+ T *operator->() { return *m_ppObject; }
+ T &operator *() { return **m_ppObject; }
+ operator T *() const { return (T*)(*m_ppObject); }
+ operator void *() { return *m_ppObject; }
+
+private:
+ T **m_ppObject;
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Classes to define memory management policies when operating
+// on pointers to members
+//
+//-----------------------------------------------------------------------------
+class CFuncMemPolicyNone
+{
+public:
+ static void OnAcquire(void *pObject) {}
+ static void OnRelease(void *pObject) {}
+};
+
+template <class OBJECT_TYPE_PTR = IRefCounted *>
+class CFuncMemPolicyRefCount
+{
+public:
+ static void OnAcquire(OBJECT_TYPE_PTR pObject) { pObject->AddRef(); }
+ static void OnRelease(OBJECT_TYPE_PTR pObject) { pObject->Release(); }
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Function proxy is a generic facility for holding a function
+// pointer. Can be used on own, though primarily for use
+// by this file
+//
+//-----------------------------------------------------------------------------
+template <class OBJECT_TYPE_PTR, typename FUNCTION_TYPE, class MEM_POLICY = CFuncMemPolicyNone >
+class CMemberFuncProxyBase
+{
+public:
+ bool operator==( const CMemberFuncProxyBase &src ) const
+ {
+ return m_pfnProxied == src.m_pfnProxied && m_pObject == src.m_pObject;
+ }
+
+ const void *GetTarget() const
+ {
+ return m_pObject;
+ }
+
+protected:
+ CMemberFuncProxyBase( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied )
+ : m_pObject( pObject ),
+ m_pfnProxied( pfnProxied )
+ {
+ MEM_POLICY::OnAcquire(m_pObject);
+ }
+
+ ~CMemberFuncProxyBase()
+ {
+ MEM_POLICY::OnRelease(m_pObject);
+ }
+
+ void Set( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied )
+ {
+ m_pfnProxied = pfnProxied;
+ m_pObject = pObject;
+ }
+
+ void OnCall()
+ {
+ Assert( (void *)m_pObject != NULL );
+ }
+
+ FUNCTION_TYPE m_pfnProxied;
+ OBJECT_TYPE_PTR m_pObject;
+};
+
+
+#define DEFINE_MEMBER_FUNC_PROXY( N ) \
+ template <class OBJECT_TYPE_PTR, typename FUNCTION_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N, class MEM_POLICY = CFuncMemPolicyNone> \
+ class CMemberFuncProxy##N : public CMemberFuncProxyBase<OBJECT_TYPE_PTR, FUNCTION_TYPE, MEM_POLICY> \
+ { \
+ public: \
+ CMemberFuncProxy##N( OBJECT_TYPE_PTR pObject = NULL, FUNCTION_TYPE pfnProxied = NULL ) \
+ : CMemberFuncProxyBase<OBJECT_TYPE_PTR, FUNCTION_TYPE, MEM_POLICY >( pObject, pfnProxied ) \
+ { \
+ } \
+ \
+ void operator()( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ this->OnCall(); \
+ ((*this->m_pObject).*this->m_pfnProxied)( FUNC_CALL_ARGS_##N ); \
+ } \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_PROXY );
+
+
+//-----------------------------------------------------------------------------
+//
+// The actual functor implementation
+//
+//-----------------------------------------------------------------------------
+
+#include "tier0/memdbgon.h"
+
+typedef CRefCounted1<CFunctor, CRefCountServiceMT> CFunctorBase;
+
+#define DEFINE_FUNCTOR_TEMPLATE(N) \
+ template <typename FUNC_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N, class FUNCTOR_BASE = CFunctorBase> \
+ class CFunctor##N : public CFunctorBase \
+ { \
+ public: \
+ CFunctor##N( FUNC_TYPE pfnProxied FUNC_ARG_FORMAL_PARAMS_##N ) : m_pfnProxied( pfnProxied ) FUNC_CALL_ARGS_INIT_##N {} \
+ void operator()() { m_pfnProxied(FUNC_CALL_MEMBER_ARGS_##N); } \
+ \
+ private: \
+ FUNC_TYPE m_pfnProxied; \
+ FUNC_ARG_MEMBERS_##N; \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_FUNCTOR_TEMPLATE );
+
+#define DEFINE_MEMBER_FUNCTOR( N ) \
+ template <class OBJECT_TYPE_PTR, typename FUNCTION_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N, class FUNCTOR_BASE = CFunctorBase, class MEM_POLICY = CFuncMemPolicyNone> \
+ class CMemberFunctor##N : public FUNCTOR_BASE \
+ { \
+ public: \
+ CMemberFunctor##N( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied FUNC_ARG_FORMAL_PARAMS_##N ) : m_Proxy( pObject, pfnProxied ) FUNC_CALL_ARGS_INIT_##N {} \
+ void operator()() { m_Proxy(FUNC_CALL_MEMBER_ARGS_##N); } \
+ \
+ private: \
+ CMemberFuncProxy##N<OBJECT_TYPE_PTR, FUNCTION_TYPE FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, MEM_POLICY> m_Proxy; \
+ FUNC_ARG_MEMBERS_##N; \
+ };
+
+
+FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR );
+
+typedef CRefCounted1<CFunctorData, CRefCountServiceMT> CFunctorDataBase;
+class CFunctorCallbackBase : public CRefCounted1<CFunctorCallback, CRefCountServiceMT>
+{
+protected:
+ virtual void ValidateFunctorData( CFunctorData *pData )
+ {
+#ifdef _DEBUG
+ char pDataString[1024];
+ char pCallbackString[1024];
+ ComputeValidationString( pCallbackString, sizeof(pCallbackString) );
+ pData->ComputeValidationString( pDataString, sizeof(pDataString) );
+ bool bMatch = !V_stricmp( pDataString, pCallbackString );
+ if ( !bMatch )
+ {
+ Warning( "Functor doesn't match data!\n\tExpected:\t%s\n\tEncountered:\t%s\n",
+ pCallbackString, pDataString );
+ Assert( 0 );
+ }
+#endif
+ }
+};
+
+#define DEFINE_FUNCTOR_DATA_TEMPLATE(N) \
+ template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
+ class CFunctorData##N : public CFunctorDataBase \
+ { \
+ public: \
+ CFunctorData##N( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) FUNC_SOLO_CALL_ARGS_INIT_##N {} \
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_##N } \
+ FUNC_ARG_MEMBERS_##N; \
+ }
+
+class CFunctorData0 : public CFunctorDataBase
+{
+public:
+ CFunctorData0( ) {}
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_0 }
+};
+
+FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_DATA_TEMPLATE );
+
+#define DEFINE_FUNCTOR_CALLBACK_TEMPLATE(N) \
+ template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
+ class CFunctorCallback##N : public CFunctorCallbackBase \
+ { \
+ typedef void (*Callback_t)( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ); \
+ public: \
+ CFunctorCallback##N( Callback_t pfnProxied ) : m_pfnProxied( pfnProxied ) {} \
+ void operator()( CFunctorData *pFunctorDataBase ) \
+ { \
+ ValidateFunctorData( pFunctorDataBase ); \
+ CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N > *pFunctorData = static_cast< CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >* >( pFunctorDataBase ); \
+ m_pfnProxied( FUNC_CALL_DATA_ARGS_##N(pFunctorData) ); \
+ } \
+ virtual bool IsEqual( CFunctorCallback *pSrc ) const { return !V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) && ( m_pfnProxied == static_cast< CFunctorCallback##N * >( pSrc )->m_pfnProxied ); } \
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_##N } \
+ virtual const char *GetImplClassName() const { return "CFunctorCallback" #N; } \
+ virtual const void *GetTarget() const { return m_pfnProxied; } \
+ private: \
+ Callback_t m_pfnProxied; \
+ }
+
+class CFunctorCallback0 : public CFunctorCallbackBase
+{
+ typedef void (*Callback_t)( );
+public:
+ CFunctorCallback0( Callback_t pfnProxied ) : m_pfnProxied( pfnProxied ) {}
+ void operator()( CFunctorData *pFunctorDataBase )
+ {
+ ValidateFunctorData( pFunctorDataBase );
+ m_pfnProxied( );
+ }
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_0 }
+ virtual bool IsEqual( CFunctorCallback *pSrc ) const
+ {
+ if ( V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) )
+ return false;
+ return m_pfnProxied == static_cast< CFunctorCallback0* >( pSrc )->m_pfnProxied;
+ }
+ virtual const char *GetImplClassName() const { return "CFunctorCallback0"; }
+ virtual const void *GetTarget() const { return ( void * )m_pfnProxied; }
+private:
+ Callback_t m_pfnProxied;
+};
+
+FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_CALLBACK_TEMPLATE );
+
+#define DEFINE_MEMBER_FUNCTOR_CALLBACK_TEMPLATE( N ) \
+ template < class FUNCTION_CLASS FUNC_TEMPLATE_ARG_PARAMS_##N, class MEM_POLICY = CFuncMemPolicyNone > \
+ class CMemberFunctorCallback##N : public CFunctorCallbackBase \
+ { \
+ typedef void (FUNCTION_CLASS::*MemberCallback_t)( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ); \
+ public: \
+ CMemberFunctorCallback##N( FUNCTION_CLASS *pObject, MemberCallback_t pfnProxied ) : m_Proxy( pObject, pfnProxied ) {} \
+ void operator()( CFunctorData *pFunctorDataBase ) \
+ { \
+ ValidateFunctorData( pFunctorDataBase ); \
+ CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N > *pFunctorData = static_cast< CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >* >( pFunctorDataBase ); \
+ m_Proxy( FUNC_CALL_DATA_ARGS_##N( pFunctorData ) ); \
+ } \
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_##N } \
+ virtual bool IsEqual( CFunctorCallback *pSrc ) const { return !V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) && ( m_Proxy == static_cast< CMemberFunctorCallback##N* >( pSrc )->m_Proxy ); } \
+ virtual const char *GetImplClassName() const { return "CMemberFunctorCallback" #N; } \
+ virtual const void *GetTarget() const { return m_Proxy.GetTarget(); } \
+ private: \
+ CMemberFuncProxy##N< FUNCTION_CLASS *, MemberCallback_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, MEM_POLICY> m_Proxy; \
+ }
+
+template < class FUNCTION_CLASS, class MEM_POLICY = CFuncMemPolicyNone >
+class CMemberFunctorCallback0 : public CFunctorCallbackBase
+{
+ typedef void (FUNCTION_CLASS::*MemberCallback_t)( );
+public:
+ CMemberFunctorCallback0( FUNCTION_CLASS *pObject, MemberCallback_t pfnProxied ) : m_Proxy( pObject, pfnProxied ) {}
+ void operator()( CFunctorData *pFunctorDataBase )
+ {
+ ValidateFunctorData( pFunctorDataBase );
+ m_Proxy( );
+ }
+ virtual void ComputeValidationString( char *pString, size_t nBufLen ) const { FUNC_VALIDATION_STRING_0 }
+ virtual bool IsEqual( CFunctorCallback *pSrc ) const
+ {
+ if ( V_stricmp( GetImplClassName(), pSrc->GetImplClassName() ) )
+ return false;
+ return m_Proxy == static_cast< CMemberFunctorCallback0 * >( pSrc )->m_Proxy;
+ }
+ virtual const char *GetImplClassName() const { return "CMemberFunctorCallback0"; }
+ virtual const void *GetTarget() const { return m_Proxy.GetTarget(); }
+private:
+ CMemberFuncProxy0< FUNCTION_CLASS *, MemberCallback_t, MEM_POLICY > m_Proxy;
+};
+
+FUNC_GENERATE_ALL_BUT0( DEFINE_MEMBER_FUNCTOR_CALLBACK_TEMPLATE );
+
+
+//-----------------------------------------------------------------------------
+//
+// The real magic, letting the compiler figure out all the right template parameters
+//
+//-----------------------------------------------------------------------------
+
+#define DEFINE_NONMEMBER_FUNCTOR_FACTORY(N) \
+ template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateFunctor(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
+ return new CFunctor##N<Func_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N>( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY );
+
+//-------------------------------------
+
+#define DEFINE_MEMBER_FUNCTOR_FACTORY(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY );
+
+//-------------------------------------
+
+#define DEFINE_CONST_MEMBER_FUNCTOR_FACTORY(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY );
+
+//-------------------------------------
+
+#define DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateRefCountingFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY );
+
+//-------------------------------------
+
+#define DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateRefCountingFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY );
+
+#define DEFINE_FUNCTOR_DATA_FACTORY(N) \
+ template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
+ inline CFunctorData *CreateFunctorData( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new CFunctorData##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >( FUNC_CALL_ARGS_##N ); \
+ }
+
+inline CFunctorData *CreateFunctorData()
+{
+ return new CFunctorData0();
+}
+
+FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_DATA_FACTORY );
+
+#define DEFINE_FUNCTOR_CALLBACK_FACTORY(N) \
+ template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N > \
+ inline CFunctorCallback *CreateFunctorCallback( void (*pfnProxied)( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) ) \
+ { \
+ return new CFunctorCallback##N< FUNC_SOLO_BASE_TEMPLATE_ARG_PARAMS_##N >( pfnProxied ); \
+ }
+
+inline CFunctorCallback *CreateFunctorCallback( void (*pfnProxied)() )
+{
+ return new CFunctorCallback0( pfnProxied );
+}
+
+FUNC_GENERATE_ALL_BUT0( DEFINE_FUNCTOR_CALLBACK_FACTORY );
+
+#define DEFINE_MEMBER_FUNCTOR_CALLBACK_FACTORY(N) \
+ template < typename FUNCTION_CLASS FUNC_TEMPLATE_ARG_PARAMS_##N > \
+ inline CFunctorCallback *CreateFunctorCallback( FUNCTION_CLASS *pObject, void ( FUNCTION_CLASS::*pfnProxied )( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) ) \
+ { \
+ return new CMemberFunctorCallback##N< FUNCTION_CLASS FUNC_BASE_TEMPLATE_ARG_PARAMS_##N >( pObject, pfnProxied ); \
+ }
+
+FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_CALLBACK_FACTORY );
+
+
+//-----------------------------------------------------------------------------
+//
+// Templates to assist early-out direct call code
+//
+//-----------------------------------------------------------------------------
+
+#define DEFINE_NONMEMBER_FUNCTOR_DIRECT(N) \
+ template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline void FunctorDirectCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+{ \
+ (*pfnProxied)( FUNC_CALL_ARGS_##N ); \
+}
+
+FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_DIRECT );
+
+
+//-------------------------------------
+
+#define DEFINE_MEMBER_FUNCTOR_DIRECT(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline void FunctorDirectCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+{ \
+ ((*pObject).*pfnProxied)(FUNC_CALL_ARGS_##N); \
+}
+
+FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_DIRECT );
+
+//-------------------------------------
+
+#define DEFINE_CONST_MEMBER_FUNCTOR_DIRECT(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline void FunctorDirectCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+{ \
+ ((*pObject).*pfnProxied)(FUNC_CALL_ARGS_##N); \
+}
+
+FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_DIRECT );
+
+#include "tier0/memdbgoff.h"
+
+//-----------------------------------------------------------------------------
+// Factory class useable as templated traits
+//-----------------------------------------------------------------------------
+
+class CDefaultFunctorFactory
+{
+public:
+ FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY );
+ FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY );
+ FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY );
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY );
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY );
+};
+
+template <class CAllocator, class CCustomFunctorBase = CFunctorBase>
+class CCustomizedFunctorFactory
+{
+public:
+ void SetAllocator( CAllocator *pAllocator )
+ {
+ m_pAllocator = pAllocator;
+ }
+
+ #define DEFINE_NONMEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
+ template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateFunctor( FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
+ return new (m_pAllocator->Alloc( sizeof(CFunctor##N<Func_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>) )) CFunctor##N<Func_t FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \
+ }
+
+ FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY_CUSTOM );
+
+ //-------------------------------------
+
+ #define DEFINE_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+ FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY_CUSTOM );
+
+ //-------------------------------------
+
+ #define DEFINE_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase>(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+ FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM );
+
+ //-------------------------------------
+
+ #define DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateRefCountingFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY_CUSTOM );
+
+ //-------------------------------------
+
+ #define DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \
+ template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
+ inline CFunctor *CreateRefCountingFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
+ { \
+ return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >) )) CMemberFunctor##N<OBJECT_TYPE_PTR, FUNCTION_RETTYPE (FUNCTION_CLASS::*)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N) const FUNC_BASE_TEMPLATE_ARG_PARAMS_##N, CCustomFunctorBase, CFuncMemPolicyRefCount<OBJECT_TYPE_PTR> >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \
+ }
+
+ FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM );
+
+private:
+ CAllocator *m_pAllocator;
+
+};
+
+//-----------------------------------------------------------------------------
+
+#endif // FUNCTORS_H
diff --git a/external/vpc/public/tier1/generichash.h b/external/vpc/public/tier1/generichash.h
new file mode 100644
index 0000000..44733d6
--- /dev/null
+++ b/external/vpc/public/tier1/generichash.h
@@ -0,0 +1,116 @@
+//======= Copyright � 2005, , Valve Corporation, All rights reserved. =========
+//
+// Purpose: Variant Pearson Hash general purpose hashing algorithm described
+// by Cargill in C++ Report 1994. Generates a 16-bit result.
+//
+//=============================================================================
+
+#ifndef GENERICHASH_H
+#define GENERICHASH_H
+
+#if defined(_WIN32)
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+
+unsigned FASTCALL HashString( const char *pszKey );
+unsigned FASTCALL HashStringCaseless( const char *pszKey );
+unsigned FASTCALL HashStringCaselessConventional( const char *pszKey );
+unsigned FASTCALL Hash4( const void *pKey );
+unsigned FASTCALL Hash8( const void *pKey );
+unsigned FASTCALL Hash12( const void *pKey );
+unsigned FASTCALL Hash16( const void *pKey );
+unsigned FASTCALL HashBlock( const void *pKey, unsigned size );
+
+unsigned FASTCALL HashInt( const int key );
+
+// hash a uint32 into a uint32
+FORCEINLINE uint32 HashIntAlternate( uint32 n)
+{
+ n = ( n + 0x7ed55d16 ) + ( n << 12 );
+ n = ( n ^ 0xc761c23c ) ^ ( n >> 19 );
+ n = ( n + 0x165667b1 ) + ( n << 5 );
+ n = ( n + 0xd3a2646c ) ^ ( n << 9 );
+ n = ( n + 0xfd7046c5 ) + ( n << 3 );
+ n = ( n ^ 0xb55a4f09 ) ^ ( n >> 16 );
+ return n;
+}
+
+inline unsigned HashIntConventional( const int n ) // faster but less effective
+{
+ // first byte
+ unsigned hash = 0xAAAAAAAA + (n & 0xFF);
+ // second byte
+ hash = ( hash << 5 ) + hash + ( (n >> 8) & 0xFF );
+ // third byte
+ hash = ( hash << 5 ) + hash + ( (n >> 16) & 0xFF );
+ // fourth byte
+ hash = ( hash << 5 ) + hash + ( (n >> 24) & 0xFF );
+
+ return hash;
+
+ /* this is the old version, which would cause a load-hit-store on every
+ line on a PowerPC, and therefore took hundreds of clocks to execute!
+
+ byte *p = (byte *)&n;
+ unsigned hash = 0xAAAAAAAA + *p++;
+ hash = ( ( hash << 5 ) + hash ) + *p++;
+ hash = ( ( hash << 5 ) + hash ) + *p++;
+ return ( ( hash << 5 ) + hash ) + *p;
+ */
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline unsigned HashItem( const T &item )
+{
+ // TODO: Confirm comiler optimizes out unused paths
+ if ( sizeof(item) == 4 )
+ return Hash4( &item );
+ else if ( sizeof(item) == 8 )
+ return Hash8( &item );
+ else if ( sizeof(item) == 12 )
+ return Hash12( &item );
+ else if ( sizeof(item) == 16 )
+ return Hash16( &item );
+ else
+ return HashBlock( &item, sizeof(item) );
+}
+
+template <> inline unsigned HashItem<int>(const int &key )
+{
+ return HashInt( key );
+}
+
+template <> inline unsigned HashItem<unsigned>(const unsigned &key )
+{
+ return HashInt( (int)key );
+}
+
+template<> inline unsigned HashItem<const char *>(const char * const &pszKey )
+{
+ return HashString( pszKey );
+}
+
+template<> inline unsigned HashItem<char *>(char * const &pszKey )
+{
+ return HashString( pszKey );
+}
+
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Murmur hash
+//-----------------------------------------------------------------------------
+uint32 MurmurHash2( const void * key, int len, uint32 seed );
+
+// return murmurhash2 of a downcased string
+uint32 MurmurHash2LowerCase( char const *pString, uint32 nSeed );
+
+uint64 MurmurHash64( const void * key, int len, uint32 seed );
+
+
+#endif /* !GENERICHASH_H */
diff --git a/external/vpc/public/tier1/iconvar.h b/external/vpc/public/tier1/iconvar.h
new file mode 100644
index 0000000..397c111
--- /dev/null
+++ b/external/vpc/public/tier1/iconvar.h
@@ -0,0 +1,121 @@
+//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef ICONVAR_H
+#define ICONVAR_H
+
+#if _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/platform.h"
+#include "tier1/strtools.h"
+#include "color.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+class IConVar;
+class CCommand;
+
+
+//-----------------------------------------------------------------------------
+// ConVar flags
+//-----------------------------------------------------------------------------
+// The default, no flags at all
+#define FCVAR_NONE 0
+
+// Command to ConVars and ConCommands
+// ConVar Systems
+#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
+#define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined.
+#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
+#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
+#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out.
+
+// ConVar only
+#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
+#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
+#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
+#define FCVAR_NOTIFY (1<<8) // notifies players when changed
+#define FCVAR_USERINFO (1<<9) // changes the client's info string
+
+#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
+#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
+#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
+
+// It's a ConVar that's shared between the client and the server.
+// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
+// client, of course )
+// If a change is requested it must come from the console (i.e., no remote client changes)
+// If a value is changed while a server is active, it's replicated to all connected clients
+#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
+#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
+#define FCVAR_SS (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated
+#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
+#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
+#define FCVAR_SS_ADDED (1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players
+#define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers
+#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload
+#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload
+
+#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
+#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread
+#define FCVAR_ARCHIVE_GAMECONSOLE (1<<24) // cvar written to config.cfg on the Xbox
+
+#define FCVAR_SERVER_CAN_EXECUTE (1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
+#define FCVAR_SERVER_CANNOT_QUERY (1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
+#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command.
+ // Note: IVEngineClient::ClientCmd_Unrestricted can run any client command.
+
+#define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars
+// #define FCVAR_AVAILABLE (1<<26)
+// #define FCVAR_AVAILABLE (1<<27)
+// #define FCVAR_AVAILABLE (1<<31)
+
+#define FCVAR_MATERIAL_THREAD_MASK ( FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD )
+
+//-----------------------------------------------------------------------------
+// Called when a ConVar changes value
+// NOTE: For FCVAR_NEVER_AS_STRING ConVars, pOldValue == NULL
+//-----------------------------------------------------------------------------
+typedef void ( *FnChangeCallback_t )( IConVar *var, const char *pOldValue, float flOldValue );
+
+
+//-----------------------------------------------------------------------------
+// Abstract interface for ConVars
+//-----------------------------------------------------------------------------
+abstract_class IConVar
+{
+public:
+ // Value set
+ virtual void SetValue( const char *pValue ) = 0;
+ virtual void SetValue( float flValue ) = 0;
+ virtual void SetValue( int nValue ) = 0;
+ virtual void SetValue( Color value ) = 0;
+
+ // Return name of command
+ virtual const char *GetName( void ) const = 0;
+
+ // Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars
+ virtual const char *GetBaseName( void ) const = 0;
+
+ // Accessors.. not as efficient as using GetState()/GetInfo()
+ // if you call these methods multiple times on the same IConVar
+ virtual bool IsFlagSet( int nFlag ) const = 0;
+
+ virtual int GetSplitScreenPlayerSlot() const = 0;
+};
+
+
+#endif // ICONVAR_H
diff --git a/external/vpc/public/tier1/interface.h b/external/vpc/public/tier1/interface.h
new file mode 100644
index 0000000..90b0f11
--- /dev/null
+++ b/external/vpc/public/tier1/interface.h
@@ -0,0 +1,226 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+// This header defines the interface convention used in the valve engine.
+// To make an interface and expose it:
+// 1. The interface must be ALL pure virtuals, and have no data members.
+// 2. Define a name for it.
+// 3. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE.
+
+// Versioning
+// There are two versioning cases that are handled by this:
+// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case,
+// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface.
+// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface
+// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and
+// expose it for the old interface.
+
+// Static Linking:
+// Must mimic unique seperate class 'InterfaceReg' constructors per subsystem.
+// Each subsystem can then import and export interfaces as expected.
+// This is achieved through unique namespacing 'InterfaceReg' via symbol _SUBSYSTEM.
+// Static Linking also needs to generate unique symbols per interface so as to
+// provide a 'stitching' method whereby these interface symbols can be referenced
+// via the lib's primary module (usually the lib's interface exposure)
+// therby stitching all of that lib's code/data together for eventual final exe link inclusion.
+
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// TODO: move interface.cpp into tier0 library.
+// Need to include platform.h in case _PS3 and other tokens are not yet defined
+#include "tier0/platform.h"
+
+#if defined( POSIX ) && !defined( _PS3 )
+
+#include <dlfcn.h> // dlopen,dlclose, et al
+#include <unistd.h>
+
+#define GetProcAddress dlsym
+
+#ifdef _snprintf
+#undef _snprintf
+#endif
+#define _snprintf snprintf
+#endif // POSIX && !_PS3
+
+// All interfaces derive from this.
+class IBaseInterface
+{
+public:
+ virtual ~IBaseInterface() {}
+};
+
+#if !defined( _X360 )
+#define CREATEINTERFACE_PROCNAME "CreateInterface"
+#else
+// x360 only allows ordinal exports, .def files export "CreateInterface" at 1
+#define CREATEINTERFACE_PROCNAME ((const char*)1)
+#endif
+
+typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode);
+typedef void* (*InstantiateInterfaceFn)();
+
+// Used internally to register classes.
+class InterfaceReg
+{
+public:
+ InterfaceReg(InstantiateInterfaceFn fn, const char *pName);
+
+public:
+ InstantiateInterfaceFn m_CreateFn;
+ const char *m_pName;
+
+ InterfaceReg *m_pNext; // For the global list.
+};
+
+// Use this to expose an interface that can have multiple instances.
+// e.g.:
+// EXPOSE_INTERFACE( CInterfaceImp, IInterface, "MyInterface001" )
+// This will expose a class called CInterfaceImp that implements IInterface (a pure class)
+// clients can receive a pointer to this class by calling CreateInterface( "MyInterface001" )
+//
+// In practice, the shared header file defines the interface (IInterface) and version name ("MyInterface001")
+// so that each component can use these names/vtables to communicate
+//
+// A single class can support multiple interfaces through multiple inheritance
+//
+// Use this if you want to write the factory function.
+#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
+#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \
+ static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName);
+#else
+#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \
+ namespace _SUBSYSTEM \
+ { \
+ static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName); \
+ }
+#endif
+
+#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
+#define EXPOSE_INTERFACE(className, interfaceName, versionName) \
+ static void* __Create##className##_interface() {return static_cast<interfaceName *>( new className );} \
+ static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName );
+#else
+#define EXPOSE_INTERFACE(className, interfaceName, versionName) \
+ namespace _SUBSYSTEM \
+ { \
+ static void* __Create##className##_interface() {return static_cast<interfaceName *>( new className );} \
+ static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName ); \
+ }
+#endif
+
+// Use this to expose a singleton interface with a global variable you've created.
+#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
+#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
+ static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceName *>( &globalVarName );} \
+ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName);
+#else
+#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \
+ namespace _SUBSYSTEM \
+ { \
+ static void* __Create##className##interfaceName##_interface() {return static_cast<interfaceName *>( &globalVarName );} \
+ static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \
+ }
+#endif
+
+// Use this to expose a singleton interface. This creates the global variable for you automatically.
+#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM)
+#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
+ static className __g_##className##_singleton; \
+ EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
+#else
+#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \
+ namespace _SUBSYSTEM \
+ { \
+ static className __g_##className##_singleton; \
+ } \
+ EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton)
+#endif
+
+// load/unload components
+class CSysModule;
+
+// interface return status
+enum
+{
+ IFACE_OK = 0,
+ IFACE_FAILED
+};
+
+//-----------------------------------------------------------------------------
+// This function is automatically exported and allows you to access any interfaces exposed with the above macros.
+// if pReturnCode is set, it will return one of the following values (IFACE_OK, IFACE_FAILED)
+// extend this for other error conditions/code
+//-----------------------------------------------------------------------------
+DLL_EXPORT void* CreateInterface(const char *pName, int *pReturnCode);
+
+#if defined( _X360 )
+DLL_EXPORT void *CreateInterfaceThunk( const char *pName, int *pReturnCode );
+#endif
+
+//-----------------------------------------------------------------------------
+// UNDONE: This is obsolete, use the module load/unload/get instead!!!
+//-----------------------------------------------------------------------------
+extern CreateInterfaceFn Sys_GetFactory( CSysModule *pModule );
+extern CreateInterfaceFn Sys_GetFactory( const char *pModuleName );
+extern CreateInterfaceFn Sys_GetFactoryThis( void );
+
+//-----------------------------------------------------------------------------
+// Load & Unload should be called in exactly one place for each module
+// The factory for that module should be passed on to dependent components for
+// proper versioning.
+//-----------------------------------------------------------------------------
+extern CSysModule *Sys_LoadModule( const char *pModuleName );
+extern void Sys_UnloadModule( CSysModule *pModule );
+
+// Determines if current process is running with any debug modules
+extern bool Sys_RunningWithDebugModules();
+
+// This is a helper function to load a module, get its factory, and get a specific interface.
+// You are expected to free all of these things.
+// Returns false and cleans up if any of the steps fail.
+bool Sys_LoadInterface(
+ const char *pModuleName,
+ const char *pInterfaceVersionName,
+ CSysModule **pOutModule,
+ void **pOutInterface );
+
+bool Sys_IsDebuggerPresent();
+
+//-----------------------------------------------------------------------------
+// Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name.
+//
+// When the singleton goes out of scope (.dll unload if at module scope),
+// then it'll call Sys_UnloadModule on the module so that the refcount is decremented
+// and the .dll actually can unload from memory.
+//-----------------------------------------------------------------------------
+class CDllDemandLoader
+{
+public:
+ CDllDemandLoader( char const *pchModuleName );
+ virtual ~CDllDemandLoader();
+ CreateInterfaceFn GetFactory();
+ void Unload();
+
+private:
+
+ char const *m_pchModuleName;
+ CSysModule *m_hModule;
+ bool m_bLoadAttempted;
+};
+
+
+#endif
+
+
+
diff --git a/external/vpc/public/tier1/keyvalues.h b/external/vpc/public/tier1/keyvalues.h
new file mode 100644
index 0000000..a419dec
--- /dev/null
+++ b/external/vpc/public/tier1/keyvalues.h
@@ -0,0 +1,519 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef KEYVALUES_H
+#define KEYVALUES_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#include "utlvector.h"
+#include "color.h"
+#include "exprevaluator.h"
+
+
+#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
+ for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
+
+#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
+ for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
+
+#define FOR_EACH_VALUE( kvRoot, kvValue ) \
+ for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
+
+
+class IBaseFileSystem;
+class CUtlBuffer;
+class Color;
+class KeyValues;
+class IKeyValuesDumpContext;
+typedef void * FileHandle_t;
+class CKeyValuesGrowableStringTable;
+
+
+// single byte identifies a xbox kv file in binary format
+// strings are pooled from a searchpath/zip mounted symbol table
+#define KV_BINARY_POOLED_FORMAT 0xAA
+
+
+#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
+ for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
+
+#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
+ for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
+
+#define FOR_EACH_VALUE( kvRoot, kvValue ) \
+ for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple recursive data access class
+// Used in vgui for message parameters and resource files
+// Destructor deletes all child KeyValues nodes
+// Data is stored in key (string names) - (string/int/float)value pairs called nodes.
+//
+// About KeyValues Text File Format:
+
+// It has 3 control characters '{', '}' and '"'. Names and values may be quoted or
+// not. The quote '"' character must not be used within name or values, only for
+// quoting whole tokens. You may use escape sequences wile parsing and add within a
+// quoted token a \" to add quotes within your name or token. When using Escape
+// Sequence the parser must now that by setting KeyValues::UsesEscapeSequences( true ),
+// which it's off by default. Non-quoted tokens ends with a whitespace, '{', '}' and '"'.
+// So you may use '{' and '}' within quoted tokens, but not for non-quoted tokens.
+// An open bracket '{' after a key name indicates a list of subkeys which is finished
+// with a closing bracket '}'. Subkeys use the same definitions recursively.
+// Whitespaces are space, return, newline and tabulator. Allowed Escape sequences
+// are \n, \t, \\, \n and \". The number character '#' is used for macro purposes
+// (eg #include), don't use it as first character in key names.
+//-----------------------------------------------------------------------------
+class KeyValues
+{
+public:
+ // By default, the KeyValues class uses a string table for the key names that is
+ // limited to 4MB. The game will exit in error if this space is exhausted. In
+ // general this is preferable for game code for performance and memory fragmentation
+ // reasons.
+ //
+ // If this is not acceptable, you can use this call to switch to a table that can grow
+ // arbitrarily. This call must be made before any KeyValues objects are allocated or it
+ // will result in undefined behavior. If you use the growable string table, you cannot
+ // share KeyValues pointers directly with any other module. You can serialize them across
+ // module boundaries. These limitations are acceptable in the Steam backend code
+ // this option was written for, but may not be in other situations. Make sure to
+ // understand the implications before using this.
+ static void SetUseGrowableStringTable( bool bUseGrowableTable );
+
+ explicit KeyValues( const char *setName );
+
+ //
+ // AutoDelete class to automatically free the keyvalues.
+ // Simply construct it with the keyvalues you allocated and it will free them when falls out of scope.
+ // When you decide that keyvalues shouldn't be deleted call Assign(NULL) on it.
+ // If you constructed AutoDelete(NULL) you can later assign the keyvalues to be deleted with Assign(pKeyValues).
+ //
+ class AutoDelete
+ {
+ public:
+ explicit inline AutoDelete( KeyValues *pKeyValues ) : m_pKeyValues( pKeyValues ) {}
+ explicit inline AutoDelete( const char *pchKVName ) : m_pKeyValues( new KeyValues( pchKVName ) ) {}
+ inline ~AutoDelete( void ) { if( m_pKeyValues ) m_pKeyValues->deleteThis(); }
+ inline void Assign( KeyValues *pKeyValues ) { m_pKeyValues = pKeyValues; }
+ KeyValues *operator->() { return m_pKeyValues; }
+ operator KeyValues *() { return m_pKeyValues; }
+ private:
+ AutoDelete( AutoDelete const &x ); // forbid
+ AutoDelete & operator= ( AutoDelete const &x ); // forbid
+ protected:
+ KeyValues *m_pKeyValues;
+ };
+
+ //
+ // AutoDeleteInline is useful when you want to hold your keyvalues object inside
+ // and delete it right after using.
+ // You can also pass temporary KeyValues object as an argument to a function by wrapping it into KeyValues::AutoDeleteInline
+ // instance: call_my_function( KeyValues::AutoDeleteInline( new KeyValues( "test" ) ) )
+ //
+ class AutoDeleteInline : public AutoDelete
+ {
+ public:
+ explicit inline AutoDeleteInline( KeyValues *pKeyValues ) : AutoDelete( pKeyValues ) {}
+ inline operator KeyValues *() const { return m_pKeyValues; }
+ inline KeyValues * Get() const { return m_pKeyValues; }
+ };
+
+ // Quick setup constructors
+ KeyValues( const char *setName, const char *firstKey, const char *firstValue );
+ KeyValues( const char *setName, const char *firstKey, const wchar_t *firstValue );
+ KeyValues( const char *setName, const char *firstKey, int firstValue );
+ KeyValues( const char *setName, const char *firstKey, const char *firstValue, const char *secondKey, const char *secondValue );
+ KeyValues( const char *setName, const char *firstKey, int firstValue, const char *secondKey, int secondValue );
+
+ // Section name
+ const char *GetName() const;
+ void SetName( const char *setName);
+
+ // gets the name as a unique int
+ int GetNameSymbol() const;
+ int GetNameSymbolCaseSensitive() const;
+
+ // File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
+ void UsesEscapeSequences(bool state); // default false
+ bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL);
+ bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
+
+ // Read from a buffer... Note that the buffer must be null terminated
+ bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL );
+
+ // Read from a utlbuffer...
+ bool LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL, GetSymbolProc_t pfnEvaluateSymbolProc = NULL );
+
+ // Find a keyValue, create it if it is not found.
+ // Set bCreate to true to create the key if it doesn't already exist (which ensures a valid pointer will be returned)
+ KeyValues *FindKey(const char *keyName, bool bCreate = false);
+ KeyValues *FindKey(int keySymbol) const;
+ KeyValues *CreateNewKey(); // creates a new key, with an autogenerated name. name is guaranteed to be an integer, of value 1 higher than the highest other integer key name
+ void AddSubKey( KeyValues *pSubkey ); // Adds a subkey. Make sure the subkey isn't a child of some other keyvalues
+ void RemoveSubKey(KeyValues *subKey); // removes a subkey from the list, DOES NOT DELETE IT
+ void InsertSubKey( int nIndex, KeyValues *pSubKey ); // Inserts the given sub-key before the Nth child location
+ bool ContainsSubKey( KeyValues *pSubKey ); // Returns true if this key values contains the specified sub key, false otherwise.
+ void SwapSubKey( KeyValues *pExistingSubKey, KeyValues *pNewSubKey ); // Swaps an existing subkey for a new one, DOES NOT DELETE THE OLD ONE but takes ownership of the new one
+ void ElideSubKey( KeyValues *pSubKey ); // Removes a subkey but inserts all of its children in its place, in-order (flattens a tree, like firing a manager!)
+
+ // Key iteration.
+ //
+ // NOTE: GetFirstSubKey/GetNextKey will iterate keys AND values. Use the functions
+ // below if you want to iterate over just the keys or just the values.
+ //
+ KeyValues *GetFirstSubKey(); // returns the first subkey in the list
+ KeyValues *GetNextKey(); // returns the next subkey
+ void SetNextKey( KeyValues * pDat);
+
+ //
+ // These functions can be used to treat it like a true key/values tree instead of
+ // confusing values with keys.
+ //
+ // So if you wanted to iterate all subkeys, then all values, it would look like this:
+ // for ( KeyValues *pKey = pRoot->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() )
+ // {
+ // Msg( "Key name: %s\n", pKey->GetName() );
+ // }
+ // for ( KeyValues *pValue = pRoot->GetFirstValue(); pKey; pKey = pKey->GetNextValue() )
+ // {
+ // Msg( "Int value: %d\n", pValue->GetInt() ); // Assuming pValue->GetDataType() == TYPE_INT...
+ // }
+ KeyValues* GetFirstTrueSubKey();
+ KeyValues* GetNextTrueSubKey();
+
+ KeyValues* GetFirstValue(); // When you get a value back, you can use GetX and pass in NULL to get the value.
+ KeyValues* GetNextValue();
+
+
+ // Data access
+ int GetInt( const char *keyName = NULL, int defaultValue = 0 );
+ uint64 GetUint64( const char *keyName = NULL, uint64 defaultValue = 0 );
+ float GetFloat( const char *keyName = NULL, float defaultValue = 0.0f );
+ const char *GetString( const char *keyName = NULL, const char *defaultValue = "" );
+ const wchar_t *GetWString( const char *keyName = NULL, const wchar_t *defaultValue = L"" );
+ void *GetPtr( const char *keyName = NULL, void *defaultValue = (void*)0 );
+ Color GetColor( const char *keyName = NULL , const Color &defaultColor = Color( 0, 0, 0, 0 ) );
+ bool GetBool( const char *keyName = NULL, bool defaultValue = false ) { return GetInt( keyName, defaultValue ? 1 : 0 ) ? true : false; }
+ bool IsEmpty(const char *keyName = NULL);
+
+ // Data access
+ int GetInt( int keySymbol, int defaultValue = 0 );
+ uint64 GetUint64( int keySymbol, uint64 defaultValue = 0 );
+ float GetFloat( int keySymbol, float defaultValue = 0.0f );
+ const char *GetString( int keySymbol, const char *defaultValue = "" );
+ const wchar_t *GetWString( int keySymbol, const wchar_t *defaultValue = L"" );
+ void *GetPtr( int keySymbol, void *defaultValue = (void*)0 );
+ Color GetColor( int keySymbol /* default value is all black */);
+ bool GetBool( int keySymbol, bool defaultValue = false ) { return GetInt( keySymbol, defaultValue ? 1 : 0 ) ? true : false; }
+ bool IsEmpty( int keySymbol );
+
+ // Key writing
+ void SetWString( const char *keyName, const wchar_t *value );
+ void SetString( const char *keyName, const char *value );
+ void SetInt( const char *keyName, int value );
+ void SetUint64( const char *keyName, uint64 value );
+ void SetFloat( const char *keyName, float value );
+ void SetPtr( const char *keyName, void *value );
+ void SetColor( const char *keyName, Color value);
+ void SetBool( const char *keyName, bool value ) { SetInt( keyName, value ? 1 : 0 ); }
+
+ // Memory allocation (optimized)
+ void *operator new( size_t iAllocSize );
+ void *operator new( size_t iAllocSize, int nBlockUse, const char *pFileName, int nLine );
+ void operator delete( void *pMem );
+ void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine );
+
+ KeyValues& operator=( KeyValues& src );
+
+ // Adds a chain... if we don't find stuff in this keyvalue, we'll look
+ // in the one we're chained to.
+ void ChainKeyValue( KeyValues* pChain );
+
+ void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel );
+
+ bool WriteAsBinary( CUtlBuffer &buffer ) const;
+ bool ReadAsBinary( CUtlBuffer &buffer );
+
+ // Allocate & create a new copy of the keys
+ KeyValues *MakeCopy( void ) const;
+
+ // Make a new copy of all subkeys, add them all to the passed-in keyvalues
+ void CopySubkeys( KeyValues *pParent ) const;
+
+ // Clear out all subkeys, and the current value
+ void Clear( void );
+
+ // Data type
+ enum types_t
+ {
+ TYPE_NONE = 0,
+ TYPE_STRING,
+ TYPE_INT,
+ TYPE_FLOAT,
+ TYPE_PTR,
+ TYPE_WSTRING,
+ TYPE_COLOR,
+ TYPE_UINT64,
+ TYPE_COMPILED_INT_BYTE, // hack to collapse 1 byte ints in the compiled format
+ TYPE_COMPILED_INT_0, // hack to collapse 0 in the compiled format
+ TYPE_COMPILED_INT_1, // hack to collapse 1 in the compiled format
+ TYPE_NUMTYPES,
+ };
+ types_t GetDataType(const char *keyName = NULL);
+
+ // Virtual deletion function - ensures that KeyValues object is deleted from correct heap
+ void deleteThis();
+
+ void SetStringValue( char const *strValue );
+
+ // unpack a key values list into a structure
+ void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest );
+
+ // Process conditional keys for widescreen support.
+ bool ProcessResolutionKeys( const char *pResString );
+
+ // Dump keyvalues recursively into a dump context
+ bool Dump( IKeyValuesDumpContext *pDump, int nIndentLevel = 0 );
+
+ // Merge operations describing how two keyvalues can be combined
+ enum MergeKeyValuesOp_t
+ {
+ MERGE_KV_ALL,
+ MERGE_KV_UPDATE, // update values are copied into storage, adding new keys to storage or updating existing ones
+ MERGE_KV_DELETE, // update values specify keys that get deleted from storage
+ MERGE_KV_BORROW, // update values only update existing keys in storage, keys in update that do not exist in storage are discarded
+ };
+ void MergeFrom( KeyValues *kvMerge, MergeKeyValuesOp_t eOp = MERGE_KV_ALL );
+
+ // Assign keyvalues from a string
+ static KeyValues * FromString( char const *szName, char const *szStringVal, char const **ppEndOfParse = NULL );
+
+protected:
+ KeyValues( KeyValues& ); // prevent copy constructor being used
+
+ // prevent delete being called except through deleteThis()
+ ~KeyValues();
+
+ KeyValues* CreateKey( const char *keyName );
+
+ void RecursiveCopyKeyValues( KeyValues& src );
+ void RemoveEverything();
+// void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel );
+// void WriteConvertedString( CUtlBuffer &buffer, const char *pszString );
+
+ // NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
+ // If filesystem is null, it'll ignore f.
+ void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
+ void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
+
+ void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf, GetSymbolProc_t pfnEvaluateSymbolProc );
+
+ // for handling #include "filename"
+ void AppendIncludedKeys( CUtlVector< KeyValues * >& includedKeys );
+ void ParseIncludedKeys( char const *resourceName, const char *filetoinclude,
+ IBaseFileSystem* pFileSystem, const char *pPathID, CUtlVector< KeyValues * >& includedKeys, GetSymbolProc_t pfnEvaluateSymbolProc );
+
+ // For handling #base "filename"
+ void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys );
+ void RecursiveMergeKeyValues( KeyValues *baseKV );
+
+ // NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
+ // If filesystem is null, it'll ignore f.
+ void InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len );
+
+ void Init();
+ const char * ReadToken( CUtlBuffer &buf, bool &wasQuoted, bool &wasConditional );
+ void WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
+
+ void FreeAllocatedValue();
+ void AllocateValueBlock(int size);
+
+ bool ReadAsBinaryPooledFormat( CUtlBuffer &buf, IBaseFileSystem *pFileSystem, unsigned int poolKey, GetSymbolProc_t pfnEvaluateSymbolProc );
+
+ bool EvaluateConditional( const char *pExpressionString, GetSymbolProc_t pfnEvaluateSymbolProc );
+
+ uint32 m_iKeyName : 24; // keyname is a symbol defined in KeyValuesSystem
+ uint32 m_iKeyNameCaseSensitive1 : 8; // 1st part of case sensitive symbol defined in KeyValueSystem
+
+ // These are needed out of the union because the API returns string pointers
+ char *m_sValue;
+ wchar_t *m_wsValue;
+
+ // we don't delete these
+ union
+ {
+ int m_iValue;
+ float m_flValue;
+ void *m_pValue;
+ unsigned char m_Color[4];
+ };
+
+ char m_iDataType;
+ char m_bHasEscapeSequences; // true, if while parsing this KeyValue, Escape Sequences are used (default false)
+ uint16 m_iKeyNameCaseSensitive2; // 2nd part of case sensitive symbol defined in KeyValueSystem;
+
+ KeyValues *m_pPeer; // pointer to next key in list
+ KeyValues *m_pSub; // pointer to Start of a new sub key list
+ KeyValues *m_pChain;// Search here if it's not in our list
+
+ GetSymbolProc_t m_pExpressionGetSymbolProc;
+
+private:
+ // Statics to implement the optional growable string table
+ // Function pointers that will determine which mode we are in
+ static int (*s_pfGetSymbolForString)( const char *name, bool bCreate );
+ static const char *(*s_pfGetStringForSymbol)( int symbol );
+ static CKeyValuesGrowableStringTable *s_pGrowableStringTable;
+
+public:
+ // Functions that invoke the default behavior
+ static int GetSymbolForStringClassic( const char *name, bool bCreate = true );
+ static const char *GetStringForSymbolClassic( int symbol );
+
+ // Functions that use the growable string table
+ static int GetSymbolForStringGrowable( const char *name, bool bCreate = true );
+ static const char *GetStringForSymbolGrowable( int symbol );
+};
+
+typedef KeyValues::AutoDelete KeyValuesAD;
+
+enum KeyValuesUnpackDestinationTypes_t
+{
+ UNPACK_TYPE_FLOAT, // dest is a float
+ UNPACK_TYPE_VECTOR, // dest is a Vector
+ UNPACK_TYPE_VECTOR_COLOR, // dest is a vector, src is a color
+ UNPACK_TYPE_STRING, // dest is a char *. unpacker will allocate.
+ UNPACK_TYPE_INT, // dest is an int
+ UNPACK_TYPE_FOUR_FLOATS, // dest is an array of 4 floats. source is a string like "1 2 3 4"
+ UNPACK_TYPE_TWO_FLOATS, // dest is an array of 2 floats. source is a string like "1 2"
+};
+
+#define UNPACK_FIXED( kname, kdefault, dtype, ofs ) { kname, kdefault, dtype, ofs, 0 }
+#define UNPACK_VARIABLE( kname, kdefault, dtype, ofs, sz ) { kname, kdefault, dtype, ofs, sz }
+#define UNPACK_END_MARKER { NULL, NULL, UNPACK_TYPE_FLOAT, 0 }
+
+struct KeyValuesUnpackStructure
+{
+ char const *m_pKeyName; // null to terminate tbl
+ char const *m_pKeyDefault; // null ok
+ KeyValuesUnpackDestinationTypes_t m_eDataType; // UNPACK_TYPE_INT, ..
+ size_t m_nFieldOffset; // use offsetof to set
+ size_t m_nFieldSize; // for strings or other variable length
+};
+
+//-----------------------------------------------------------------------------
+// inline methods
+//-----------------------------------------------------------------------------
+inline int KeyValues::GetInt( int keySymbol, int defaultValue )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetInt( (const char *)NULL, defaultValue ) : defaultValue;
+}
+
+inline uint64 KeyValues::GetUint64( int keySymbol, uint64 defaultValue )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetUint64( (const char *)NULL, defaultValue ) : defaultValue;
+}
+
+inline float KeyValues::GetFloat( int keySymbol, float defaultValue )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetFloat( (const char *)NULL, defaultValue ) : defaultValue;
+}
+
+inline const char *KeyValues::GetString( int keySymbol, const char *defaultValue )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetString( (const char *)NULL, defaultValue ) : defaultValue;
+}
+
+inline const wchar_t *KeyValues::GetWString( int keySymbol, const wchar_t *defaultValue )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetWString( (const char *)NULL, defaultValue ) : defaultValue;
+}
+
+inline void *KeyValues::GetPtr( int keySymbol, void *defaultValue )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetPtr( (const char *)NULL, defaultValue ) : defaultValue;
+}
+
+inline Color KeyValues::GetColor( int keySymbol )
+{
+ Color defaultValue( 0, 0, 0, 0 );
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->GetColor( ) : defaultValue;
+}
+
+inline bool KeyValues::IsEmpty( int keySymbol )
+{
+ KeyValues *dat = FindKey( keySymbol );
+ return dat ? dat->IsEmpty( ) : true;
+}
+
+
+//
+// KeyValuesDumpContext and generic implementations
+//
+
+class IKeyValuesDumpContext
+{
+public:
+ virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel ) = 0;
+ virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel ) = 0;
+ virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel ) = 0;
+};
+
+class IKeyValuesDumpContextAsText : public IKeyValuesDumpContext
+{
+public:
+ virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
+ virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel );
+ virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel );
+
+public:
+ virtual bool KvWriteIndent( int nIndentLevel );
+ virtual bool KvWriteText( char const *szText ) = 0;
+};
+
+class CKeyValuesDumpContextAsDevMsg : public IKeyValuesDumpContextAsText
+{
+public:
+ // Overrides developer level to dump in DevMsg, zero to dump as Msg
+ CKeyValuesDumpContextAsDevMsg( int nDeveloperLevel = 1 ) : m_nDeveloperLevel( nDeveloperLevel ) {}
+
+public:
+ virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
+ virtual bool KvWriteText( char const *szText );
+
+protected:
+ int m_nDeveloperLevel;
+};
+
+inline bool KeyValuesDumpAsDevMsg( KeyValues *pKeyValues, int nIndentLevel = 0, int nDeveloperLevel = 1 )
+{
+ CKeyValuesDumpContextAsDevMsg ctx( nDeveloperLevel );
+ return pKeyValues->Dump( &ctx, nIndentLevel );
+}
+
+
+#endif // KEYVALUES_H
diff --git a/external/vpc/public/tier1/mempool.h b/external/vpc/public/tier1/mempool.h
new file mode 100644
index 0000000..67da207
--- /dev/null
+++ b/external/vpc/public/tier1/mempool.h
@@ -0,0 +1,649 @@
+//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef MEMPOOL_H
+#define MEMPOOL_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/memalloc.h"
+#include "tier0/tslist.h"
+#include "tier0/platform.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlrbtree.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Optimized pool memory allocator
+//-----------------------------------------------------------------------------
+
+typedef void (*MemoryPoolReportFunc_t)( char const* pMsg, ... );
+
+class CUtlMemoryPool
+{
+public:
+ // Ways the memory pool can grow when it needs to make a new blob.
+ enum MemoryPoolGrowType_t
+ {
+ GROW_NONE=0, // Don't allow new blobs.
+ GROW_FAST=1, // New blob size is numElements * (i+1) (ie: the blocks it allocates
+ // get larger and larger each time it allocates one).
+ GROW_SLOW=2 // New blob size is numElements.
+ };
+
+ CUtlMemoryPool( int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL, int nAlignment = 0 );
+ ~CUtlMemoryPool();
+
+ void* Alloc(); // Allocate the element size you specified in the constructor.
+ void* Alloc( size_t amount );
+ void* AllocZero(); // Allocate the element size you specified in the constructor, zero the memory before construction
+ void* AllocZero( size_t amount );
+ void Free(void *pMem);
+
+ // Frees everything
+ void Clear();
+
+ // Error reporting...
+ static void SetErrorReportFunc( MemoryPoolReportFunc_t func );
+
+ // returns number of allocated blocks
+ int Count() const { return m_BlocksAllocated; }
+ int PeakCount() const { return m_PeakAlloc; }
+ int BlockSize() const { return m_BlockSize; }
+ int Size() const { return m_NumBlobs * m_BlocksPerBlob * m_BlockSize; }
+
+ bool IsAllocationWithinPool( void *pMem ) const;
+
+protected:
+ class CBlob
+ {
+ public:
+ CBlob *m_pPrev, *m_pNext;
+ int m_NumBytes; // Number of bytes in this blob.
+ char m_Data[1];
+ char m_Padding[3]; // to int align the struct
+ };
+
+ // Resets the pool
+ void Init();
+ void AddNewBlob();
+ void ReportLeaks();
+
+ int m_BlockSize;
+ int m_BlocksPerBlob;
+
+ int m_GrowMode; // GROW_ enum.
+
+ // FIXME: Change m_ppMemBlob into a growable array?
+ void *m_pHeadOfFreeList;
+ int m_BlocksAllocated;
+ int m_PeakAlloc;
+ unsigned short m_nAlignment;
+ unsigned short m_NumBlobs;
+ const char * m_pszAllocOwner;
+ // CBlob could be not a multiple of 4 bytes so stuff it at the end here to keep us otherwise aligned
+ CBlob m_BlobHead;
+
+ static MemoryPoolReportFunc_t g_ReportFunc;
+};
+
+
+//-----------------------------------------------------------------------------
+// Multi-thread/Thread Safe Memory Class
+//-----------------------------------------------------------------------------
+class CMemoryPoolMT : public CUtlMemoryPool
+{
+public:
+ CMemoryPoolMT( int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL, int nAlignment = 0) : CUtlMemoryPool( blockSize, numElements, growMode, pszAllocOwner, nAlignment ) {}
+
+
+ void* Alloc() { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::Alloc(); }
+ void* Alloc( size_t amount ) { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::Alloc( amount ); }
+ void* AllocZero() { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::AllocZero(); }
+ void* AllocZero( size_t amount ) { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::AllocZero( amount ); }
+ void Free(void *pMem) { AUTO_LOCK( m_mutex ); CUtlMemoryPool::Free( pMem ); }
+
+ // Frees everything
+ void Clear() { AUTO_LOCK( m_mutex ); return CUtlMemoryPool::Clear(); }
+private:
+ CThreadFastMutex m_mutex; // @TODO: Rework to use tslist (toml 7/6/2007)
+};
+
+
+//-----------------------------------------------------------------------------
+// Wrapper macro to make an allocator that returns particular typed allocations
+// and construction and destruction of objects.
+//-----------------------------------------------------------------------------
+template< class T >
+class CClassMemoryPool : public CUtlMemoryPool
+{
+public:
+ CClassMemoryPool(int numElements, int growMode = GROW_FAST, int nAlignment = 0 ) :
+ CUtlMemoryPool( sizeof(T), numElements, growMode, MEM_ALLOC_CLASSNAME(T), nAlignment ) {}
+
+ T* Alloc();
+ T* AllocZero();
+ void Free( T *pMem );
+
+ void Clear();
+};
+
+//-----------------------------------------------------------------------------
+// Specialized pool for aligned data management (e.g., Xbox textures)
+//-----------------------------------------------------------------------------
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE = false, int COMPACT_THRESHOLD = 4 >
+class CAlignedMemPool
+{
+ enum
+ {
+ BLOCK_SIZE = COMPILETIME_MAX( ALIGN_VALUE( ITEM_SIZE, ALIGNMENT ), 8 ),
+ };
+
+public:
+ CAlignedMemPool();
+
+ void *Alloc();
+ void Free( void *p );
+
+ static int __cdecl CompareChunk( void * const *ppLeft, void * const *ppRight );
+ void Compact();
+
+ int NumTotal() { AUTO_LOCK( m_mutex ); return m_Chunks.Count() * ( CHUNK_SIZE / BLOCK_SIZE ); }
+ int NumAllocated() { AUTO_LOCK( m_mutex ); return NumTotal() - m_nFree; }
+ int NumFree() { AUTO_LOCK( m_mutex ); return m_nFree; }
+
+ int BytesTotal() { AUTO_LOCK( m_mutex ); return NumTotal() * BLOCK_SIZE; }
+ int BytesAllocated() { AUTO_LOCK( m_mutex ); return NumAllocated() * BLOCK_SIZE; }
+ int BytesFree() { AUTO_LOCK( m_mutex ); return NumFree() * BLOCK_SIZE; }
+
+ int ItemSize() { return ITEM_SIZE; }
+ int BlockSize() { return BLOCK_SIZE; }
+ int ChunkSize() { return CHUNK_SIZE; }
+
+private:
+ struct FreeBlock_t
+ {
+ FreeBlock_t *pNext;
+ byte reserved[ BLOCK_SIZE - sizeof( FreeBlock_t *) ];
+ };
+
+ CUtlVector<void *> m_Chunks; // Chunks are tracked outside blocks (unlike CUtlMemoryPool) to simplify alignment issues
+ FreeBlock_t * m_pFirstFree;
+ int m_nFree;
+ CAllocator m_Allocator;
+ double m_TimeLastCompact;
+
+ CThreadFastMutex m_mutex;
+};
+
+//-----------------------------------------------------------------------------
+// Pool variant using standard allocation
+//-----------------------------------------------------------------------------
+template <typename T, int nInitialCount = 0, bool bDefCreateNewIfEmpty = true >
+class CObjectPool
+{
+public:
+ CObjectPool()
+ {
+ int i = nInitialCount;
+ while ( i-- > 0 )
+ {
+ m_AvailableObjects.PushItem( new T );
+ }
+ }
+
+ ~CObjectPool()
+ {
+ Purge();
+ }
+
+ int NumAvailable()
+ {
+ return m_AvailableObjects.Count();
+ }
+
+ void Purge()
+ {
+ T *p = NULL;
+ while ( m_AvailableObjects.PopItem( &p ) )
+ {
+ delete p;
+ }
+ }
+
+ T *GetObject( bool bCreateNewIfEmpty = bDefCreateNewIfEmpty )
+ {
+ T *p = NULL;
+ if ( !m_AvailableObjects.PopItem( &p ) )
+ {
+ p = ( bCreateNewIfEmpty ) ? new T : NULL;
+ }
+ return p;
+ }
+
+ void PutObject( T *p )
+ {
+ m_AvailableObjects.PushItem( p );
+ }
+
+private:
+ CTSList<T *> m_AvailableObjects;
+};
+
+//-----------------------------------------------------------------------------
+// Fixed budget pool with overflow to malloc
+//-----------------------------------------------------------------------------
+template <size_t PROVIDED_ITEM_SIZE, int ITEM_COUNT>
+class CFixedBudgetMemoryPool
+{
+public:
+ CFixedBudgetMemoryPool()
+ {
+ m_pBase = m_pLimit = 0;
+ COMPILE_TIME_ASSERT( ITEM_SIZE % 4 == 0 );
+ }
+
+ bool Owns( void *p )
+ {
+ return ( p >= m_pBase && p < m_pLimit );
+ }
+
+ void *Alloc()
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+#ifndef USE_MEM_DEBUG
+ if ( !m_pBase )
+ {
+ LOCAL_THREAD_LOCK();
+ if ( !m_pBase )
+ {
+ byte *pMemory = m_pBase = (byte *)malloc( ITEM_COUNT * ITEM_SIZE );
+ m_pLimit = m_pBase + ( ITEM_COUNT * ITEM_SIZE );
+
+ for ( int i = 0; i < ITEM_COUNT; i++ )
+ {
+ m_freeList.Push( (TSLNodeBase_t *)pMemory );
+ pMemory += ITEM_SIZE;
+ }
+ }
+ }
+
+ void *p = m_freeList.Pop();
+ if ( p )
+ return p;
+#endif
+ return malloc( ITEM_SIZE );
+ }
+
+ void Free( void *p )
+ {
+#ifndef USE_MEM_DEBUG
+ if ( Owns( p ) )
+ m_freeList.Push( (TSLNodeBase_t *)p );
+ else
+#endif
+ free( p );
+ }
+
+ void Clear()
+ {
+#ifndef USE_MEM_DEBUG
+ if ( m_pBase )
+ {
+ free( m_pBase );
+ }
+ m_pBase = m_pLimit = 0;
+ Construct( &m_freeList );
+#endif
+ }
+
+ bool IsEmpty()
+ {
+#ifndef USE_MEM_DEBUG
+ if ( m_pBase && m_freeList.Count() != ITEM_COUNT )
+ return false;
+#endif
+ return true;
+ }
+
+ enum
+ {
+ ITEM_SIZE = ALIGN_VALUE( PROVIDED_ITEM_SIZE, TSLIST_NODE_ALIGNMENT )
+ };
+
+ CTSListBase m_freeList;
+ byte *m_pBase;
+ byte *m_pLimit;
+};
+
+#define BIND_TO_FIXED_BUDGET_POOL( poolName ) \
+ inline void* operator new( size_t size ) { return poolName.Alloc(); } \
+ inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { return poolName.Alloc(); } \
+ inline void operator delete( void* p ) { poolName.Free(p); } \
+ inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { poolName.Free(p); }
+
+//-----------------------------------------------------------------------------
+
+
+template< class T >
+inline T* CClassMemoryPool<T>::Alloc()
+{
+ T *pRet;
+
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ pRet = (T*)CUtlMemoryPool::Alloc();
+ }
+
+ if ( pRet )
+ {
+ Construct( pRet );
+ }
+ return pRet;
+}
+
+template< class T >
+inline T* CClassMemoryPool<T>::AllocZero()
+{
+ T *pRet;
+
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ pRet = (T*)CUtlMemoryPool::AllocZero();
+ }
+
+ if ( pRet )
+ {
+ Construct( pRet );
+ }
+ return pRet;
+}
+
+template< class T >
+inline void CClassMemoryPool<T>::Free(T *pMem)
+{
+ if ( pMem )
+ {
+ Destruct( pMem );
+ }
+
+ CUtlMemoryPool::Free( pMem );
+}
+
+template< class T >
+inline void CClassMemoryPool<T>::Clear()
+{
+ CUtlRBTree<void *> freeBlocks;
+ SetDefLessFunc( freeBlocks );
+
+ void *pCurFree = m_pHeadOfFreeList;
+ while ( pCurFree != NULL )
+ {
+ freeBlocks.Insert( pCurFree );
+ pCurFree = *((void**)pCurFree);
+ }
+
+ for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
+ {
+ T *p = (T *)pCur->m_Data;
+ T *pLimit = (T *)(pCur->m_Data + pCur->m_NumBytes);
+ while ( p < pLimit )
+ {
+ if ( freeBlocks.Find( p ) == freeBlocks.InvalidIndex() )
+ {
+ Destruct( p );
+ }
+ p++;
+ }
+ }
+
+ CUtlMemoryPool::Clear();
+}
+
+
+//-----------------------------------------------------------------------------
+// Macros that make it simple to make a class use a fixed-size allocator
+// Put DECLARE_FIXEDSIZE_ALLOCATOR in the private section of a class,
+// Put DEFINE_FIXEDSIZE_ALLOCATOR in the CPP file
+//-----------------------------------------------------------------------------
+#define DECLARE_FIXEDSIZE_ALLOCATOR( _class ) \
+ public: \
+ inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
+ inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
+ inline void operator delete( void* p ) { s_Allocator.Free(p); } \
+ inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \
+ private: \
+ static CUtlMemoryPool s_Allocator
+
+#define DEFINE_FIXEDSIZE_ALLOCATOR( _class, _initsize, _grow ) \
+ CUtlMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool")
+
+#define DEFINE_FIXEDSIZE_ALLOCATOR_ALIGNED( _class, _initsize, _grow, _alignment ) \
+ CUtlMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool", _alignment )
+
+#define DECLARE_FIXEDSIZE_ALLOCATOR_MT( _class ) \
+ public: \
+ inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
+ inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \
+ inline void operator delete( void* p ) { s_Allocator.Free(p); } \
+ inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \
+ private: \
+ static CMemoryPoolMT s_Allocator
+
+#define DEFINE_FIXEDSIZE_ALLOCATOR_MT( _class, _initsize, _grow ) \
+ CMemoryPoolMT _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool")
+
+//-----------------------------------------------------------------------------
+// Macros that make it simple to make a class use a fixed-size allocator
+// This version allows us to use a memory pool which is externally defined...
+// Put DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL in the private section of a class,
+// Put DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL in the CPP file
+//-----------------------------------------------------------------------------
+
+#define DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class ) \
+ public: \
+ inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \
+ inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \
+ inline void operator delete( void* p ) { s_pAllocator->Free(p); } \
+ private: \
+ static CUtlMemoryPool* s_pAllocator
+
+#define DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class, _allocator ) \
+ CUtlMemoryPool* _class::s_pAllocator = _allocator
+
+
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
+inline CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::CAlignedMemPool()
+ : m_pFirstFree( 0 ),
+ m_nFree( 0 ),
+ m_TimeLastCompact( 0 )
+{
+ COMPILE_TIME_ASSERT( sizeof( FreeBlock_t ) >= BLOCK_SIZE );
+ COMPILE_TIME_ASSERT( ALIGN_VALUE( sizeof( FreeBlock_t ), ALIGNMENT ) == sizeof( FreeBlock_t ) );
+}
+
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
+inline void *CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::Alloc()
+{
+ AUTO_LOCK( m_mutex );
+
+ if ( !m_pFirstFree )
+ {
+ if ( !GROWMODE && m_Chunks.Count() )
+ {
+ return NULL;
+ }
+
+ FreeBlock_t *pNew = (FreeBlock_t *)m_Allocator.Alloc( CHUNK_SIZE );
+ Assert( (unsigned)pNew % ALIGNMENT == 0 );
+ m_Chunks.AddToTail( pNew );
+ m_nFree = CHUNK_SIZE / BLOCK_SIZE;
+ m_pFirstFree = pNew;
+ for ( int i = 0; i < m_nFree - 1; i++ )
+ {
+ pNew->pNext = pNew + 1;
+ pNew++;
+ }
+ pNew->pNext = NULL;
+ }
+
+ void *p = m_pFirstFree;
+ m_pFirstFree = m_pFirstFree->pNext;
+ m_nFree--;
+
+ return p;
+}
+
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
+inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::Free( void *p )
+{
+ AUTO_LOCK( m_mutex );
+
+ // Insertion sort to encourage allocation clusters in chunks
+ FreeBlock_t *pFree = ((FreeBlock_t *)p);
+ FreeBlock_t *pCur = m_pFirstFree;
+ FreeBlock_t *pPrev = NULL;
+
+ while ( pCur && pFree > pCur )
+ {
+ pPrev = pCur;
+ pCur = pCur->pNext;
+ }
+
+ pFree->pNext = pCur;
+
+ if ( pPrev )
+ {
+ pPrev->pNext = pFree;
+ }
+ else
+ {
+ m_pFirstFree = pFree;
+ }
+ m_nFree++;
+
+ if ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD )
+ {
+ double time = Plat_FloatTime();
+ double compactTime = ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD * 4 ) ? 15.0 : 30.0;
+ if ( m_TimeLastCompact > time || m_TimeLastCompact + compactTime < time )
+ {
+ Compact();
+ m_TimeLastCompact = time;
+ }
+ }
+}
+
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
+inline int __cdecl CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::CompareChunk( void * const *ppLeft, void * const *ppRight )
+{
+ return ((unsigned)*ppLeft) - ((unsigned)*ppRight);
+}
+
+template <int ITEM_SIZE, int ALIGNMENT, int CHUNK_SIZE, class CAllocator, bool GROWMODE, int COMPACT_THRESHOLD >
+inline void CAlignedMemPool<ITEM_SIZE, ALIGNMENT, CHUNK_SIZE, CAllocator, GROWMODE, COMPACT_THRESHOLD>::Compact()
+{
+ FreeBlock_t *pCur = m_pFirstFree;
+ FreeBlock_t *pPrev = NULL;
+
+ m_Chunks.Sort( CompareChunk );
+
+#ifdef VALIDATE_ALIGNED_MEM_POOL
+ {
+ FreeBlock_t *p = m_pFirstFree;
+ while ( p )
+ {
+ if ( p->pNext && p > p->pNext )
+ {
+ __asm { int 3 }
+ }
+ p = p->pNext;
+ }
+
+ for ( int i = 0; i < m_Chunks.Count(); i++ )
+ {
+ if ( i + 1 < m_Chunks.Count() )
+ {
+ if ( m_Chunks[i] > m_Chunks[i + 1] )
+ {
+ __asm { int 3 }
+ }
+ }
+ }
+ }
+#endif
+
+ int i;
+
+ for ( i = 0; i < m_Chunks.Count(); i++ )
+ {
+ int nBlocksPerChunk = CHUNK_SIZE / BLOCK_SIZE;
+ FreeBlock_t *pChunkLimit = ((FreeBlock_t *)m_Chunks[i]) + nBlocksPerChunk;
+ int nFromChunk = 0;
+ if ( pCur == m_Chunks[i] )
+ {
+ FreeBlock_t *pFirst = pCur;
+ while ( pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit )
+ {
+ pCur = pCur->pNext;
+ nFromChunk++;
+ }
+ pCur = pFirst;
+
+ }
+
+ while ( pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit )
+ {
+ if ( nFromChunk != nBlocksPerChunk )
+ {
+ if ( pPrev )
+ {
+ pPrev->pNext = pCur;
+ }
+ else
+ {
+ m_pFirstFree = pCur;
+ }
+ pPrev = pCur;
+ }
+ else if ( pPrev )
+ {
+ pPrev->pNext = NULL;
+ }
+ else
+ {
+ m_pFirstFree = NULL;
+ }
+
+ pCur = pCur->pNext;
+ }
+
+ if ( nFromChunk == nBlocksPerChunk )
+ {
+ m_Allocator.Free( m_Chunks[i] );
+ m_nFree -= nBlocksPerChunk;
+ m_Chunks[i] = 0;
+ }
+ }
+
+ for ( i = m_Chunks.Count() - 1; i >= 0 ; i-- )
+ {
+ if ( !m_Chunks[i] )
+ {
+ m_Chunks.FastRemove( i );
+ }
+ }
+}
+
+#endif // MEMPOOL_H
diff --git a/external/vpc/public/tier1/memstack.h b/external/vpc/public/tier1/memstack.h
new file mode 100644
index 0000000..f1846d2
--- /dev/null
+++ b/external/vpc/public/tier1/memstack.h
@@ -0,0 +1,348 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: A fast stack memory allocator that uses virtual memory if available
+//
+//===========================================================================//
+
+#ifndef MEMSTACK_H
+#define MEMSTACK_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "tier1/utlvector.h"
+
+#if defined( _WIN32 ) || defined( _PS3 )
+#define MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
+#endif
+
+//-----------------------------------------------------------------------------
+
+typedef unsigned MemoryStackMark_t;
+
+class CMemoryStack
+{
+public:
+ CMemoryStack();
+ ~CMemoryStack();
+
+ bool Init( const char *pszAllocOwner, unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 );
+#ifdef _GAMECONSOLE
+ bool InitPhysical( const char *pszAllocOwner, uint size, uint nBaseAddrAlignment, uint alignment = 16, uint32 nAdditionalFlags = 0 );
+#endif
+ void Term();
+
+ int GetSize();
+ int GetMaxSize();
+ int GetUsed();
+
+ void *Alloc( unsigned bytes, bool bClear = false ) RESTRICT;
+
+ MemoryStackMark_t GetCurrentAllocPoint();
+ void FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit = true );
+ void FreeAll( bool bDecommit = true );
+
+ void Access( void **ppRegion, unsigned *pBytes );
+
+ void PrintContents();
+
+ void *GetBase();
+ const void *GetBase() const { return const_cast<CMemoryStack *>(this)->GetBase(); }
+
+ bool CommitSize( int );
+
+ void SetAllocOwner( const char *pszAllocOwner );
+
+private:
+ bool CommitTo( byte * ) RESTRICT;
+ void RegisterAllocation();
+ void RegisterDeallocation( bool bShouldSpew );
+
+ byte *m_pNextAlloc;
+ byte *m_pCommitLimit;
+ byte *m_pAllocLimit;
+
+ byte *m_pBase;
+ bool m_bRegisteredAllocation;
+ bool m_bPhysical;
+ char *m_pszAllocOwner;
+
+ unsigned m_maxSize;
+ unsigned m_alignment;
+#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE
+ unsigned m_commitSize;
+ unsigned m_minCommit;
+#endif
+#if defined( MEMSTACK_VIRTUAL_MEMORY_AVAILABLE ) && defined( _PS3 )
+ IVirtualMemorySection *m_pVirtualMemorySection;
+#endif
+};
+
+//-------------------------------------
+
+FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT
+{
+ Assert( m_pBase );
+
+ bytes = MAX( bytes, m_alignment );
+ bytes = AlignValue( bytes, m_alignment );
+
+ void *pResult = m_pNextAlloc;
+ byte *pNextAlloc = m_pNextAlloc + bytes;
+
+ if ( pNextAlloc > m_pCommitLimit )
+ {
+ if ( !CommitTo( pNextAlloc ) )
+ {
+ return NULL;
+ }
+ }
+
+ if ( bClear )
+ {
+ memset( pResult, 0, bytes );
+ }
+
+ m_pNextAlloc = pNextAlloc;
+
+ return pResult;
+}
+
+//-------------------------------------
+
+inline bool CMemoryStack::CommitSize( int nBytes )
+{
+ if ( GetSize() != nBytes )
+ {
+ return CommitTo( m_pBase + nBytes );
+ }
+ return true;
+}
+
+//-------------------------------------
+
+inline int CMemoryStack::GetMaxSize()
+{
+ return m_maxSize;
+}
+
+//-------------------------------------
+
+inline int CMemoryStack::GetUsed()
+{
+ return ( m_pNextAlloc - m_pBase );
+}
+
+//-------------------------------------
+
+inline void *CMemoryStack::GetBase()
+{
+ return m_pBase;
+}
+
+//-------------------------------------
+
+inline MemoryStackMark_t CMemoryStack::GetCurrentAllocPoint()
+{
+ return ( m_pNextAlloc - m_pBase );
+}
+
+
+//-----------------------------------------------------------------------------
+// The CUtlMemoryStack class:
+// A fixed memory class
+//-----------------------------------------------------------------------------
+template< typename T, typename I, size_t MAX_SIZE, size_t COMMIT_SIZE = 0, size_t INITIAL_COMMIT = 0 >
+class CUtlMemoryStack
+{
+public:
+ // constructor, destructor
+ CUtlMemoryStack( int nGrowSize = 0, int nInitSize = 0 ) { m_MemoryStack.Init( "CUtlMemoryStack", MAX_SIZE * sizeof(T), COMMIT_SIZE * sizeof(T), INITIAL_COMMIT * sizeof(T), 4 ); COMPILE_TIME_ASSERT( sizeof(T) % 4 == 0 ); }
+ CUtlMemoryStack( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Can we use this index?
+ bool IsIdxValid( I i ) const { long x=i; return (x >= 0) && (x < m_nAllocated); }
+
+ // Specify the invalid ('null') index that we'll only return on failure
+ static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT
+ static I InvalidIndex() { return INVALID_INDEX; }
+
+ class Iterator_t
+ {
+ Iterator_t( I i ) : index( i ) {}
+ I index;
+ friend class CUtlMemoryStack<T,I,MAX_SIZE, COMMIT_SIZE, INITIAL_COMMIT>;
+ public:
+ bool operator==( const Iterator_t it ) const { return index == it.index; }
+ bool operator!=( const Iterator_t it ) const { return index != it.index; }
+ };
+ Iterator_t First() const { return Iterator_t( m_nAllocated ? 0 : InvalidIndex() ); }
+ Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( it.index < m_nAllocated ? it.index + 1 : InvalidIndex() ); }
+ I GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
+ bool IsValidIterator( const Iterator_t &it ) const { long x=it.index; return x >= 0 && x < m_nAllocated; }
+ Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
+
+ // Gets the base address
+ T* Base() { return (T*)m_MemoryStack.GetBase(); }
+ const T* Base() const { return (const T*)m_MemoryStack.GetBase(); }
+
+ // element access
+ T& operator[]( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& operator[]( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+ T& Element( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& Element( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Size
+ int NumAllocated() const { return m_nAllocated; }
+ int Count() const { return m_nAllocated; }
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 ) { Assert( num > 0 ); m_nAllocated += num; m_MemoryStack.Alloc( num * sizeof(T) ); }
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num ) { Assert( num <= MAX_SIZE ); if ( m_nAllocated < num ) Grow( num - m_nAllocated ); }
+
+ // Memory deallocation
+ void Purge() { m_MemoryStack.FreeAll(); m_nAllocated = 0; }
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const { return false; }
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size ) { Assert( 0 ); }
+
+ // Identify the owner of this memory stack's memory
+ void SetAllocOwner( const char *pszAllocOwner ) { m_MemoryStack.SetAllocOwner( pszAllocOwner ); }
+
+private:
+ CMemoryStack m_MemoryStack;
+ int m_nAllocated;
+};
+
+
+#ifdef _X360
+//-----------------------------------------------------------------------------
+// A memory stack used for allocating physical memory on the 360
+// Usage pattern anticipates we usually never go over the initial allocation
+// When we do so, we're ok with slightly slower allocation
+//-----------------------------------------------------------------------------
+class CPhysicalMemoryStack
+{
+public:
+ CPhysicalMemoryStack();
+ ~CPhysicalMemoryStack();
+
+ // The physical memory stack is allocated in chunks. We will initially
+ // allocate nInitChunkCount chunks, which will always be in memory.
+ // When FreeAll() is called, it will free down to the initial chunk count
+ // but not below it.
+ bool Init( size_t nChunkSizeInBytes, size_t nAlignment, int nInitialChunkCount, uint32 nAdditionalFlags );
+ void Term();
+
+ size_t GetSize() const;
+ size_t GetPeakUsed() const;
+ size_t GetUsed() const;
+ size_t GetFramePeakUsed() const;
+
+ MemoryStackMark_t GetCurrentAllocPoint() const;
+ void FreeToAllocPoint( MemoryStackMark_t mark, bool bUnused = true ); // bUnused is for interface compat with CMemoryStack
+ void *Alloc( size_t nSizeInBytes, bool bClear = false ) RESTRICT;
+ void FreeAll( bool bUnused = true ); // bUnused is for interface compat with CMemoryStack
+
+ void PrintContents();
+
+private:
+ void *AllocFromOverflow( size_t nSizeInBytes );
+
+ struct PhysicalChunk_t
+ {
+ uint8 *m_pBase;
+ uint8 *m_pNextAlloc;
+ uint8 *m_pAllocLimit;
+ };
+
+ PhysicalChunk_t m_InitialChunk;
+ CUtlVector< PhysicalChunk_t > m_ExtraChunks;
+ size_t m_nUsage;
+ size_t m_nFramePeakUsage;
+ size_t m_nPeakUsage;
+ size_t m_nAlignment;
+ size_t m_nChunkSizeInBytes;
+ int m_nFirstAvailableChunk;
+ int m_nAdditionalFlags;
+ PhysicalChunk_t *m_pLastAllocedChunk;
+};
+
+//-------------------------------------
+
+FORCEINLINE void *CPhysicalMemoryStack::Alloc( size_t nSizeInBytes, bool bClear ) RESTRICT
+{
+ if ( nSizeInBytes )
+ {
+ nSizeInBytes = AlignValue( nSizeInBytes, m_nAlignment );
+ }
+ else
+ {
+ nSizeInBytes = m_nAlignment;
+ }
+
+ // Can't do an allocation bigger than the chunk size
+ Assert( nSizeInBytes <= m_nChunkSizeInBytes );
+
+ void *pResult = m_InitialChunk.m_pNextAlloc;
+ uint8 *pNextAlloc = m_InitialChunk.m_pNextAlloc + nSizeInBytes;
+ if ( pNextAlloc <= m_InitialChunk.m_pAllocLimit )
+ {
+ m_InitialChunk.m_pNextAlloc = pNextAlloc;
+ m_pLastAllocedChunk = &m_InitialChunk;
+ }
+ else
+ {
+ pResult = AllocFromOverflow( nSizeInBytes );
+ }
+
+ m_nUsage += nSizeInBytes;
+ m_nFramePeakUsage = MAX( m_nUsage, m_nFramePeakUsage );
+ m_nPeakUsage = MAX( m_nUsage, m_nPeakUsage );
+
+ if ( bClear )
+ {
+ memset( pResult, 0, nSizeInBytes );
+ }
+
+ return pResult;
+}
+
+//-------------------------------------
+
+inline size_t CPhysicalMemoryStack::GetPeakUsed() const
+{
+ return m_nPeakUsage;
+}
+
+//-------------------------------------
+
+inline size_t CPhysicalMemoryStack::GetUsed() const
+{
+ return m_nUsage;
+}
+
+inline size_t CPhysicalMemoryStack::GetFramePeakUsed() const
+{
+ return m_nFramePeakUsage;
+}
+
+inline MemoryStackMark_t CPhysicalMemoryStack::GetCurrentAllocPoint() const
+{
+ Assert( m_pLastAllocedChunk );
+ return ( m_pLastAllocedChunk->m_pNextAlloc - m_pLastAllocedChunk->m_pBase );
+}
+
+#endif // _X360
+
+#endif // MEMSTACK_H
diff --git a/external/vpc/public/tier1/netadr.h b/external/vpc/public/tier1/netadr.h
new file mode 100644
index 0000000..c635a33
--- /dev/null
+++ b/external/vpc/public/tier1/netadr.h
@@ -0,0 +1,73 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// netadr.h
+#ifndef NETADR_H
+#define NETADR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#undef SetPort
+
+typedef enum
+{
+ NA_NULL = 0,
+ NA_LOOPBACK,
+ NA_BROADCAST,
+ NA_IP,
+} netadrtype_t;
+
+struct netadr_t
+{
+public:
+ netadr_t() { SetIP( 0 ); SetPort( 0 ); SetType( NA_IP ); }
+ netadr_t( uint unIP, uint16 usPort ) { SetIP( unIP ); SetPort( usPort ); SetType( NA_IP ); }
+ netadr_t( const char *pch ) { SetFromString( pch ); }
+ void Clear(); // invalids Address
+
+ void SetType( netadrtype_t type );
+ void SetPort( unsigned short port );
+ bool SetFromSockadr(const struct sockaddr *s);
+ void SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4);
+ void SetIP(uint unIP); // Sets IP. unIP is in host order (little-endian)
+ void SetIPAndPort( uint unIP, unsigned short usPort ) { SetIP( unIP ); SetPort( usPort ); }
+ void SetFromString(const char *pch, bool bUseDNS = false ); // if bUseDNS is true then do a DNS lookup if needed
+
+ bool CompareAdr (const netadr_t &a, bool onlyBase = false) const;
+ bool CompareClassBAdr (const netadr_t &a) const;
+ bool CompareClassCAdr (const netadr_t &a) const;
+
+ netadrtype_t GetType() const;
+ unsigned short GetPort() const;
+ const char* ToString( bool onlyBase = false ) const; // returns xxx.xxx.xxx.xxx:ppppp
+ void ToSockadr(struct sockaddr *s) const;
+ unsigned int GetIP() const;
+
+ bool IsLocalhost() const; // true, if this is the localhost IP
+ bool IsLoopback() const; // true if engine loopback buffers are used
+ bool IsReservedAdr() const; // true, if this is a private LAN IP
+ bool IsValid() const; // ip & port != 0
+ bool IsBaseAdrValid() const; // ip != 0
+
+ void SetFromSocket( int hSocket );
+
+ // These function names are decorated because the Xbox360 defines macros for ntohl and htonl
+ unsigned long addr_ntohl() const;
+ unsigned long addr_htonl() const;
+ bool operator==(const netadr_t &netadr) const {return ( CompareAdr( netadr ) );}
+ bool operator<(const netadr_t &netadr) const;
+
+public: // members are public to avoid to much changes
+
+ netadrtype_t type;
+ unsigned char ip[4];
+ unsigned short port;
+};
+
+#endif // NETADR_H
diff --git a/external/vpc/public/tier1/refcount.h b/external/vpc/public/tier1/refcount.h
new file mode 100644
index 0000000..58bcf65
--- /dev/null
+++ b/external/vpc/public/tier1/refcount.h
@@ -0,0 +1,384 @@
+//========== Copyright � 2005, Valve Corporation, All rights reserved. ========
+//
+// Purpose: Tools for correctly implementing & handling reference counted
+// objects
+//
+//=============================================================================
+
+#ifndef REFCOUNT_H
+#define REFCOUNT_H
+
+#include "tier0/threadtools.h"
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose: Implement a standard reference counted interface. Use of this
+// is optional insofar as all the concrete tools only require
+// at compile time that the function signatures match.
+//-----------------------------------------------------------------------------
+
+class IRefCounted
+{
+public:
+ virtual int AddRef() = 0;
+ virtual int Release() = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Release a pointer and mark it NULL
+//-----------------------------------------------------------------------------
+
+template <class REFCOUNTED_ITEM_PTR>
+inline int SafeRelease( REFCOUNTED_ITEM_PTR &pRef )
+{
+ // Use funny syntax so that this works on "auto pointers"
+ REFCOUNTED_ITEM_PTR *ppRef = &pRef;
+ if ( *ppRef )
+ {
+ int result = (*ppRef)->Release();
+ *ppRef = NULL;
+ return result;
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Maintain a reference across a scope
+//-----------------------------------------------------------------------------
+
+template <class T = IRefCounted>
+class CAutoRef
+{
+public:
+ CAutoRef( T *pRef )
+ : m_pRef( pRef )
+ {
+ if ( m_pRef )
+ m_pRef->AddRef();
+ }
+
+ ~CAutoRef()
+ {
+ if (m_pRef)
+ m_pRef->Release();
+ }
+
+private:
+ T *m_pRef;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Do a an inline AddRef then return the pointer, useful when
+// returning an object from a function
+//-----------------------------------------------------------------------------
+
+#define RetAddRef( p ) ( (p)->AddRef(), (p) )
+#define InlineAddRef( p ) ( (p)->AddRef(), (p) )
+
+
+//-----------------------------------------------------------------------------
+// Purpose: A class to both hold a pointer to an object and its reference.
+// Base exists to support other cleanup models
+//-----------------------------------------------------------------------------
+
+template <class T>
+class CBaseAutoPtr
+{
+public:
+ CBaseAutoPtr() : m_pObject(0) {}
+ CBaseAutoPtr(T *pFrom) : m_pObject(pFrom) {}
+
+ operator const void *() const { return m_pObject; }
+ operator void *() { return m_pObject; }
+
+ operator const T *() const { return m_pObject; }
+ operator const T *() { return m_pObject; }
+ operator T *() { return m_pObject; }
+
+ int operator=( int i ) { AssertMsg( i == 0, "Only NULL allowed on integer assign" ); m_pObject = 0; return 0; }
+ T * operator=( T *p ) { m_pObject = p; return p; }
+
+ bool operator !() const { return ( !m_pObject ); }
+ bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (m_pObject != NULL); }
+ bool operator==( const void *p ) const { return ( m_pObject == p ); }
+ bool operator!=( const void *p ) const { return ( m_pObject != p ); }
+ bool operator==( T *p ) const { return operator==( (void *)p ); }
+ bool operator!=( T *p ) const { return operator!=( (void *)p ); }
+ bool operator==( const CBaseAutoPtr<T> &p ) const { return operator==( (const void *)p ); }
+ bool operator!=( const CBaseAutoPtr<T> &p ) const { return operator!=( (const void *)p ); }
+
+ T * operator->() { return m_pObject; }
+ T & operator *() { return *m_pObject; }
+ T ** operator &() { return &m_pObject; }
+
+ const T * operator->() const { return m_pObject; }
+ const T & operator *() const { return *m_pObject; }
+ T * const * operator &() const { return &m_pObject; }
+
+protected:
+ CBaseAutoPtr( const CBaseAutoPtr<T> &from ) : m_pObject( from.m_pObject ) {}
+ void operator=( const CBaseAutoPtr<T> &from ) { m_pObject = from.m_pObject; }
+
+ T *m_pObject;
+};
+
+//---------------------------------------------------------
+
+template <class T>
+class CRefPtr : public CBaseAutoPtr<T>
+{
+ typedef CBaseAutoPtr<T> BaseClass;
+public:
+ CRefPtr() {}
+ CRefPtr( T *pInit ) : BaseClass( pInit ) {}
+ CRefPtr( const CRefPtr<T> &from ) : BaseClass( from ) {}
+ ~CRefPtr() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); }
+
+ void operator=( const CRefPtr<T> &from ) { BaseClass::operator=( from ); }
+
+ int operator=( int i ) { return BaseClass::operator=( i ); }
+ T *operator=( T *p ) { return BaseClass::operator=( p ); }
+
+ operator bool() const { return !BaseClass::operator!(); }
+ operator bool() { return !BaseClass::operator!(); }
+
+ void SafeRelease() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); BaseClass::m_pObject = 0; }
+ void AssignAddRef( T *pFrom ) { SafeRelease(); if (pFrom) pFrom->AddRef(); BaseClass::m_pObject = pFrom; }
+ void AddRefAssignTo( T *&pTo ) { ::SafeRelease( pTo ); if ( BaseClass::m_pObject ) BaseClass::m_pObject->AddRef(); pTo = BaseClass::m_pObject; }
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Traits classes defining reference count threading model
+//-----------------------------------------------------------------------------
+
+class CRefMT
+{
+public:
+ static int Increment( int *p) { return ThreadInterlockedIncrement( (int32 *)p ); }
+ static int Decrement( int *p) { return ThreadInterlockedDecrement( (int32 *)p ); }
+};
+
+class CRefST
+{
+public:
+ static int Increment( int *p) { return ++(*p); }
+ static int Decrement( int *p) { return --(*p); }
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Actual reference counting implementation. Pulled out to reduce
+// code bloat.
+//-----------------------------------------------------------------------------
+
+template <const bool bSelfDelete, typename CRefThreading = CRefMT>
+class NO_VTABLE CRefCountServiceBase
+{
+protected:
+ CRefCountServiceBase()
+ : m_iRefs( 1 )
+ {
+ }
+
+ virtual ~CRefCountServiceBase()
+ {
+ }
+
+ virtual bool OnFinalRelease()
+ {
+ return true;
+ }
+
+ int GetRefCount() const
+ {
+ return m_iRefs;
+ }
+
+ int DoAddRef()
+ {
+ return CRefThreading::Increment( &m_iRefs );
+ }
+
+ int DoRelease()
+ {
+ int result = CRefThreading::Decrement( &m_iRefs );
+ if ( result )
+ return result;
+ if ( OnFinalRelease() && bSelfDelete )
+ delete this;
+ return 0;
+ }
+
+private:
+ int m_iRefs;
+};
+
+class CRefCountServiceNull
+{
+protected:
+ static int DoAddRef() { return 1; }
+ static int DoRelease() { return 1; }
+};
+
+template <typename CRefThreading = CRefMT>
+class NO_VTABLE CRefCountServiceDestruct
+{
+protected:
+ CRefCountServiceDestruct()
+ : m_iRefs( 1 )
+ {
+ }
+
+ virtual ~CRefCountServiceDestruct()
+ {
+ }
+
+ int GetRefCount() const
+ {
+ return m_iRefs;
+ }
+
+ int DoAddRef()
+ {
+ return CRefThreading::Increment( &m_iRefs );
+ }
+
+ int DoRelease()
+ {
+ int result = CRefThreading::Decrement( &m_iRefs );
+ if ( result )
+ return result;
+ this->~CRefCountServiceDestruct();
+ return 0;
+ }
+
+private:
+ int m_iRefs;
+};
+
+
+typedef CRefCountServiceBase<true, CRefST> CRefCountServiceST;
+typedef CRefCountServiceBase<false, CRefST> CRefCountServiceNoDeleteST;
+
+typedef CRefCountServiceBase<true, CRefMT> CRefCountServiceMT;
+typedef CRefCountServiceBase<false, CRefMT> CRefCountServiceNoDeleteMT;
+
+// Default to threadsafe
+typedef CRefCountServiceNoDeleteMT CRefCountServiceNoDelete;
+typedef CRefCountServiceMT CRefCountService;
+
+//-----------------------------------------------------------------------------
+// Purpose: Base classes to implement reference counting
+//-----------------------------------------------------------------------------
+
+template < class REFCOUNT_SERVICE = CRefCountService >
+class NO_VTABLE CRefCounted : public REFCOUNT_SERVICE
+{
+public:
+ virtual ~CRefCounted() {}
+ int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
+ int Release() { return REFCOUNT_SERVICE::DoRelease(); }
+};
+
+//-------------------------------------
+
+template < class BASE1, class REFCOUNT_SERVICE = CRefCountService >
+class NO_VTABLE CRefCounted1 : public BASE1,
+ public REFCOUNT_SERVICE
+{
+public:
+ virtual ~CRefCounted1() {}
+ int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
+ int Release() { return REFCOUNT_SERVICE::DoRelease(); }
+};
+
+//-------------------------------------
+
+template < class BASE1, class BASE2, class REFCOUNT_SERVICE = CRefCountService >
+class NO_VTABLE CRefCounted2 : public BASE1, public BASE2,
+ public REFCOUNT_SERVICE
+{
+public:
+ virtual ~CRefCounted2() {}
+ int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
+ int Release() { return REFCOUNT_SERVICE::DoRelease(); }
+};
+
+//-------------------------------------
+
+template < class BASE1, class BASE2, class BASE3, class REFCOUNT_SERVICE = CRefCountService >
+class NO_VTABLE CRefCounted3 : public BASE1, public BASE2, public BASE3,
+ public REFCOUNT_SERVICE
+{
+ virtual ~CRefCounted3() {}
+ int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
+ int Release() { return REFCOUNT_SERVICE::DoRelease(); }
+};
+
+//-------------------------------------
+
+template < class BASE1, class BASE2, class BASE3, class BASE4, class REFCOUNT_SERVICE = CRefCountService >
+class NO_VTABLE CRefCounted4 : public BASE1, public BASE2, public BASE3, public BASE4,
+ public REFCOUNT_SERVICE
+{
+public:
+ virtual ~CRefCounted4() {}
+ int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
+ int Release() { return REFCOUNT_SERVICE::DoRelease(); }
+};
+
+//-------------------------------------
+
+template < class BASE1, class BASE2, class BASE3, class BASE4, class BASE5, class REFCOUNT_SERVICE = CRefCountService >
+class NO_VTABLE CRefCounted5 : public BASE1, public BASE2, public BASE3, public BASE4, public BASE5,
+ public REFCOUNT_SERVICE
+{
+public:
+ virtual ~CRefCounted5() {}
+ int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); }
+ int Release() { return REFCOUNT_SERVICE::DoRelease(); }
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Class to throw around a reference counted item to debug
+// referencing problems
+//-----------------------------------------------------------------------------
+#ifdef _DEBUG
+template <class BASE_REFCOUNTED, int FINAL_REFS = 0, const char *pszName = (const char *)NULL >
+class CRefDebug : public BASE_REFCOUNTED
+{
+public:
+ CRefDebug()
+ {
+ AssertMsg( this->GetRefCount() == 1, "Expected initial ref count of 1" );
+ DevMsg( "%s:create 0x%x\n", ( pszName ) ? pszName : "", this );
+ }
+
+ virtual ~CRefDebug()
+ {
+ AssertDevMsg( this->GetRefCount() == FINAL_REFS, "Object still referenced on destroy?" );
+ DevMsg( "%s:destroy 0x%x\n", ( pszName ) ? pszName : "", this );
+ }
+
+ int AddRef()
+ {
+ DevMsg( "%s:(0x%x)->AddRef() --> %d\n", ( pszName ) ? pszName : "", this, this->GetRefCount() + 1 );
+ return BASE_REFCOUNTED::AddRef();
+ }
+
+ int Release()
+ {
+ DevMsg( "%s:(0x%x)->Release() --> %d\n", ( pszName ) ? pszName : "", this, this->GetRefCount() - 1 );
+ Assert( this->GetRefCount() > 0 );
+ return BASE_REFCOUNTED::Release();
+ }
+};
+#endif
+
+//-----------------------------------------------------------------------------
+
+#endif // REFCOUNT_H
diff --git a/external/vpc/public/tier1/stringpool.h b/external/vpc/public/tier1/stringpool.h
new file mode 100644
index 0000000..67dfb51
--- /dev/null
+++ b/external/vpc/public/tier1/stringpool.h
@@ -0,0 +1,106 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef STRINGPOOL_H
+#define STRINGPOOL_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "utlrbtree.h"
+#include "utlvector.h"
+#include "utlbuffer.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: Allocates memory for strings, checking for duplicates first,
+// reusing exising strings if duplicate found.
+//-----------------------------------------------------------------------------
+
+enum StringPoolCase_t
+{
+ StringPoolCaseInsensitive,
+ StringPoolCaseSensitive
+};
+
+class CStringPool
+{
+public:
+ CStringPool( StringPoolCase_t caseSensitivity = StringPoolCaseInsensitive );
+ ~CStringPool();
+
+ unsigned int Count() const;
+
+ const char * Allocate( const char *pszValue );
+ // This feature is deliberately not supported because it's pretty dangerous
+ // given current uses of CStringPool, which assume they can copy string pointers without
+ // any refcounts.
+ //void Free( const char *pszValue );
+ void FreeAll();
+
+ // searches for a string already in the pool
+ const char * Find( const char *pszValue );
+
+protected:
+ typedef CUtlRBTree<const char *, unsigned short> CStrSet;
+
+ CStrSet m_Strings;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: A reference counted string pool.
+//
+// Elements are stored more efficiently than in the conventional string pool,
+// quicker to look up, and storage is tracked via reference counts.
+//
+// At some point this should replace CStringPool
+//-----------------------------------------------------------------------------
+class CCountedStringPool
+{
+public: // HACK, hash_item_t structure should not be public.
+
+ struct hash_item_t
+ {
+ char* pString;
+ unsigned short nNextElement;
+ unsigned char nReferenceCount;
+ unsigned char pad;
+ };
+
+ enum
+ {
+ INVALID_ELEMENT = 0,
+ MAX_REFERENCE = 0xFF,
+ HASH_TABLE_SIZE = 1024
+ };
+
+ CUtlVector<unsigned short> m_HashTable; // Points to each element
+ CUtlVector<hash_item_t> m_Elements;
+ unsigned short m_FreeListStart;
+ StringPoolCase_t m_caseSensitivity;
+
+public:
+ CCountedStringPool( StringPoolCase_t caseSensitivity = StringPoolCaseInsensitive );
+ virtual ~CCountedStringPool();
+
+ void FreeAll();
+
+ char *FindString( const char* pIntrinsic );
+ char *ReferenceString( const char* pIntrinsic );
+ void DereferenceString( const char* pIntrinsic );
+
+ // These are only reliable if there are less than 64k strings in your string pool
+ unsigned short FindStringHandle( const char* pIntrinsic );
+ unsigned short ReferenceStringHandle( const char* pIntrinsic );
+ char *HandleToString( unsigned short handle );
+ void SpewStrings();
+ unsigned Hash( const char *pszKey );
+
+ bool SaveToBuffer( CUtlBuffer &buffer );
+ bool RestoreFromBuffer( CUtlBuffer &buffer );};
+
+#endif // STRINGPOOL_H
diff --git a/external/vpc/public/tier1/strtools.h b/external/vpc/public/tier1/strtools.h
new file mode 100644
index 0000000..62d335f
--- /dev/null
+++ b/external/vpc/public/tier1/strtools.h
@@ -0,0 +1,589 @@
+//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef TIER1_STRTOOLS_H
+#define TIER1_STRTOOLS_H
+
+#include "tier0/basetypes.h"
+
+#ifdef _WIN32
+#pragma once
+#elif POSIX
+#include <ctype.h>
+#include <wchar.h>
+#include <math.h>
+#include <wctype.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+
+// 3d memcpy. Copy (up-to) 3 dimensional data with arbitrary source and destination
+// strides. Optimizes to just a single memcpy when possible. For 2d data, set numslices to 1.
+void CopyMemory3D( void *pDestAdr, void const *pSrcAdr,
+ int nNumCols, int nNumRows, int nNumSlices, // dimensions of copy
+ int nSrcBytesPerRow, int nSrcBytesPerSlice, // strides for source.
+ int nDestBytesPerRow, int nDestBytesPerSlice // strides for dest
+ );
+
+
+
+
+template< class T, class I > class CUtlMemory;
+template< class T, class A > class CUtlVector;
+
+
+//-----------------------------------------------------------------------------
+// Portable versions of standard string functions
+//-----------------------------------------------------------------------------
+void _V_memset ( void *dest, int fill, int count );
+void _V_memcpy ( void *dest, const void *src, int count );
+void _V_memmove ( void *dest, const void *src, int count );
+int _V_memcmp ( const void *m1, const void *m2, int count );
+int _V_strlen ( const char *str );
+void _V_strcpy ( char *dest, const char *src );
+char* _V_strrchr ( const char *s, char c );
+int _V_strcmp ( const char *s1, const char *s2 );
+int _V_wcscmp ( const wchar_t *s1, const wchar_t *s2 );
+int _V_stricmp ( const char *s1, const char *s2 );
+char* _V_strstr ( const char *s1, const char *search );
+char* _V_strupr ( char *start );
+char* _V_strlower ( char *start );
+int _V_wcslen ( const wchar_t *pwch );
+
+wchar_t* _V_wcslower (const char* file, int line, wchar_t *start);
+wchar_t* _V_wcsupr (const char* file, int line, wchar_t *start);
+
+#ifdef POSIX
+inline char *strupr( char *start )
+{
+ char *str = start;
+ while( str && *str )
+ {
+ *str = (char)toupper(*str);
+ str++;
+ }
+ return start;
+}
+
+inline char *strlwr( char *start )
+{
+ char *str = start;
+ while( str && *str )
+ {
+ *str = (char)tolower(*str);
+ str++;
+ }
+ return start;
+}
+
+inline wchar_t *_wcslwr( wchar_t *start )
+{
+ wchar_t *str = start;
+ while( str && *str )
+ {
+ *str = (wchar_t)towlower(static_cast<wint_t>(*str));
+ str++;
+ }
+ return start;
+};
+
+inline wchar_t *_wcsupr( wchar_t *start )
+{
+ wchar_t *str = start;
+ while( str && *str )
+ {
+ *str = (wchar_t)towupper(static_cast<wint_t>(*str));
+ str++;
+ }
+ return start;
+};
+
+#endif // POSIX
+
+// there are some users of these via tier1 templates in used in tier0. but tier0 can't depend on vstdlib which means in tier0 we always need the inlined ones
+#if ( !defined( TIER0_DLL_EXPORT ) )
+
+#if !defined( _DEBUG ) && defined( _PS3 )
+
+#include "tier1/strtools_inlines.h"
+
+// To avoid cross-prx calls, making the V_* fucntions that don't do anything but debug checks and call through to the non V_* function
+// go ahead and call the non-V_* functions directly.
+#define V_memset(dest, fill, count) memset ((dest), (fill), (count))
+#define V_memcpy(dest, src, count) memcpy ((dest), (src), (count))
+#define V_memmove(dest, src, count) memmove ((dest), (src), (count))
+#define V_memcmp(m1, m2, count) memcmp ((m1), (m2), (count))
+#define V_strcpy(dest, src) strcpy ((dest), (src))
+#define V_strcmp(s1, s2) strcmp ((s1), (s2))
+#define V_strupr(start) strupr ((start))
+#define V_strlower(start) strlwr ((start))
+#define V_wcslen(pwch) wcslen ((pwch))
+// To avoid cross-prx calls, using inline versions of these custom functions:
+#define V_strlen(str) _V_strlen_inline ((str))
+#define V_strrchr(s, c) _V_strrchr_inline ((s), (c))
+#define V_wcscmp(s1, s2) _V_wcscmp_inline ((s1), (s2))
+#define V_stricmp(s1, s2 ) _V_stricmp_inline ((s1), (s2) )
+#define V_strstr(s1, search ) _V_strstr_inline ((s1), (search) )
+
+#else
+
+#define V_memset(dest, fill, count) _V_memset ((dest), (fill), (count))
+#define V_memcpy(dest, src, count) _V_memcpy ((dest), (src), (count))
+#define V_memmove(dest, src, count) _V_memmove ((dest), (src), (count))
+#define V_memcmp(m1, m2, count) _V_memcmp ((m1), (m2), (count))
+#define V_strlen(str) _V_strlen ((str))
+#define V_strcpy(dest, src) _V_strcpy ((dest), (src))
+#define V_strrchr(s, c) _V_strrchr ((s), (c))
+#define V_strcmp(s1, s2) _V_strcmp ((s1), (s2))
+#define V_wcscmp(s1, s2) _V_wcscmp ((s1), (s2))
+#define V_stricmp(s1, s2 ) _V_stricmp ((s1), (s2) )
+#define V_strstr(s1, search ) _V_strstr ((s1), (search) )
+#define V_strupr(start) _V_strupr ((start))
+#define V_strlower(start) _V_strlower ((start))
+#define V_wcslen(pwch) _V_wcslen ((pwch))
+
+#endif
+
+#else
+
+inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); }
+inline void V_memcpy (void *dest, const void *src, int count) { memcpy( dest, src, count ); }
+inline void V_memmove (void *dest, const void *src, int count) { memmove( dest, src, count ); }
+inline int V_memcmp (const void *m1, const void *m2, int count){ return memcmp( m1, m2, count ); }
+inline int V_strlen (const char *str) { return (int) strlen ( str ); }
+inline void V_strcpy (char *dest, const char *src) { strcpy( dest, src ); }
+inline int V_wcslen(const wchar_t *pwch) { return (int)wcslen(pwch); }
+inline char* V_strrchr (const char *s, char c) { return (char*)strrchr( s, c ); }
+inline int V_strcmp (const char *s1, const char *s2) { return strcmp( s1, s2 ); }
+inline int V_wcscmp (const wchar_t *s1, const wchar_t *s2) { return wcscmp( s1, s2 ); }
+inline int V_stricmp( const char *s1, const char *s2 ) { return stricmp( s1, s2 ); }
+inline char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); }
+#ifndef COMPILER_PS3
+inline char* V_strupr (char *start) { return strupr( start ); }
+inline char* V_strlower (char *start) { return strlwr( start ); }
+inline wchar_t* V_wcsupr (wchar_t *start) { return _wcsupr( start ); }
+#endif
+
+#endif
+
+
+int V_strncmp (const char *s1, const char *s2, int count);
+int V_strcasecmp (const char *s1, const char *s2);
+int V_strncasecmp (const char *s1, const char *s2, int n);
+int V_strnicmp (const char *s1, const char *s2, int n);
+int V_atoi (const char *str);
+int64 V_atoi64(const char *str);
+uint64 V_atoui64(const char *str);
+float V_atof (const char *str);
+char* V_stristr( char* pStr, const char* pSearch );
+const char* V_stristr( const char* pStr, const char* pSearch );
+const char* V_strnistr( const char* pStr, const char* pSearch, int n );
+const char* V_strnchr( const char* pStr, char c, int n );
+
+// returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found
+const char *StringAfterPrefix ( const char *str, const char *prefix );
+const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix );
+inline bool StringHasPrefix ( const char *str, const char *prefix ) { return StringAfterPrefix ( str, prefix ) != NULL; }
+inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; }
+
+
+// Normalizes a float string in place.
+// (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible)
+void V_normalizeFloatString( char* pFloat );
+
+inline bool V_isspace(int c)
+{
+ // The standard white-space characters are the following: space, tab, carriage-return, newline, vertical tab, and form-feed. In the C locale, V_isspace() returns true only for the standard white-space characters.
+ //return c == ' ' || c == 9 /*horizontal tab*/ || c == '\r' || c == '\n' || c == 11 /*vertical tab*/ || c == '\f';
+ // codes of whitespace symbols: 9 HT, 10 \n, 11 VT, 12 form feed, 13 \r, 32 space
+
+ // easy to understand version, validated:
+ // return ((1 << (c-1)) & 0x80001F00) != 0 && ((c-1)&0xE0) == 0;
+
+ // 5% faster on Core i7, 35% faster on Xbox360, no branches, validated:
+ #ifdef _X360
+ return ((1 << (c-1)) & 0x80001F00 & ~(-int((c-1)&0xE0))) != 0;
+ #else
+ // this is 11% faster on Core i7 than the previous, VC2005 compiler generates a seemingly unbalanced search tree that's faster
+ switch(c)
+ {
+ case ' ':
+ case 9:
+ case '\r':
+ case '\n':
+ case 11:
+ case '\f':
+ return true;
+ default:
+ return false;
+ }
+ #endif
+}
+
+
+// These are versions of functions that guarantee NULL termination.
+//
+// maxLen is the maximum number of bytes in the destination string.
+// pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen.
+//
+// This means the last parameter can usually be a sizeof() of a string.
+void V_strncpy( char *pDest, const char *pSrc, int maxLen );
+int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ) FMTFUNCTION( 3, 4 );
+void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
+int V_snwprintf( wchar_t *pDest, int maxLenInNumWideCharacters, const wchar_t *pFormat, ... );
+
+#define COPY_ALL_CHARACTERS -1
+char *V_strncat(char *, const char *, size_t maxLenInBytes, int max_chars_to_copy=COPY_ALL_CHARACTERS );
+wchar_t *V_wcsncat(wchar_t *, const wchar_t *, int maxLenInBytes, int max_chars_to_copy=COPY_ALL_CHARACTERS );
+char *V_strnlwr(char *, size_t);
+
+
+// UNDONE: Find a non-compiler-specific way to do this
+#ifdef _WIN32
+#ifndef _VA_LIST_DEFINED
+
+#ifdef _M_ALPHA
+
+struct va_list
+{
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+};
+
+#else // !_M_ALPHA
+
+typedef char * va_list;
+
+#endif // !_M_ALPHA
+
+#define _VA_LIST_DEFINED
+
+#endif // _VA_LIST_DEFINED
+
+#elif POSIX
+#include <stdarg.h>
+#endif
+
+#ifdef _WIN32
+#define CORRECT_PATH_SEPARATOR '\\'
+#define CORRECT_PATH_SEPARATOR_S "\\"
+#define INCORRECT_PATH_SEPARATOR '/'
+#define INCORRECT_PATH_SEPARATOR_S "/"
+#elif POSIX || defined( _PS3 )
+#define CORRECT_PATH_SEPARATOR '/'
+#define CORRECT_PATH_SEPARATOR_S "/"
+#define INCORRECT_PATH_SEPARATOR '\\'
+#define INCORRECT_PATH_SEPARATOR_S "\\"
+#endif
+
+int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params );
+int V_vsnprintfRet( char *pDest, int maxLen, const char *pFormat, va_list params, bool *pbTruncated );
+
+// Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes )
+char *V_pretifymem( float value, int digitsafterdecimal = 2, bool usebinaryonek = false );
+
+// Prints out a pretified integer with comma separators (eg, 7,233,270,000)
+char *V_pretifynum( int64 value );
+
+// Functions for converting hexidecimal character strings back into binary data etc.
+//
+// e.g.,
+// int output;
+// V_hextobinary( "ffffffff", 8, &output, sizeof( output ) );
+// would make output == 0xfffffff or -1
+// Similarly,
+// char buffer[ 9 ];
+// V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) );
+// would put "ffffffff" into buffer (note null terminator!!!)
+void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes );
+void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize );
+
+// Tools for working with filenames
+// Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator)
+void V_FileBase( const char *in, char *out,int maxlen );
+// Remove the final characters of ppath if it's '\' or '/'.
+void V_StripTrailingSlash( char *ppath );
+// Remove any extension from in and return resulting string in out
+void V_StripExtension( const char *in, char *out, int outLen );
+// Make path end with extension if it doesn't already have an extension
+void V_DefaultExtension( char *path, const char *extension, int pathStringLength );
+// Strips any current extension from path and ensures that extension is the new extension.
+// NOTE: extension string MUST include the . character
+void V_SetExtension( char *path, const char *extension, int pathStringLength );
+// Removes any filename from path ( strips back to previous / or \ character )
+void V_StripFilename( char *path );
+// Remove the final directory from the path
+bool V_StripLastDir( char *dirName, int maxlen );
+// Returns a pointer to the unqualified file name (no path) of a file name
+const char * V_UnqualifiedFileName( const char * in );
+char * V_UnqualifiedFileName( char * in );
+// Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary
+void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize );
+
+// Copy out the path except for the stuff after the final pathseparator
+bool V_ExtractFilePath( const char *path, char *dest, int destSize );
+// Copy out the file extension into dest
+void V_ExtractFileExtension( const char *path, char *dest, int destSize );
+
+const char *V_GetFileExtension( const char * path );
+
+// returns a pointer to just the filename part of the path
+// (everything after the last path seperator)
+const char *V_GetFileName( const char * path );
+
+// This removes "./" and "../" from the pathname. pFilename should be a full pathname.
+// Returns false if it tries to ".." past the root directory in the drive (in which case
+// it is an invalid path).
+bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR );
+
+// If pPath is a relative path, this function makes it into an absolute path
+// using the current working directory as the base, or pStartingDir if it's non-NULL.
+// Returns false if it runs out of room in the string, or if pPath tries to ".." past the root directory.
+void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir = NULL );
+
+// Creates a relative path given two full paths
+// The first is the full path of the file to make a relative path for.
+// The second is the full path of the directory to make the first file relative to
+// Returns false if they can't be made relative (on separate drives, for example)
+bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen );
+
+// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc.
+void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath );
+
+// Adds a path separator to the end of the string if there isn't one already. Returns false if it would run out of space.
+void V_AppendSlash( char *pStr, int strSize );
+
+// Returns true if the path is an absolute path.
+bool V_IsAbsolutePath( const char *pPath );
+
+// Scans pIn and replaces all occurences of pMatch with pReplaceWith.
+// Writes the result to pOut.
+// Returns true if it completed successfully.
+// If it would overflow pOut, it fills as much as it can and returns false.
+bool V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith,
+ char *pOut, int outLen, bool bCaseSensitive=false );
+
+
+// Split the specified string on the specified separator.
+// Returns a list of strings separated by pSeparator.
+// You are responsible for freeing the contents of outStrings (call outStrings.PurgeAndDeleteElements).
+void V_SplitString( const char *pString, const char *pSeparator, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
+
+// Just like V_SplitString, but it can use multiple possible separators.
+void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector<char*, CUtlMemory<char*, int> > &outStrings );
+
+// Returns false if the buffer is not large enough to hold the working directory name.
+bool V_GetCurrentDirectory( char *pOut, int maxLen );
+
+// Set the working directory thus.
+bool V_SetCurrentDirectory( const char *pDirName );
+
+
+// This function takes a slice out of pStr and stores it in pOut.
+// It follows the Python slice convention:
+// Negative numbers wrap around the string (-1 references the last character).
+// Large numbers are clamped to the end of the string.
+void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize );
+
+// Chop off the left nChars of a string.
+void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize );
+
+// Chop off the right nChars of a string.
+void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize );
+
+// change "special" characters to have their c-style backslash sequence. like \n, \r, \t, ", etc.
+// returns a pointer to a newly allocated string, which you must delete[] when finished with.
+char *V_AddBackSlashesToSpecialChars( char const *pSrc );
+
+// Force slashes of either type to be = separator character
+void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR );
+
+// This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash.
+void V_FixDoubleSlashes( char *pStr );
+
+// Convert multibyte to wchar + back
+// Specify -1 for nInSize for null-terminated string
+void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize );
+void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize );
+
+// buffer-safe strcat
+inline void V_strcat( char *dest, const char *src, int maxLenInBytes )
+{
+ V_strncat( dest, src, maxLenInBytes, COPY_ALL_CHARACTERS );
+}
+
+// buffer-safe strcat
+inline void V_wcscat( wchar_t *dest, const wchar_t *src, int maxLenInBytes )
+{
+ V_wcsncat( dest, src, maxLenInBytes, COPY_ALL_CHARACTERS );
+}
+
+// Convert from a string to an array of integers.
+void V_StringToIntArray( int *pVector, int count, const char *pString );
+
+// Convert from a string to a 4 byte color value.
+void V_StringToColor32( color32 *color, const char *pString );
+
+// Convert \r\n (Windows linefeeds) to \n (Unix linefeeds).
+void V_TranslateLineFeedsToUnix( char *pStr );
+
+//-----------------------------------------------------------------------------
+// generic unique name helper functions
+//-----------------------------------------------------------------------------
+
+// returns -1 if no match, nDefault if pName==prefix, and N if pName==prefix+N
+inline int V_IndexAfterPrefix( const char *pName, const char *prefix, int nDefault = 0 )
+{
+ if ( !pName || !prefix )
+ return -1;
+
+ const char *pIndexStr = StringAfterPrefix( pName, prefix );
+ if ( !pIndexStr )
+ return -1;
+
+ if ( !*pIndexStr )
+ return nDefault;
+
+ return atoi( pIndexStr );
+}
+
+// returns startindex if none found, 2 if "prefix" found, and n+1 if "prefixn" found
+template < class NameArray >
+int V_GenerateUniqueNameIndex( const char *prefix, const NameArray &nameArray, int startindex = 0 )
+{
+ if ( !prefix )
+ return 0;
+
+ int freeindex = startindex;
+
+ int nNames = nameArray.Count();
+ for ( int i = 0; i < nNames; ++i )
+ {
+ int index = V_IndexAfterPrefix( nameArray[ i ], prefix, 1 ); // returns -1 if no match, 0 for exact match, N for
+ if ( index >= freeindex )
+ {
+ // TODO - check that there isn't more junk after the index in pElementName
+ freeindex = index + 1;
+ }
+ }
+
+ return freeindex;
+}
+
+template < class NameArray >
+bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const NameArray &nameArray )
+{
+ if ( name == NULL || memsize == 0 )
+ return false;
+
+ if ( prefix == NULL )
+ {
+ name[ 0 ] = '\0';
+ return false;
+ }
+
+ int prefixLength = V_strlen( prefix );
+ if ( prefixLength + 1 > memsize )
+ {
+ name[ 0 ] = '\0';
+ return false;
+ }
+
+ int i = V_GenerateUniqueNameIndex( prefix, nameArray );
+ if ( i <= 0 )
+ {
+ V_strncpy( name, prefix, memsize );
+ return true;
+ }
+
+ int newlen = prefixLength + ( int )log10( ( float )i ) + 1;
+ if ( newlen + 1 > memsize )
+ {
+ V_strncpy( name, prefix, memsize );
+ return false;
+ }
+
+ V_snprintf( name, memsize, "%s%d", prefix, i );
+ return true;
+}
+
+
+extern bool V_StringToBin( const char*pString, void *pBin, uint nBinSize );
+extern bool V_BinToString( char*pString, void *pBin, uint nBinSize );
+
+template<typename T>
+struct BinString_t
+{
+ BinString_t(){}
+ BinString_t( const char *pStr )
+ {
+ V_strncpy( m_string, pStr, sizeof(m_string) );
+ ToBin();
+ }
+ BinString_t( const T & that )
+ {
+ m_bin = that;
+ ToString();
+ }
+ bool ToBin()
+ {
+ return V_StringToBin( m_string, &m_bin, sizeof( m_bin ) );
+ }
+ void ToString()
+ {
+ V_BinToString( m_string, &m_bin, sizeof( m_bin ) );
+ }
+ T m_bin;
+ char m_string[sizeof(T)*2+2]; // 0-terminated string representing the binary data in hex
+};
+
+template <typename T>
+inline BinString_t<T> MakeBinString( const T& that )
+{
+ return BinString_t<T>( that );
+}
+
+
+
+
+
+
+#if defined(_PS3) || defined(POSIX)
+#define PRI_WS_FOR_WS L"%ls"
+#define PRI_WS_FOR_S "%ls"
+#define PRI_S_FOR_WS L"%s"
+#define PRI_S_FOR_S "%s"
+#else
+#define PRI_WS_FOR_WS L"%s"
+#define PRI_WS_FOR_S "%S"
+#define PRI_S_FOR_WS L"%S"
+#define PRI_S_FOR_S "%s"
+#endif
+
+namespace AsianWordWrap
+{
+ // Functions used by Asian language line wrapping to determine if a character can end a line, begin a line, or be broken up when repeated (eg: "...")
+ bool CanEndLine( wchar_t wcCandidate );
+ bool CanBeginLine( wchar_t wcCandidate );
+ bool CanBreakRepeated( wchar_t wcCandidate );
+
+ // Used to determine if we can break a line between the first two characters passed; calls the above functions on each character
+ bool CanBreakAfter( const wchar_t* wsz );
+}
+
+// We use this function to determine where it is permissible to break lines
+// of text while wrapping them. On most platforms, the native iswspace() function
+// returns FALSE for the "non-breaking space" characters 0x00a0 and 0x202f, and so we don't
+// break on them. On the 360, however, iswspace returns TRUE for them. So, on that
+// platform, we work around it by defining this wrapper which returns false
+// for &nbsp; and calls through to the library function for everything else.
+int isbreakablewspace( wchar_t ch );
+
+#endif // TIER1_STRTOOLS_H
diff --git a/external/vpc/public/tier1/tier1.h b/external/vpc/public/tier1/tier1.h
new file mode 100644
index 0000000..c4d89c6
--- /dev/null
+++ b/external/vpc/public/tier1/tier1.h
@@ -0,0 +1,85 @@
+//===== Copyright � 2005-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: A higher level link library for general use in the game and tools.
+//
+//===========================================================================//
+
+
+#ifndef TIER1_H
+#define TIER1_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "appframework/iappsystem.h"
+#include "tier1/convar.h"
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Call this to connect to/disconnect from all tier 1 libraries.
+// It's up to the caller to check the globals it cares about to see if ones are missing
+//-----------------------------------------------------------------------------
+void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount );
+void DisconnectTier1Libraries();
+
+
+//-----------------------------------------------------------------------------
+// Helper empty implementation of an IAppSystem for tier2 libraries
+//-----------------------------------------------------------------------------
+template< class IInterface, int ConVarFlag = 0 >
+class CTier1AppSystem : public CTier0AppSystem< IInterface >
+{
+ typedef CTier0AppSystem< IInterface > BaseClass;
+
+public:
+ virtual bool Connect( CreateInterfaceFn factory )
+ {
+ if ( !BaseClass::Connect( factory ) )
+ return false;
+
+ ConnectTier1Libraries( &factory, 1 );
+ return true;
+ }
+
+ virtual void Disconnect()
+ {
+ DisconnectTier1Libraries();
+ BaseClass::Disconnect();
+ }
+
+ virtual InitReturnVal_t Init()
+ {
+ InitReturnVal_t nRetVal = BaseClass::Init();
+ if ( nRetVal != INIT_OK )
+ return nRetVal;
+
+ if ( g_pCVar )
+ {
+ ConVar_Register( ConVarFlag );
+ }
+ return INIT_OK;
+ }
+
+ virtual void Shutdown()
+ {
+ if ( g_pCVar )
+ {
+ ConVar_Unregister( );
+ }
+ BaseClass::Shutdown( );
+ }
+
+ virtual AppSystemTier_t GetTier()
+ {
+ return APP_SYSTEM_TIER1;
+ }
+};
+
+
+#endif // TIER1_H
+
diff --git a/external/vpc/public/tier1/utlblockmemory.h b/external/vpc/public/tier1/utlblockmemory.h
new file mode 100644
index 0000000..81ba5e5
--- /dev/null
+++ b/external/vpc/public/tier1/utlblockmemory.h
@@ -0,0 +1,349 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable memory class.
+//===========================================================================//
+
+#ifndef UTLBLOCKMEMORY_H
+#define UTLBLOCKMEMORY_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/platform.h"
+#include "mathlib/mathlib.h"
+
+#include "tier0/memalloc.h"
+#include "tier0/memdbgon.h"
+
+#pragma warning (disable:4100)
+#pragma warning (disable:4514)
+
+//-----------------------------------------------------------------------------
+
+#ifdef UTBLOCKLMEMORY_TRACK
+#define UTLBLOCKMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlBlockMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
+#define UTLBLOCKMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlBlockMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
+#else
+#define UTLBLOCKMEMORY_TRACK_ALLOC() ((void)0)
+#define UTLBLOCKMEMORY_TRACK_FREE() ((void)0)
+#endif
+
+
+//-----------------------------------------------------------------------------
+// The CUtlBlockMemory class:
+// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
+//-----------------------------------------------------------------------------
+template< class T, class I >
+class CUtlBlockMemory
+{
+public:
+ // constructor, destructor
+ CUtlBlockMemory( int nGrowSize = 0, int nInitSize = 0 );
+ ~CUtlBlockMemory();
+
+ // Set the size by which the memory grows - round up to the next power of 2
+ void Init( int nGrowSize = 0, int nInitSize = 0 );
+
+ // here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
+ T* Base() { return NULL; }
+ const T* Base() const { return NULL; }
+
+ class Iterator_t
+ {
+ public:
+ Iterator_t( I i ) : index( i ) {}
+ I index;
+
+ bool operator==( const Iterator_t it ) const { return index == it.index; }
+ bool operator!=( const Iterator_t it ) const { return index != it.index; }
+ };
+ Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); }
+ Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); }
+ I GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
+ bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); }
+ Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
+
+ // element access
+ T& operator[]( I i );
+ const T& operator[]( I i ) const;
+ T& Element( I i );
+ const T& Element( I i ) const;
+
+ // Can we use this index?
+ bool IsIdxValid( I i ) const;
+ static I InvalidIndex() { return ( I )-1; }
+
+ void Swap( CUtlBlockMemory< T, I > &mem );
+
+ // Size
+ int NumAllocated() const;
+ int Count() const { return NumAllocated(); }
+
+ // Grows memory by max(num,growsize) rounded up to the next power of 2, and returns the allocation index/ptr
+ void Grow( int num = 1 );
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num );
+
+ // Memory deallocation
+ void Purge();
+
+ // Purge all but the given number of elements
+ void Purge( int numElements );
+
+protected:
+ int Index( int major, int minor ) const { return ( major << m_nIndexShift ) | minor; }
+ int MajorIndex( int i ) const { return i >> m_nIndexShift; }
+ int MinorIndex( int i ) const { return i & m_nIndexMask; }
+ void ChangeSize( int nBlocks );
+ int NumElementsInBlock() const { return m_nIndexMask + 1; }
+
+ T** m_pMemory;
+ int m_nBlocks;
+ int m_nIndexMask : 27;
+ int m_nIndexShift : 5;
+};
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template< class T, class I >
+CUtlBlockMemory<T,I>::CUtlBlockMemory( int nGrowSize, int nInitAllocationCount )
+: m_pMemory( 0 ), m_nBlocks( 0 ), m_nIndexMask( 0 ), m_nIndexShift( 0 )
+{
+ Init( nGrowSize, nInitAllocationCount );
+}
+
+template< class T, class I >
+CUtlBlockMemory<T,I>::~CUtlBlockMemory()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Fast swap
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlBlockMemory<T,I>::Swap( CUtlBlockMemory< T, I > &mem )
+{
+ V_swap( m_pMemory, mem.m_pMemory );
+ V_swap( m_nBlocks, mem.m_nBlocks );
+ V_swap( m_nIndexMask, mem.m_nIndexMask );
+ V_swap( m_nIndexShift, mem.m_nIndexShift );
+}
+
+
+//-----------------------------------------------------------------------------
+// Set the size by which the memory grows - round up to the next power of 2
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlBlockMemory<T,I>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ )
+{
+ Purge();
+
+ if ( nGrowSize == 0)
+ {
+ // default grow size is smallest size s.t. c++ allocation overhead is ~6% of block size
+ nGrowSize = ( 127 + sizeof( T ) ) / sizeof( T );
+ }
+ nGrowSize = SmallestPowerOfTwoGreaterOrEqual( nGrowSize );
+ m_nIndexMask = nGrowSize - 1;
+
+ m_nIndexShift = 0;
+ while ( nGrowSize > 1 )
+ {
+ nGrowSize >>= 1;
+ ++m_nIndexShift;
+ }
+ Assert( m_nIndexMask + 1 == ( 1 << m_nIndexShift ) );
+
+ Grow( nInitSize );
+}
+
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline T& CUtlBlockMemory<T,I>::operator[]( I i )
+{
+ Assert( IsIdxValid(i) );
+ T *pBlock = m_pMemory[ MajorIndex( i ) ];
+ return pBlock[ MinorIndex( i ) ];
+}
+
+template< class T, class I >
+inline const T& CUtlBlockMemory<T,I>::operator[]( I i ) const
+{
+ Assert( IsIdxValid(i) );
+ const T *pBlock = m_pMemory[ MajorIndex( i ) ];
+ return pBlock[ MinorIndex( i ) ];
+}
+
+template< class T, class I >
+inline T& CUtlBlockMemory<T,I>::Element( I i )
+{
+ Assert( IsIdxValid(i) );
+ T *pBlock = m_pMemory[ MajorIndex( i ) ];
+ return pBlock[ MinorIndex( i ) ];
+}
+
+template< class T, class I >
+inline const T& CUtlBlockMemory<T,I>::Element( I i ) const
+{
+ Assert( IsIdxValid(i) );
+ const T *pBlock = m_pMemory[ MajorIndex( i ) ];
+ return pBlock[ MinorIndex( i ) ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Size
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline int CUtlBlockMemory<T,I>::NumAllocated() const
+{
+ return m_nBlocks * NumElementsInBlock();
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline bool CUtlBlockMemory<T,I>::IsIdxValid( I i ) const
+{
+ return ( i >= 0 ) && ( MajorIndex( i ) < m_nBlocks );
+}
+
+template< class T, class I >
+void CUtlBlockMemory<T,I>::Grow( int num )
+{
+ if ( num <= 0 )
+ return;
+
+ int nBlockSize = NumElementsInBlock();
+ int nBlocks = ( num + nBlockSize - 1 ) / nBlockSize;
+
+ ChangeSize( m_nBlocks + nBlocks );
+}
+
+template< class T, class I >
+void CUtlBlockMemory<T,I>::ChangeSize( int nBlocks )
+{
+ UTLBLOCKMEMORY_TRACK_FREE(); // this must stay before the recalculation of m_nBlocks, since it implicitly uses the old value
+
+ int nBlocksOld = m_nBlocks;
+ m_nBlocks = nBlocks;
+
+ UTLBLOCKMEMORY_TRACK_ALLOC(); // this must stay after the recalculation of m_nBlocks, since it implicitly uses the new value
+
+ // free old blocks if shrinking
+ for ( int i = m_nBlocks; i < nBlocksOld; ++i )
+ {
+ UTLBLOCKMEMORY_TRACK_FREE();
+ free( (void*)m_pMemory[ i ] );
+ }
+
+ if ( m_pMemory )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T**)realloc( m_pMemory, m_nBlocks * sizeof(T*) );
+ Assert( m_pMemory );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T**)malloc( m_nBlocks * sizeof(T*) );
+ Assert( m_pMemory );
+ }
+
+ if ( !m_pMemory )
+ {
+ Error( "CUtlBlockMemory overflow!\n" );
+ }
+
+ // allocate new blocks if growing
+ int nBlockSize = NumElementsInBlock();
+ for ( int i = nBlocksOld; i < m_nBlocks; ++i )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory[ i ] = (T*)malloc( nBlockSize * sizeof( T ) );
+ Assert( m_pMemory[ i ] );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we've got at least this much memory
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline void CUtlBlockMemory<T,I>::EnsureCapacity( int num )
+{
+ Grow( num - NumAllocated() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlBlockMemory<T,I>::Purge()
+{
+ if ( !m_pMemory )
+ return;
+
+ for ( int i = 0; i < m_nBlocks; ++i )
+ {
+ UTLBLOCKMEMORY_TRACK_FREE();
+ free( (void*)m_pMemory[ i ] );
+ }
+ m_nBlocks = 0;
+
+ UTLBLOCKMEMORY_TRACK_FREE();
+ free( (void*)m_pMemory );
+ m_pMemory = 0;
+}
+
+template< class T, class I >
+void CUtlBlockMemory<T,I>::Purge( int numElements )
+{
+ Assert( numElements >= 0 );
+
+ int nAllocated = NumAllocated();
+ if ( numElements > nAllocated )
+ {
+ // Ensure this isn't a grow request in disguise.
+ Assert( numElements <= nAllocated );
+ return;
+ }
+
+ if ( numElements <= 0 )
+ {
+ Purge();
+ return;
+ }
+
+ int nBlockSize = NumElementsInBlock();
+ int nBlocksOld = m_nBlocks;
+ int nBlocks = ( numElements + nBlockSize - 1 ) / nBlockSize;
+
+ // If the number of blocks is the same as the allocated number of blocks, we are done.
+ if ( nBlocks == m_nBlocks )
+ return;
+
+ ChangeSize( nBlocks );
+}
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLBLOCKMEMORY_H
diff --git a/external/vpc/public/tier1/utlbuffer.h b/external/vpc/public/tier1/utlbuffer.h
new file mode 100644
index 0000000..5832750
--- /dev/null
+++ b/external/vpc/public/tier1/utlbuffer.h
@@ -0,0 +1,1398 @@
+//====== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLBUFFER_H
+#define UTLBUFFER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "unitlib/unitlib.h" // just here for tests - remove before checking in!!!
+
+#include "tier1/utlmemory.h"
+#include "tier1/byteswap.h"
+#include <stdarg.h>
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct characterset_t;
+
+
+//-----------------------------------------------------------------------------
+// Description of character conversions for string output
+// Here's an example of how to use the macros to define a character conversion
+// BEGIN_CHAR_CONVERSION( CStringConversion, '\\' )
+// { '\n', "n" },
+// { '\t', "t" }
+// END_CHAR_CONVERSION( CStringConversion, '\\' )
+//-----------------------------------------------------------------------------
+class CUtlCharConversion
+{
+public:
+ struct ConversionArray_t
+ {
+ char m_nActualChar;
+ char *m_pReplacementString;
+ };
+
+ CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray );
+ char GetEscapeChar() const;
+ const char *GetDelimiter() const;
+ int GetDelimiterLength() const;
+
+ const char *GetConversionString( char c ) const;
+ int GetConversionLength( char c ) const;
+ int MaxConversionLength() const;
+
+ // Finds a conversion for the passed-in string, returns length
+ virtual char FindConversion( const char *pString, int *pLength );
+
+protected:
+ struct ConversionInfo_t
+ {
+ int m_nLength;
+ char *m_pReplacementString;
+ };
+
+ char m_nEscapeChar;
+ const char *m_pDelimiter;
+ int m_nDelimiterLength;
+ int m_nCount;
+ int m_nMaxConversionLength;
+ char m_pList[256];
+ ConversionInfo_t m_pReplacements[256];
+};
+
+#define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
+ static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
+
+#define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \
+ }; \
+ CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
+
+#define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
+ static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = {
+
+#define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \
+ }; \
+ _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name );
+
+//-----------------------------------------------------------------------------
+// Character conversions for C strings
+//-----------------------------------------------------------------------------
+CUtlCharConversion *GetCStringCharConversion();
+
+//-----------------------------------------------------------------------------
+// Character conversions for quoted strings, with no escape sequences
+//-----------------------------------------------------------------------------
+CUtlCharConversion *GetNoEscCharConversion();
+
+
+//-----------------------------------------------------------------------------
+// Macro to set overflow functions easily
+//-----------------------------------------------------------------------------
+#define SetUtlBufferOverflowFuncs( _get, _put ) \
+ SetOverflowFuncs( static_cast <UtlBufferOverflowFunc_t>( _get ), static_cast <UtlBufferOverflowFunc_t>( _put ) )
+
+
+#define FMSTRRETTYPE static const char *
+#ifdef LINUX
+// gcc 4.3 is techinically correct and doesn't like the storage specifier,
+// unfortunately, that makes gcc on the mac and VS wind up with multiply defined
+// symbols at link time
+#define FMSTRRETTYPE const char *
+#endif
+
+typedef unsigned short ushort;
+
+template < class A >
+static const char *GetFmtStr( int nRadix = 10, bool bPrint = true ) { Assert( 0 ); return ""; }
+
+template <> FMSTRRETTYPE GetFmtStr< short > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hd"; }
+template <> FMSTRRETTYPE GetFmtStr< ushort > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%hu"; }
+template <> FMSTRRETTYPE GetFmtStr< int > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%d"; }
+template <> FMSTRRETTYPE GetFmtStr< uint > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 || nRadix == 16 ); return nRadix == 16 ? "%x" : "%u"; }
+template <> FMSTRRETTYPE GetFmtStr< int64 > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%lld"; }
+template <> FMSTRRETTYPE GetFmtStr< float > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return "%f"; }
+template <> FMSTRRETTYPE GetFmtStr< double > ( int nRadix, bool bPrint ) { Assert( nRadix == 10 ); return bPrint ? "%.15lf" : "%lf"; } // force Printf to print DBL_DIG=15 digits of precision for doubles - defaults to FLT_DIG=6
+
+
+//-----------------------------------------------------------------------------
+// Command parsing..
+//-----------------------------------------------------------------------------
+class CUtlBuffer
+{
+// Brian has on his todo list to revisit this as there are issues in some cases with CUtlVector using operator = instead of copy construtor in InsertMultiple, etc.
+// The unsafe case is something like this:
+// CUtlVector< CUtlBuffer > vecFoo;
+//
+// CUtlBuffer buf;
+// buf.Put( xxx );
+// vecFoo.Insert( buf );
+//
+// This will cause memory corruption when vecFoo is cleared
+//
+//private:
+// // Disallow copying
+// CUtlBuffer( const CUtlBuffer & );// { Assert( 0 ); }
+// CUtlBuffer &operator=( const CUtlBuffer & );// { Assert( 0 ); return *this; }
+
+public:
+ enum SeekType_t
+ {
+ SEEK_HEAD = 0,
+ SEEK_CURRENT,
+ SEEK_TAIL
+ };
+
+ // flags
+ enum BufferFlags_t
+ {
+ TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary)
+ EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
+ CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r?
+ READ_ONLY = 0x8, // For external buffers; prevents null termination from happening.
+ AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs
+ };
+
+ // Overflow functions when a get or put overflows
+ typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize );
+
+ // Constructors for growable + external buffers for serialization/unserialization
+ CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
+ CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 );
+ // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
+ CUtlBuffer( const void *pBuffer, int size, bool crap );
+
+ unsigned char GetFlags() const;
+
+ // NOTE: This will assert if you attempt to recast it in a way that
+ // is not compatible. The only valid conversion is binary-> text w/CRLF
+ void SetBufferType( bool bIsText, bool bContainsCRLF );
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num );
+
+ // Access for direct read into buffer
+ void * AccessForDirectRead( int nBytes );
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
+ bool IsExternallyAllocated() const;
+ void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 );
+ void *Detach();
+ void* DetachMemory();
+
+ FORCEINLINE void ActivateByteSwappingIfBigEndian( void )
+ {
+ if ( ( IsX360() || IsPS3() ) )
+ ActivateByteSwapping( true );
+ }
+
+
+ // Controls endian-ness of binary utlbufs - default matches the current platform
+ void ActivateByteSwapping( bool bActivate );
+ void SetBigEndian( bool bigEndian );
+ bool IsBigEndian( void );
+
+ // Resets the buffer; but doesn't free memory
+ void Clear();
+
+ // Clears out the buffer; frees memory
+ void Purge();
+
+ // Dump the buffer to stdout
+ void Spew( );
+
+ // Read stuff out.
+ // Binary mode: it'll just read the bits directly in, and characters will be
+ // read for strings until a null character is reached.
+ // Text mode: it'll parse the file, turning text #s into real numbers.
+ // GetString will read a string until a space is reached
+ char GetChar( );
+ unsigned char GetUnsignedChar( );
+ short GetShort( );
+ unsigned short GetUnsignedShort( );
+ int GetInt( );
+ int64 GetInt64( );
+ unsigned int GetIntHex( );
+ unsigned int GetUnsignedInt( );
+ float GetFloat( );
+ double GetDouble( );
+ void * GetPtr();
+ void GetString( char* pString, int nMaxChars = 0 );
+ void Get( void* pMem, int size );
+ void GetLine( char* pLine, int nMaxChars = 0 );
+
+ // Used for getting objects that have a byteswap datadesc defined
+ template <typename T> void GetObjects( T *dest, int count = 1 );
+
+ // This will get at least 1 byte and up to nSize bytes.
+ // It will return the number of bytes actually read.
+ int GetUpTo( void *pMem, int nSize );
+
+ // This version of GetString converts \" to \\ and " to \, etc.
+ // It also reads a " at the beginning and end of the string
+ void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 );
+ char GetDelimitedChar( CUtlCharConversion *pConv );
+
+ // This will return the # of characters of the string about to be read out
+ // NOTE: The count will *include* the terminating 0!!
+ // In binary mode, it's the number of characters until the next 0
+ // In text mode, it's the number of characters until the next space.
+ int PeekStringLength();
+
+ // This version of PeekStringLength converts \" to \\ and " to \, etc.
+ // It also reads a " at the beginning and end of the string
+ // NOTE: The count will *include* the terminating 0!!
+ // In binary mode, it's the number of characters until the next 0
+ // In text mode, it's the number of characters between "s (checking for \")
+ // Specifying false for bActualSize will return the pre-translated number of characters
+ // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false
+ // and only 1 character when bActualSize == true
+ int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true );
+
+ // Just like scanf, but doesn't work in binary mode
+ int Scanf( const char* pFmt, ... );
+ int VaScanf( const char* pFmt, va_list list );
+
+ // Eats white space, advances Get index
+ void EatWhiteSpace();
+
+ // Eats C++ style comments
+ bool EatCPPComment();
+
+ // (For text buffers only)
+ // Parse a token from the buffer:
+ // Grab all text that lies between a starting delimiter + ending delimiter
+ // (skipping whitespace that leads + trails both delimiters).
+ // If successful, the get index is advanced and the function returns true,
+ // otherwise the index is not advanced and the function returns false.
+ bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen );
+
+ // Advance the get index until after the particular string is found
+ // Do not eat whitespace before starting. Return false if it failed
+ // String test is case-insensitive.
+ bool GetToken( const char *pToken );
+
+ // Parses the next token, given a set of character breaks to stop at
+ // Returns the length of the token parsed in bytes (-1 if none parsed)
+ int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true );
+
+ // Write stuff in
+ // Binary mode: it'll just write the bits directly in, and strings will be
+ // written with a null terminating character
+ // Text mode: it'll convert the numbers to text versions
+ // PutString will not write a terminating character
+ void PutChar( char c );
+ void PutUnsignedChar( unsigned char uc );
+ void PutShort( short s );
+ void PutUnsignedShort( unsigned short us );
+ void PutInt( int i );
+ void PutInt64( int64 i );
+ void PutUnsignedInt( unsigned int u );
+ void PutFloat( float f );
+ void PutDouble( double d );
+ void PutPtr( void * ); // Writes the pointer, not the pointed to
+ void PutString( const char* pString );
+ void Put( const void* pMem, int size );
+
+ // Used for putting objects that have a byteswap datadesc defined
+ template <typename T> void PutObjects( T *src, int count = 1 );
+
+ // This version of PutString converts \ to \\ and " to \", etc.
+ // It also places " at the beginning and end of the string
+ void PutDelimitedString( CUtlCharConversion *pConv, const char *pString );
+ void PutDelimitedChar( CUtlCharConversion *pConv, char c );
+
+ // Just like printf, writes a terminating zero in binary mode
+ void Printf( const char* pFmt, ... ) FMTFUNCTION( 2, 3 );
+ void VaPrintf( const char* pFmt, va_list list );
+
+ // What am I writing (put)/reading (get)?
+ void* PeekPut( int offset = 0 );
+ const void* PeekGet( int offset = 0 ) const;
+ const void* PeekGet( int nMaxSize, int nOffset );
+
+ // Where am I writing (put)/reading (get)?
+ int TellPut( ) const;
+ int TellGet( ) const;
+
+ // What's the most I've ever written?
+ int TellMaxPut( ) const;
+
+ // How many bytes remain to be read?
+ // NOTE: This is not accurate for streaming text files; it overshoots
+ int GetBytesRemaining() const;
+
+ // Change where I'm writing (put)/reading (get)
+ void SeekPut( SeekType_t type, int offset );
+ void SeekGet( SeekType_t type, int offset );
+
+ // Buffer base
+ const void* Base() const;
+ void* Base();
+
+ // memory allocation size, does *not* reflect size written or read,
+ // use TellPut or TellGet for that
+ int Size() const;
+
+ // Am I a text buffer?
+ bool IsText() const;
+
+ // Can I grow if I'm externally allocated?
+ bool IsGrowable() const;
+
+ // Am I valid? (overflow or underflow error), Once invalid it stays invalid
+ bool IsValid() const;
+
+ // Do I contain carriage return/linefeeds?
+ bool ContainsCRLF() const;
+
+ // Am I read-only
+ bool IsReadOnly() const;
+
+ // Converts a buffer from a CRLF buffer to a CR buffer (and back)
+ // Returns false if no conversion was necessary (and outBuf is left untouched)
+ // If the conversion occurs, outBuf will be cleared.
+ bool ConvertCRLF( CUtlBuffer &outBuf );
+
+ // Push/pop pretty-printing tabs
+ void PushTab();
+ void PopTab();
+
+ // Temporarily disables pretty print
+ void EnableTabs( bool bEnable );
+
+#if !defined( _GAMECONSOLE )
+ // Swap my internal memory with another buffer,
+ // and copy all of its other members
+ void SwapCopy( CUtlBuffer &other ) ;
+#endif
+
+protected:
+ // error flags
+ enum
+ {
+ PUT_OVERFLOW = 0x1,
+ GET_OVERFLOW = 0x2,
+ MAX_ERROR_FLAG = GET_OVERFLOW,
+ };
+
+ void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc );
+
+ bool OnPutOverflow( int nSize );
+ bool OnGetOverflow( int nSize );
+
+protected:
+ // Checks if a get/put is ok
+ bool CheckPut( int size );
+ bool CheckGet( int size );
+
+ // NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
+ // after modifying m_Put and this lets it stay in a register
+ void AddNullTermination( int nPut );
+
+ // Methods to help with pretty-printing
+ bool WasLastCharacterCR();
+ void PutTabs();
+
+ // Help with delimited stuff
+ char GetDelimitedCharInternal( CUtlCharConversion *pConv );
+ void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c );
+
+ // Default overflow funcs
+ bool PutOverflow( int nSize );
+ bool GetOverflow( int nSize );
+
+ // Does the next bytes of the buffer match a pattern?
+ bool PeekStringMatch( int nOffset, const char *pString, int nLen );
+
+ // Peek size of line to come, check memory bound
+ int PeekLineLength();
+
+ // How much whitespace should I skip?
+ int PeekWhiteSpace( int nOffset );
+
+ // Checks if a peek get is ok
+ bool CheckPeekGet( int nOffset, int nSize );
+
+ // Call this to peek arbitrarily long into memory. It doesn't fail unless
+ // it can't read *anything* new
+ bool CheckArbitraryPeekGet( int nOffset, int &nIncrement );
+
+ template <typename T> void GetType( T& dest );
+ template <typename T> void GetTypeBin( T& dest );
+ template <typename T> bool GetTypeText( T &value, int nRadix = 10 );
+ template <typename T> void GetObject( T *src );
+
+ template <typename T> void PutType( T src );
+ template <typename T> void PutTypeBin( T src );
+ template <typename T> void PutObject( T *src );
+
+ // be sure to also update the copy constructor
+ // and SwapCopy() when adding members.
+ CUtlMemory<unsigned char> m_Memory;
+ int m_Get;
+ int m_Put;
+
+ unsigned char m_Error;
+ unsigned char m_Flags;
+ unsigned char m_Reserved;
+#if defined( _GAMECONSOLE )
+ unsigned char pad;
+#endif
+
+ int m_nTab;
+ int m_nMaxPut;
+ int m_nOffset;
+
+ UtlBufferOverflowFunc_t m_GetOverflowFunc;
+ UtlBufferOverflowFunc_t m_PutOverflowFunc;
+
+ CByteswap m_Byteswap;
+};
+
+
+// Stream style output operators for CUtlBuffer
+inline CUtlBuffer &operator<<( CUtlBuffer &b, char v )
+{
+ b.PutChar( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned char v )
+{
+ b.PutUnsignedChar( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, short v )
+{
+ b.PutShort( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned short v )
+{
+ b.PutUnsignedShort( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, int v )
+{
+ b.PutInt( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned int v )
+{
+ b.PutUnsignedInt( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, float v )
+{
+ b.PutFloat( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, double v )
+{
+ b.PutDouble( v );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, const char *pv )
+{
+ b.PutString( pv );
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector &v )
+{
+ b << v.x << " " << v.y << " " << v.z;
+ return b;
+}
+
+inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector2D &v )
+{
+ b << v.x << " " << v.y;
+ return b;
+}
+
+
+class CUtlInplaceBuffer : public CUtlBuffer
+{
+public:
+ CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 );
+
+ //
+ // Routines returning buffer-inplace-pointers
+ //
+public:
+ //
+ // Upon success, determines the line length, fills out the pointer to the
+ // beginning of the line and the line length, advances the "get" pointer
+ // offset by the line length and returns "true".
+ //
+ // If end of file is reached or upon error returns "false".
+ //
+ // Note: the returned length of the line is at least one character because the
+ // trailing newline characters are also included as part of the line.
+ //
+ // Note: the pointer returned points into the local memory of this buffer, in
+ // case the buffer gets relocated or destroyed the pointer becomes invalid.
+ //
+ // e.g.: -------------
+ //
+ // char *pszLine;
+ // int nLineLen;
+ // while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) )
+ // {
+ // ...
+ // }
+ //
+ // -------------
+ //
+ // @param ppszInBufferPtr on return points into this buffer at start of line
+ // @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr)
+ //
+ // @returns true if line was successfully read
+ // false when EOF is reached or error occurs
+ //
+ bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength );
+
+ //
+ // Determines the line length, advances the "get" pointer offset by the line length,
+ // replaces the newline character with null-terminator and returns the initial pointer
+ // to now null-terminated line.
+ //
+ // If end of file is reached or upon error returns NULL.
+ //
+ // Note: the pointer returned points into the local memory of this buffer, in
+ // case the buffer gets relocated or destroyed the pointer becomes invalid.
+ //
+ // e.g.: -------------
+ //
+ // while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() )
+ // {
+ // ...
+ // }
+ //
+ // -------------
+ //
+ // @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified
+ // NULL when EOF is reached or error occurs
+ //
+ char * InplaceGetLinePtr( void );
+};
+
+
+//-----------------------------------------------------------------------------
+// Where am I reading?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::TellGet( ) const
+{
+ return m_Get;
+}
+
+
+//-----------------------------------------------------------------------------
+// How many bytes remain to be read?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::GetBytesRemaining() const
+{
+ return m_nMaxPut - TellGet();
+}
+
+
+//-----------------------------------------------------------------------------
+// What am I reading?
+//-----------------------------------------------------------------------------
+inline const void* CUtlBuffer::PeekGet( int offset ) const
+{
+ return &m_Memory[ m_Get + offset - m_nOffset ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Unserialization
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline void CUtlBuffer::GetObject( T *dest )
+{
+ if ( CheckGet( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ *dest = *(T *)PeekGet();
+ }
+ else
+ {
+ m_Byteswap.SwapFieldsToTargetEndian<T>( dest, (T*)PeekGet() );
+ }
+ m_Get += sizeof(T);
+ }
+ else
+ {
+ V_memset( &dest, 0, sizeof(T) );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::GetObjects( T *dest, int count )
+{
+ for ( int i = 0; i < count; ++i, ++dest )
+ {
+ GetObject<T>( dest );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::GetTypeBin( T &dest )
+{
+ if ( CheckGet( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ dest = *(T *)PeekGet();
+ }
+ else
+ {
+ m_Byteswap.SwapBufferToTargetEndian<T>( &dest, (T*)PeekGet() );
+ }
+ m_Get += sizeof(T);
+ }
+ else
+ {
+ dest = 0;
+ }
+}
+
+template <>
+inline void CUtlBuffer::GetTypeBin< float >( float &dest )
+{
+ if ( CheckGet( sizeof( float ) ) )
+ {
+ uintp pData = (uintp)PeekGet();
+ if ( ( IsX360() || IsPS3() ) && ( pData & 0x03 ) )
+ {
+ // handle unaligned read
+ ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
+ ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
+ ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
+ ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
+ }
+ else
+ {
+ // aligned read
+ dest = *(float *)pData;
+ }
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest );
+ }
+ m_Get += sizeof( float );
+ }
+ else
+ {
+ dest = 0;
+ }
+}
+
+template <>
+inline void CUtlBuffer::GetTypeBin< double >( double &dest )
+{
+ if ( CheckGet( sizeof( double ) ) )
+ {
+ uintp pData = (uintp)PeekGet();
+ if ( ( IsX360() || IsPS3() ) && ( pData & 0x07 ) )
+ {
+ // handle unaligned read
+ ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0];
+ ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1];
+ ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2];
+ ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3];
+ ((unsigned char*)&dest)[4] = ((unsigned char*)pData)[4];
+ ((unsigned char*)&dest)[5] = ((unsigned char*)pData)[5];
+ ((unsigned char*)&dest)[6] = ((unsigned char*)pData)[6];
+ ((unsigned char*)&dest)[7] = ((unsigned char*)pData)[7];
+ }
+ else
+ {
+ // aligned read
+ dest = *(double *)pData;
+ }
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian< double >( &dest, &dest );
+ }
+ m_Get += sizeof( double );
+ }
+ else
+ {
+ dest = 0;
+ }
+}
+
+template < class T >
+inline T StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ Assert( 0 );
+ *ppEnd = pString;
+ return 0;
+}
+
+template <>
+inline int8 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( int8 )strtol( pString, ppEnd, nRadix );
+}
+
+template <>
+inline uint8 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( uint8 )strtoul( pString, ppEnd, nRadix );
+}
+
+template <>
+inline int16 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( int16 )strtol( pString, ppEnd, nRadix );
+}
+
+template <>
+inline uint16 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( uint16 )strtoul( pString, ppEnd, nRadix );
+}
+
+template <>
+inline int32 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( int32 )strtol( pString, ppEnd, nRadix );
+}
+
+template <>
+inline uint32 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ return ( uint32 )strtoul( pString, ppEnd, nRadix );
+}
+
+template <>
+inline int64 StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+#if defined(_PS3) || defined(POSIX)
+ return ( int64 )strtoll( pString, ppEnd, nRadix );
+#else // !_PS3
+ return ( int64 )_strtoi64( pString, ppEnd, nRadix );
+#endif // _PS3
+}
+
+template <>
+inline float StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ NOTE_UNUSED( nRadix );
+ return ( float )strtod( pString, ppEnd );
+}
+
+template <>
+inline double StringToNumber( char *pString, char **ppEnd, int nRadix )
+{
+ NOTE_UNUSED( nRadix );
+ return ( double )strtod( pString, ppEnd );
+}
+
+template <typename T>
+inline bool CUtlBuffer::GetTypeText( T &value, int nRadix /*= 10*/ )
+{
+ // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
+ int nLength = 128;
+ if ( !CheckArbitraryPeekGet( 0, nLength ) )
+ {
+ value = 0;
+ return false;
+ }
+
+ char *pStart = (char*)PeekGet();
+ char* pEnd = pStart;
+ value = StringToNumber< T >( pStart, &pEnd, nRadix );
+
+ int nBytesRead = (int)( pEnd - pStart );
+ if ( nBytesRead == 0 )
+ return false;
+
+ m_Get += nBytesRead;
+ return true;
+}
+
+template <typename T>
+inline void CUtlBuffer::GetType( T &dest )
+{
+ if (!IsText())
+ {
+ GetTypeBin( dest );
+ }
+ else
+ {
+ GetTypeText( dest );
+ }
+}
+
+inline char CUtlBuffer::GetChar( )
+{
+ // LEGACY WARNING: this behaves differently than GetUnsignedChar()
+ char c;
+ GetTypeBin( c ); // always reads as binary
+ return c;
+}
+
+inline unsigned char CUtlBuffer::GetUnsignedChar( )
+{
+ // LEGACY WARNING: this behaves differently than GetChar()
+ unsigned char c;
+ if (!IsText())
+ {
+ GetTypeBin( c );
+ }
+ else
+ {
+ c = ( unsigned char )GetUnsignedShort();
+ }
+ return c;
+}
+
+inline short CUtlBuffer::GetShort( )
+{
+ short s;
+ GetType( s );
+ return s;
+}
+
+inline unsigned short CUtlBuffer::GetUnsignedShort( )
+{
+ unsigned short s;
+ GetType( s );
+ return s;
+}
+
+inline int CUtlBuffer::GetInt( )
+{
+ int i;
+ GetType( i );
+ return i;
+}
+
+inline int64 CUtlBuffer::GetInt64( )
+{
+ int64 i;
+ GetType( i );
+ return i;
+}
+
+inline unsigned int CUtlBuffer::GetIntHex( )
+{
+ uint i;
+ if (!IsText())
+ {
+ GetTypeBin( i );
+ }
+ else
+ {
+ GetTypeText( i, 16 );
+ }
+ return i;
+}
+
+inline unsigned int CUtlBuffer::GetUnsignedInt( )
+{
+ unsigned int i;
+ GetType( i );
+ return i;
+}
+
+inline float CUtlBuffer::GetFloat( )
+{
+ float f;
+ GetType( f );
+ return f;
+}
+
+inline double CUtlBuffer::GetDouble( )
+{
+ double d;
+ GetType( d );
+ return d;
+}
+
+inline void *CUtlBuffer::GetPtr( )
+{
+ void *p;
+ // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
+#ifndef X64BITS
+ p = ( void* )GetUnsignedInt();
+#else
+ p = ( void* )GetInt64();
+#endif
+ return p;
+}
+
+//-----------------------------------------------------------------------------
+// Where am I writing?
+//-----------------------------------------------------------------------------
+inline unsigned char CUtlBuffer::GetFlags() const
+{
+ return m_Flags;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsExternallyAllocated() const
+{
+ return m_Memory.IsExternallyAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Where am I writing?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::TellPut( ) const
+{
+ return m_Put;
+}
+
+
+//-----------------------------------------------------------------------------
+// What's the most I've ever written?
+//-----------------------------------------------------------------------------
+inline int CUtlBuffer::TellMaxPut( ) const
+{
+ return m_nMaxPut;
+}
+
+
+//-----------------------------------------------------------------------------
+// What am I reading?
+//-----------------------------------------------------------------------------
+inline void* CUtlBuffer::PeekPut( int offset )
+{
+ return &m_Memory[m_Put + offset - m_nOffset];
+}
+
+
+//-----------------------------------------------------------------------------
+// Various put methods
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline void CUtlBuffer::PutObject( T *src )
+{
+ if ( CheckPut( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ *(T *)PeekPut() = *src;
+ }
+ else
+ {
+ m_Byteswap.SwapFieldsToTargetEndian<T>( (T*)PeekPut(), src );
+ }
+ m_Put += sizeof(T);
+ AddNullTermination( m_Put );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::PutObjects( T *src, int count )
+{
+ for ( int i = 0; i < count; ++i, ++src )
+ {
+ PutObject<T>( src );
+ }
+}
+
+
+template <typename T>
+inline void CUtlBuffer::PutTypeBin( T src )
+{
+ if ( CheckPut( sizeof(T) ) )
+ {
+ if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) )
+ {
+ *(T *)PeekPut() = src;
+ }
+ else
+ {
+ m_Byteswap.SwapBufferToTargetEndian<T>( (T*)PeekPut(), &src );
+ }
+ m_Put += sizeof(T);
+ AddNullTermination( m_Put );
+ }
+}
+
+#if defined( _GAMECONSOLE )
+template <>
+inline void CUtlBuffer::PutTypeBin< float >( float src )
+{
+ if ( CheckPut( sizeof( src ) ) )
+ {
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian<float>( &src, &src );
+ }
+
+ //
+ // Write the data
+ //
+ unsigned pData = (unsigned)PeekPut();
+ if ( pData & 0x03 )
+ {
+ // handle unaligned write
+ byte* dst = (byte*)pData;
+ byte* srcPtr = (byte*)&src;
+ dst[0] = srcPtr[0];
+ dst[1] = srcPtr[1];
+ dst[2] = srcPtr[2];
+ dst[3] = srcPtr[3];
+ }
+ else
+ {
+ *(float *)pData = src;
+ }
+
+ m_Put += sizeof(float);
+ AddNullTermination( m_Put );
+ }
+}
+
+template <>
+inline void CUtlBuffer::PutTypeBin< double >( double src )
+{
+ if ( CheckPut( sizeof( src ) ) )
+ {
+ if ( m_Byteswap.IsSwappingBytes() )
+ {
+ m_Byteswap.SwapBufferToTargetEndian<double>( &src, &src );
+ }
+
+ //
+ // Write the data
+ //
+ unsigned pData = (unsigned)PeekPut();
+ if ( pData & 0x07 )
+ {
+ // handle unaligned write
+ byte* dst = (byte*)pData;
+ byte* srcPtr = (byte*)&src;
+ dst[0] = srcPtr[0];
+ dst[1] = srcPtr[1];
+ dst[2] = srcPtr[2];
+ dst[3] = srcPtr[3];
+ dst[4] = srcPtr[4];
+ dst[5] = srcPtr[5];
+ dst[6] = srcPtr[6];
+ dst[7] = srcPtr[7];
+ }
+ else
+ {
+ *(double *)pData = src;
+ }
+
+ m_Put += sizeof(double);
+ AddNullTermination( m_Put );
+ }
+}
+#endif
+
+template <typename T>
+inline void CUtlBuffer::PutType( T src )
+{
+ if (!IsText())
+ {
+ PutTypeBin( src );
+ }
+ else
+ {
+ Printf( GetFmtStr< T >(), src );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Methods to help with pretty-printing
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::WasLastCharacterCR()
+{
+ if ( !IsText() || (TellPut() == 0) )
+ return false;
+ return ( *( const char * )PeekPut( -1 ) == '\n' );
+}
+
+inline void CUtlBuffer::PutTabs()
+{
+ int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab;
+ for (int i = nTabCount; --i >= 0; )
+ {
+ PutTypeBin<char>( '\t' );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Push/pop pretty-printing tabs
+//-----------------------------------------------------------------------------
+inline void CUtlBuffer::PushTab( )
+{
+ ++m_nTab;
+}
+
+inline void CUtlBuffer::PopTab()
+{
+ if ( --m_nTab < 0 )
+ {
+ m_nTab = 0;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Temporarily disables pretty print
+//-----------------------------------------------------------------------------
+inline void CUtlBuffer::EnableTabs( bool bEnable )
+{
+ if ( bEnable )
+ {
+ m_Flags &= ~AUTO_TABS_DISABLED;
+ }
+ else
+ {
+ m_Flags |= AUTO_TABS_DISABLED;
+ }
+}
+
+inline void CUtlBuffer::PutChar( char c )
+{
+ if ( WasLastCharacterCR() )
+ {
+ PutTabs();
+ }
+
+ PutTypeBin( c );
+}
+
+inline void CUtlBuffer::PutUnsignedChar( unsigned char c )
+{
+ if (!IsText())
+ {
+ PutTypeBin( c );
+ }
+ else
+ {
+ PutUnsignedShort( c );
+ }
+}
+
+inline void CUtlBuffer::PutShort( short s )
+{
+ PutType( s );
+}
+
+inline void CUtlBuffer::PutUnsignedShort( unsigned short s )
+{
+ PutType( s );
+}
+
+inline void CUtlBuffer::PutInt( int i )
+{
+ PutType( i );
+}
+
+inline void CUtlBuffer::PutInt64( int64 i )
+{
+ PutType( i );
+}
+
+inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
+{
+ PutType( u );
+}
+
+inline void CUtlBuffer::PutFloat( float f )
+{
+ PutType( f );
+}
+
+inline void CUtlBuffer::PutDouble( double d )
+{
+ PutType( d );
+}
+
+inline void CUtlBuffer::PutPtr( void *p )
+{
+ // LEGACY WARNING: in text mode, PutPtr writes 32 bit pointers in hex, while GetPtr reads 32 or 64 bit pointers in decimal
+ if (!IsText())
+ {
+ PutTypeBin( p );
+ }
+ else
+ {
+ Printf( "0x%p", p );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Am I a text buffer?
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsText() const
+{
+ return (m_Flags & TEXT_BUFFER) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Can I grow if I'm externally allocated?
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsGrowable() const
+{
+ return (m_Flags & EXTERNAL_GROWABLE) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Am I valid? (overflow or underflow error), Once invalid it stays invalid
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsValid() const
+{
+ return m_Error == 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Do I contain carriage return/linefeeds?
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::ContainsCRLF() const
+{
+ return IsText() && ((m_Flags & CONTAINS_CRLF) != 0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Am I read-only
+//-----------------------------------------------------------------------------
+inline bool CUtlBuffer::IsReadOnly() const
+{
+ return (m_Flags & READ_ONLY) != 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Buffer base and size
+//-----------------------------------------------------------------------------
+inline const void* CUtlBuffer::Base() const
+{
+ return m_Memory.Base();
+}
+
+inline void* CUtlBuffer::Base()
+{
+ return m_Memory.Base();
+}
+
+inline int CUtlBuffer::Size() const
+{
+ return m_Memory.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Clears out the buffer; frees memory
+//-----------------------------------------------------------------------------
+inline void CUtlBuffer::Clear()
+{
+ m_Get = 0;
+ m_Put = 0;
+ m_Error = 0;
+ m_nOffset = 0;
+ m_nMaxPut = -1;
+ AddNullTermination( m_Put );
+}
+
+inline void CUtlBuffer::Purge()
+{
+ m_Get = 0;
+ m_Put = 0;
+ m_nOffset = 0;
+ m_nMaxPut = 0;
+ m_Error = 0;
+ m_Memory.Purge();
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+inline void *CUtlBuffer::AccessForDirectRead( int nBytes )
+{
+ Assert( m_Get == 0 && m_Put == 0 && m_nMaxPut == 0 );
+ EnsureCapacity( nBytes );
+ m_nMaxPut = nBytes;
+ return Base();
+}
+
+inline void *CUtlBuffer::Detach()
+{
+ void *p = m_Memory.Detach();
+ Clear();
+ return p;
+}
+
+//-----------------------------------------------------------------------------
+
+inline void CUtlBuffer::Spew( )
+{
+ SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
+
+ char pTmpLine[1024];
+ while( IsValid() && GetBytesRemaining() )
+ {
+ V_memset( pTmpLine, 0, sizeof(pTmpLine) );
+ Get( pTmpLine, MIN( ( size_t )GetBytesRemaining(), sizeof(pTmpLine)-1 ) );
+ Msg( _T( "%s" ), pTmpLine );
+ }
+}
+
+#if !defined(_GAMECONSOLE)
+inline void CUtlBuffer::SwapCopy( CUtlBuffer &other )
+{
+ m_Get = other.m_Get;
+ m_Put = other.m_Put;
+ m_Error = other.m_Error;
+ m_Flags = other.m_Flags;
+ m_Reserved = other.m_Reserved;
+ m_nTab = other.m_nTab;
+ m_nMaxPut = other.m_nMaxPut;
+ m_nOffset = other.m_nOffset;
+ m_GetOverflowFunc = other.m_GetOverflowFunc;
+ m_PutOverflowFunc = other.m_PutOverflowFunc;
+ m_Byteswap = other.m_Byteswap;
+
+ m_Memory.Swap( other.m_Memory );
+}
+#endif
+
+#endif // UTLBUFFER_H
+
diff --git a/external/vpc/public/tier1/utldict.h b/external/vpc/public/tier1/utldict.h
new file mode 100644
index 0000000..cb6d4f1
--- /dev/null
+++ b/external/vpc/public/tier1/utldict.h
@@ -0,0 +1,338 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose: A dictionary mapping from symbol to structure
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLDICT_H
+#define UTLDICT_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "tier1/utlmap.h"
+
+// Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h
+#include "tier1/utlsymbol.h"
+
+#include "tier0/memdbgon.h"
+
+enum EDictCompareType
+{
+ k_eDictCompareTypeCaseSensitive=0,
+ k_eDictCompareTypeCaseInsensitive=1,
+ k_eDictCompareTypeFilenames // Slashes and backslashes count as the same character..
+};
+
+
+//-----------------------------------------------------------------------------
+// A dictionary mapping from symbol to structure
+//-----------------------------------------------------------------------------
+#define FOR_EACH_DICT( dictName, iteratorName ) \
+ for( int iteratorName=dictName.First(); iteratorName != dictName.InvalidIndex(); iteratorName = dictName.Next( iteratorName ) )
+
+// faster iteration, but in an unspecified order
+#define FOR_EACH_DICT_FAST( dictName, iteratorName ) \
+ for ( int iteratorName = 0; iteratorName < dictName.MaxElement(); ++iteratorName ) if ( !dictName.IsValidIndex( iteratorName ) ) continue; else
+
+
+//-----------------------------------------------------------------------------
+// A dictionary mapping from symbol to structure
+//-----------------------------------------------------------------------------
+template <class T, class I = int >
+class CUtlDict
+{
+public:
+ // constructor, destructor
+ // Left at growSize = 0, the memory will first allocate 1 element and double in size
+ // at each increment.
+ CUtlDict( int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0 );
+ ~CUtlDict( );
+
+ void EnsureCapacity( int );
+
+ // gets particular elements
+ T& Element( I i );
+ const T& Element( I i ) const;
+ T& operator[]( I i );
+ const T& operator[]( I i ) const;
+
+ // gets element names
+ char *GetElementName( I i );
+ char const *GetElementName( I i ) const;
+
+ void SetElementName( I i, char const *pName );
+
+ // Number of elements
+ unsigned int Count() const;
+
+ // Checks if a node is valid and in the tree
+ bool IsValidIndex( I i ) const;
+
+ // Invalid index
+ static I InvalidIndex();
+
+ // Insert method (inserts in order)
+ I Insert( const char *pName, const T &element );
+ I Insert( const char *pName );
+
+ // Find method
+ I Find( const char *pName ) const;
+
+ // Remove methods
+ void RemoveAt( I i );
+ void Remove( const char *pName );
+ void RemoveAll( );
+
+ // Purge memory
+ void Purge();
+ void PurgeAndDeleteElements(); // Call delete on each element.
+
+ // Iteration methods
+ I First() const;
+ I Next( I i ) const;
+
+ // Nested typedefs, for code that might need
+ // to fish out the index type from a given dict
+ typedef I IndexType_t;
+
+protected:
+ typedef CUtlMap<const char *, T, I> DictElementMap_t;
+ DictElementMap_t m_Elements;
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template <class T, class I>
+CUtlDict<T, I>::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize )
+{
+ if ( compareType == k_eDictCompareTypeFilenames )
+ {
+ m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes );
+ }
+ else if ( compareType == k_eDictCompareTypeCaseInsensitive )
+ {
+ m_Elements.SetLessFunc( CaselessStringLessThan );
+ }
+ else
+ {
+ m_Elements.SetLessFunc( StringLessThan );
+ }
+}
+
+template <class T, class I>
+CUtlDict<T, I>::~CUtlDict()
+{
+ Purge();
+}
+
+template <class T, class I>
+inline void CUtlDict<T, I>::EnsureCapacity( int num )
+{
+ return m_Elements.EnsureCapacity( num );
+}
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline T& CUtlDict<T, I>::Element( I i )
+{
+ return m_Elements[i];
+}
+
+template <class T, class I>
+inline const T& CUtlDict<T, I>::Element( I i ) const
+{
+ return m_Elements[i];
+}
+
+//-----------------------------------------------------------------------------
+// gets element names
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline char *CUtlDict<T, I>::GetElementName( I i )
+{
+ return (char *)m_Elements.Key( i );
+}
+
+template <class T, class I>
+inline char const *CUtlDict<T, I>::GetElementName( I i ) const
+{
+ return m_Elements.Key( i );
+}
+
+template <class T, class I>
+inline T& CUtlDict<T, I>::operator[]( I i )
+{
+ return Element(i);
+}
+
+template <class T, class I>
+inline const T & CUtlDict<T, I>::operator[]( I i ) const
+{
+ return Element(i);
+}
+
+template <class T, class I>
+inline void CUtlDict<T, I>::SetElementName( I i, char const *pName )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ // TODO: This makes a copy of the old element
+ // TODO: This relies on the rb tree putting the most recently
+ // removed element at the head of the insert list
+ free( (void *)m_Elements.Key( i ) );
+ m_Elements.Reinsert( strdup( pName ), i );
+}
+
+//-----------------------------------------------------------------------------
+// Num elements
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline unsigned int CUtlDict<T, I>::Count() const
+{
+ return m_Elements.Count();
+}
+
+
+//-----------------------------------------------------------------------------
+// Checks if a node is valid and in the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline bool CUtlDict<T, I>::IsValidIndex( I i ) const
+{
+ return m_Elements.IsValidIndex(i);
+}
+
+
+//-----------------------------------------------------------------------------
+// Invalid index
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline I CUtlDict<T, I>::InvalidIndex()
+{
+ return DictElementMap_t::InvalidIndex();
+}
+
+
+//-----------------------------------------------------------------------------
+// Delete a node from the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlDict<T, I>::RemoveAt(I elem)
+{
+ free( (void *)m_Elements.Key( elem ) );
+ m_Elements.RemoveAt(elem);
+}
+
+
+//-----------------------------------------------------------------------------
+// remove a node in the tree
+//-----------------------------------------------------------------------------
+template <class T, class I> void CUtlDict<T, I>::Remove( const char *search )
+{
+ I node = Find( search );
+ if (node != InvalidIndex())
+ {
+ RemoveAt(node);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlDict<T, I>::RemoveAll()
+{
+ typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder();
+ while ( index != m_Elements.InvalidIndex() )
+ {
+ const char *pKey = m_Elements.Key( index );
+ free( const_cast<char*>(pKey) );
+ index = m_Elements.NextInorder( index );
+ }
+
+ m_Elements.RemoveAll();
+}
+
+template <class T, class I>
+void CUtlDict<T, I>::Purge()
+{
+ RemoveAll();
+}
+
+
+template <class T, class I>
+void CUtlDict<T, I>::PurgeAndDeleteElements()
+{
+ // Delete all the elements.
+ I index = m_Elements.FirstInorder();
+ while ( index != m_Elements.InvalidIndex() )
+ {
+ const char* pKey = m_Elements.Key( index );
+ free( const_cast<char*>(pKey) );
+ delete m_Elements[index];
+ index = m_Elements.NextInorder( index );
+ }
+
+ m_Elements.RemoveAll();
+}
+
+
+//-----------------------------------------------------------------------------
+// inserts a node into the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlDict<T, I>::Insert( const char *pName, const T &element )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ return m_Elements.Insert( strdup( pName ), element );
+}
+
+template <class T, class I>
+I CUtlDict<T, I>::Insert( const char *pName )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ return m_Elements.Insert( strdup( pName ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// finds a node in the tree
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlDict<T, I>::Find( const char *pName ) const
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ if ( pName )
+ return m_Elements.Find( pName );
+ else
+ return InvalidIndex();
+}
+
+
+//-----------------------------------------------------------------------------
+// Iteration methods
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlDict<T, I>::First() const
+{
+ return m_Elements.FirstInorder();
+}
+
+template <class T, class I>
+I CUtlDict<T, I>::Next( I i ) const
+{
+ return m_Elements.NextInorder(i);
+}
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLDICT_H
diff --git a/external/vpc/public/tier1/utlenvelope.h b/external/vpc/public/tier1/utlenvelope.h
new file mode 100644
index 0000000..28e434b
--- /dev/null
+++ b/external/vpc/public/tier1/utlenvelope.h
@@ -0,0 +1,241 @@
+//========== Copyright � 2005, Valve Corporation, All rights reserved. ========
+//
+// Purpose: A class to wrap data for transport over a boundary like a thread
+// or window.
+//
+//=============================================================================
+
+#include "tier1/utlstring.h"
+#include "tier0/basetypes.h"
+
+#ifndef UTLENVELOPE_H
+#define UTLENVELOPE_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+//-----------------------------------------------------------------------------
+
+class CUtlDataEnvelope
+{
+public:
+ CUtlDataEnvelope( const void *pData, int nBytes );
+ CUtlDataEnvelope( const CUtlDataEnvelope &from );
+ ~CUtlDataEnvelope();
+
+ CUtlDataEnvelope &operator=( const CUtlDataEnvelope &from );
+
+ operator void *();
+ operator void *() const;
+
+private:
+ void Assign( const void *pData, int nBytes );
+ void Assign( const CUtlDataEnvelope &from );
+ void Purge();
+
+ // TODO: switch to a reference counted array?
+ union
+ {
+ byte *m_pData;
+ byte m_data[4];
+ };
+ int m_nBytes;
+};
+
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+class CUtlEnvelope : protected CUtlDataEnvelope
+{
+public:
+ CUtlEnvelope( const T *pData, int nElems = 1 );
+ CUtlEnvelope( const CUtlEnvelope<T> &from );
+
+ CUtlEnvelope<T> &operator=( const CUtlEnvelope<T> &from );
+
+ operator T *();
+ operator T *() const;
+
+ operator void *();
+ operator void *() const;
+};
+
+//-----------------------------------------------------------------------------
+
+template <>
+class CUtlEnvelope<const char *>
+{
+public:
+ CUtlEnvelope( const char *pData )
+ {
+ m_string = pData;
+ }
+
+ CUtlEnvelope( const CUtlEnvelope<const char *> &from )
+ {
+ m_string = from.m_string;
+ }
+
+ CUtlEnvelope<const char *> &operator=( const CUtlEnvelope<const char *> &from )
+ {
+ m_string = from.m_string;
+ return *this;
+ }
+
+ operator char *()
+ {
+ return (char *) m_string.Get();
+ }
+
+ operator char *() const
+ {
+ return (char *) m_string.Get();
+ }
+
+ operator void *()
+ {
+ return (void *) m_string.Get();
+ }
+
+ operator void *() const
+ {
+ return (void *) m_string.Get();
+ }
+
+private:
+ CUtlString m_string;
+};
+
+//-----------------------------------------------------------------------------
+
+#include "tier0/memdbgon.h"
+
+inline void CUtlDataEnvelope::Assign( const void *pData, int nBytes )
+{
+ if ( pData )
+ {
+ m_nBytes = nBytes;
+ if ( m_nBytes > 4 )
+ {
+ m_pData = new byte[nBytes];
+ memcpy( m_pData, pData, nBytes );
+ }
+ else
+ {
+ memcpy( m_data, pData, nBytes );
+ }
+ }
+ else
+ {
+ m_pData = NULL;
+ m_nBytes = 0;
+ }
+}
+
+inline void CUtlDataEnvelope::Assign( const CUtlDataEnvelope &from )
+{
+ Assign( from.operator void *(), from.m_nBytes );
+}
+
+inline void CUtlDataEnvelope::Purge()
+{
+ if (m_nBytes > 4)
+ delete [] m_pData;
+ m_nBytes = 0;
+}
+
+inline CUtlDataEnvelope::CUtlDataEnvelope( const void *pData, int nBytes )
+{
+ Assign( pData, nBytes );
+}
+
+inline CUtlDataEnvelope::CUtlDataEnvelope( const CUtlDataEnvelope &from )
+{
+ Assign( from );
+}
+
+inline CUtlDataEnvelope::~CUtlDataEnvelope()
+{
+ Purge();
+}
+
+inline CUtlDataEnvelope &CUtlDataEnvelope::operator=( const CUtlDataEnvelope &from )
+{
+ Purge();
+ Assign( from );
+ return *this;
+}
+
+inline CUtlDataEnvelope::operator void *()
+{
+ if ( !m_nBytes )
+ {
+ return NULL;
+ }
+
+ return ( m_nBytes > 4) ? m_pData : m_data;
+}
+
+inline CUtlDataEnvelope::operator void *() const
+{
+ if ( !m_nBytes )
+ {
+ return NULL;
+ }
+
+ return ( m_nBytes > 4) ? (void *)m_pData : (void *)m_data;
+}
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+inline CUtlEnvelope<T>::CUtlEnvelope( const T *pData, int nElems )
+ : CUtlDataEnvelope( pData, sizeof(T) * nElems )
+{
+}
+
+template <typename T>
+inline CUtlEnvelope<T>::CUtlEnvelope( const CUtlEnvelope<T> &from )
+ : CUtlDataEnvelope( from )
+{
+
+}
+
+template <typename T>
+inline CUtlEnvelope<T> &CUtlEnvelope<T>::operator=( const CUtlEnvelope<T> &from )
+{
+ CUtlDataEnvelope::operator=( from );
+ return *this;
+}
+
+template <typename T>
+inline CUtlEnvelope<T>::operator T *()
+{
+ return (T *)CUtlDataEnvelope::operator void *();
+}
+
+template <typename T>
+inline CUtlEnvelope<T>::operator T *() const
+{
+ return (T *)( (const_cast<CUtlEnvelope<T> *>(this))->operator T *() );
+}
+
+template <typename T>
+inline CUtlEnvelope<T>::operator void *()
+{
+ return CUtlDataEnvelope::operator void *();
+}
+
+template <typename T>
+inline CUtlEnvelope<T>::operator void *() const
+{
+ return ( (const_cast<CUtlEnvelope<T> *>(this))->operator void *() );
+}
+
+//-----------------------------------------------------------------------------
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLENVELOPE_H
diff --git a/external/vpc/public/tier1/utlfixedmemory.h b/external/vpc/public/tier1/utlfixedmemory.h
new file mode 100644
index 0000000..a124889
--- /dev/null
+++ b/external/vpc/public/tier1/utlfixedmemory.h
@@ -0,0 +1,354 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable memory class.
+//===========================================================================//
+
+#ifndef UTLFIXEDMEMORY_H
+#define UTLFIXEDMEMORY_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/platform.h"
+
+#include "tier0/memalloc.h"
+#include "tier0/memdbgon.h"
+
+#pragma warning (disable:4100)
+#pragma warning (disable:4514)
+
+//-----------------------------------------------------------------------------
+
+#ifdef UTLFIXEDMEMORY_TRACK
+#define UTLFIXEDMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlFixedMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
+#define UTLFIXEDMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlFixedMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
+#else
+#define UTLFIXEDMEMORY_TRACK_ALLOC() ((void)0)
+#define UTLFIXEDMEMORY_TRACK_FREE() ((void)0)
+#endif
+
+
+//-----------------------------------------------------------------------------
+// The CUtlFixedMemory class:
+// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
+//-----------------------------------------------------------------------------
+template< class T >
+class CUtlFixedMemory
+{
+public:
+ // constructor, destructor
+ CUtlFixedMemory( int nGrowSize = 0, int nInitSize = 0 );
+ ~CUtlFixedMemory();
+
+ // Set the size by which the memory grows
+ void Init( int nGrowSize = 0, int nInitSize = 0 );
+
+ // here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL
+ T* Base() { return NULL; }
+ const T* Base() const { return NULL; }
+
+protected:
+ struct BlockHeader_t;
+
+public:
+ class Iterator_t
+ {
+ public:
+ Iterator_t( BlockHeader_t *p, int i ) : m_pBlockHeader( p ), m_nIndex( i ) {}
+ BlockHeader_t *m_pBlockHeader;
+ int m_nIndex;
+
+ bool operator==( const Iterator_t it ) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; }
+ bool operator!=( const Iterator_t it ) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; }
+ };
+ Iterator_t First() const { return m_pBlocks ? Iterator_t( m_pBlocks, 0 ) : InvalidIterator(); }
+ Iterator_t Next( const Iterator_t &it ) const
+ {
+ Assert( IsValidIterator( it ) );
+ if ( !IsValidIterator( it ) )
+ return InvalidIterator();
+
+ BlockHeader_t * RESTRICT pHeader = it.m_pBlockHeader;
+ if ( it.m_nIndex + 1 < pHeader->m_nBlockSize )
+ return Iterator_t( pHeader, it.m_nIndex + 1 );
+
+ return pHeader->m_pNext ? Iterator_t( pHeader->m_pNext, 0 ) : InvalidIterator();
+ }
+ int GetIndex( const Iterator_t &it ) const
+ {
+ Assert( IsValidIterator( it ) );
+ if ( !IsValidIterator( it ) )
+ return InvalidIndex();
+
+ return ( int )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex );
+ }
+ bool IsIdxAfter( int i, const Iterator_t &it ) const
+ {
+ Assert( IsValidIterator( it ) );
+ if ( !IsValidIterator( it ) )
+ return false;
+
+ if ( IsInBlock( i, it.m_pBlockHeader ) )
+ return i > GetIndex( it );
+
+ for ( BlockHeader_t * RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext )
+ {
+ if ( IsInBlock( i, pbh ) )
+ return true;
+ }
+ return false;
+ }
+ bool IsValidIterator( const Iterator_t &it ) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; }
+ Iterator_t InvalidIterator() const { return Iterator_t( NULL, -1 ); }
+
+ // element access
+ T& operator[]( int i );
+ const T& operator[]( int i ) const;
+ T& Element( int i );
+ const T& Element( int i ) const;
+
+ // Can we use this index?
+ bool IsIdxValid( int i ) const;
+
+ // Specify the invalid ('null') index that we'll only return on failure
+ static const int INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT
+ static int InvalidIndex() { return INVALID_INDEX; }
+
+ // Size
+ int NumAllocated() const;
+ int Count() const { return NumAllocated(); }
+
+ // Grows memory by max(num,growsize), and returns the allocation index/ptr
+ void Grow( int num = 1 );
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num );
+
+ // Memory deallocation
+ void Purge();
+
+protected:
+ // Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
+ void Swap( CUtlFixedMemory< T > &mem );
+
+ bool IsInBlock( int i, BlockHeader_t *pBlockHeader ) const
+ {
+ T *p = ( T* )i;
+ const T *p0 = HeaderToBlock( pBlockHeader );
+ return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize;
+ }
+
+ struct BlockHeader_t
+ {
+ BlockHeader_t *m_pNext;
+ int m_nBlockSize;
+ };
+
+ const T *HeaderToBlock( const BlockHeader_t *pHeader ) const { return ( T* )( pHeader + 1 ); }
+ const BlockHeader_t *BlockToHeader( const T *pBlock ) const { return ( BlockHeader_t* )( pBlock ) - 1; }
+
+ BlockHeader_t* m_pBlocks;
+ int m_nAllocationCount;
+ int m_nGrowSize;
+};
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template< class T >
+CUtlFixedMemory<T>::CUtlFixedMemory( int nGrowSize, int nInitAllocationCount )
+: m_pBlocks( 0 ), m_nAllocationCount( 0 ), m_nGrowSize( 0 )
+{
+ Init( nGrowSize, nInitAllocationCount );
+}
+
+template< class T >
+CUtlFixedMemory<T>::~CUtlFixedMemory()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
+//-----------------------------------------------------------------------------
+template< class T >
+void CUtlFixedMemory<T>::Swap( CUtlFixedMemory< T > &mem )
+{
+ V_swap( m_pBlocks, mem.m_pBlocks );
+ V_swap( m_nAllocationCount, mem.m_nAllocationCount );
+ V_swap( m_nGrowSize, mem.m_nGrowSize );
+}
+
+
+//-----------------------------------------------------------------------------
+// Set the size by which the memory grows - round up to the next power of 2
+//-----------------------------------------------------------------------------
+template< class T >
+void CUtlFixedMemory<T>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ )
+{
+ Purge();
+
+ m_nGrowSize = nGrowSize;
+
+ Grow( nInitSize );
+}
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< class T >
+inline T& CUtlFixedMemory<T>::operator[]( int i )
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+template< class T >
+inline const T& CUtlFixedMemory<T>::operator[]( int i ) const
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+template< class T >
+inline T& CUtlFixedMemory<T>::Element( int i )
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+template< class T >
+inline const T& CUtlFixedMemory<T>::Element( int i ) const
+{
+ Assert( IsIdxValid(i) );
+ return *( T* )i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Size
+//-----------------------------------------------------------------------------
+template< class T >
+inline int CUtlFixedMemory<T>::NumAllocated() const
+{
+ return m_nAllocationCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< class T >
+inline bool CUtlFixedMemory<T>::IsIdxValid( int i ) const
+{
+#ifdef _DEBUG
+ for ( BlockHeader_t *pbh = m_pBlocks; pbh; pbh = pbh->m_pNext )
+ {
+ if ( IsInBlock( i, pbh ) )
+ return true;
+ }
+ return false;
+#else
+ return i != InvalidIndex();
+#endif
+}
+
+template< class T >
+void CUtlFixedMemory<T>::Grow( int num )
+{
+ if ( num <= 0 )
+ return;
+
+ int nBlockSize = m_nGrowSize;
+ if ( nBlockSize == 0 )
+ {
+ if ( m_nAllocationCount )
+ {
+ nBlockSize = m_nAllocationCount;
+ }
+ else
+ {
+ // Compute an allocation which is at least as big as a cache line...
+ nBlockSize = ( 31 + sizeof( T ) ) / sizeof( T );
+ Assert( nBlockSize );
+ }
+ }
+ if ( nBlockSize < num )
+ {
+ int n = ( num + nBlockSize -1 ) / nBlockSize;
+ Assert( n * nBlockSize >= num );
+ Assert( ( n - 1 ) * nBlockSize < num );
+ nBlockSize *= n;
+ }
+ m_nAllocationCount += nBlockSize;
+
+ MEM_ALLOC_CREDIT_CLASS();
+ BlockHeader_t * RESTRICT pBlockHeader = ( BlockHeader_t* )malloc( sizeof( BlockHeader_t ) + nBlockSize * sizeof( T ) );
+ if ( !pBlockHeader )
+ {
+ Error( "CUtlFixedMemory overflow!\n" );
+ }
+ pBlockHeader->m_pNext = NULL;
+ pBlockHeader->m_nBlockSize = nBlockSize;
+
+ if ( !m_pBlocks )
+ {
+ m_pBlocks = pBlockHeader;
+ }
+ else
+ {
+#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end
+ BlockHeader_t * RESTRICT pbh = m_pBlocks;
+ while ( pbh->m_pNext )
+ {
+ pbh = pbh->m_pNext;
+ }
+ pbh->m_pNext = pBlockHeader;
+#else
+ pBlockHeader = m_pBlocks;
+ pBlockHeader->m_pNext = m_pBlocks;
+#endif
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we've got at least this much memory
+//-----------------------------------------------------------------------------
+template< class T >
+inline void CUtlFixedMemory<T>::EnsureCapacity( int num )
+{
+ Grow( num - NumAllocated() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+template< class T >
+void CUtlFixedMemory<T>::Purge()
+{
+ if ( !m_pBlocks )
+ return;
+
+ for ( BlockHeader_t *pbh = m_pBlocks; pbh; )
+ {
+ BlockHeader_t *pFree = pbh;
+ pbh = pbh->m_pNext;
+ free( pFree );
+ }
+ m_pBlocks = NULL;
+ m_nAllocationCount = 0;
+}
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLFIXEDMEMORY_H
diff --git a/external/vpc/public/tier1/utlgraph.h b/external/vpc/public/tier1/utlgraph.h
new file mode 100644
index 0000000..9b9482e
--- /dev/null
+++ b/external/vpc/public/tier1/utlgraph.h
@@ -0,0 +1,658 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLGRAPH_H
+#define UTLGRAPH_H
+
+#include "tier1/utlmap.h"
+#include "tier1/utlvector.h"
+#include <limits.h>
+
+
+
+//-------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// A Graph class
+//
+// Nodes must have a unique Node ID.
+//
+// Edges are unidirectional, specified from the beginning node.
+//
+//-----------------------------------------------------------------------------
+
+template <class T, class C >
+class CUtlGraphVisitor;
+
+template <class T, class C = int >
+class CUtlGraph
+{
+public:
+ typedef int I;
+ typedef I IndexType_t;
+ typedef T NodeID_t;
+ typedef C CostType_t;
+
+ typedef CUtlGraphVisitor<T,C> Visitor_t;
+
+ struct Edge_t
+ {
+ IndexType_t m_DestinationNode;
+ CostType_t m_EdgeCost;
+
+ Edge_t( IndexType_t i = 0 )
+ {
+ m_DestinationNode = i;
+ m_EdgeCost = 0;
+ }
+
+ bool operator==(const Edge_t &that ) const
+ {
+ return m_DestinationNode == that.m_DestinationNode;
+ }
+
+ static int SortFn( const Edge_t *plhs, const Edge_t *prhs )
+ {
+ if ( plhs->m_EdgeCost < prhs->m_EdgeCost )
+ return -1;
+ else if ( plhs->m_EdgeCost > prhs->m_EdgeCost )
+ return 1;
+ else return 0;
+ }
+ };
+
+ typedef CUtlVector<Edge_t> vecEdges_t;
+
+ // constructor, destructor
+ CUtlGraph( );
+ ~CUtlGraph();
+
+ // Add an edge
+ bool AddEdge( T SourceNode, T DestNode, C nCost );
+
+ // Remove an edge
+ bool RemoveEdge( T SourceNode, T DestNode );
+
+ // gets particular elements
+ T& Element( I i );
+ T const &Element( I i ) const;
+ T& operator[]( I i );
+ T const &operator[]( I i ) const;
+
+ // Find a node
+ I Find( T Node ) { return m_Nodes.Find( Node ); }
+ I Find( T Node ) const { return m_Nodes.Find( Node ); }
+
+ // Num elements
+ unsigned int Count() const { return m_Nodes.Count() ; }
+
+ // Max "size" of the vector
+ I MaxElement() const { return m_Nodes.MaxElement(); }
+
+ // Checks if a node is valid and in the graph
+ bool IsValidIndex( I i ) const { return m_Nodes.IsValidIndex( i ); }
+
+ // Checks if the graph as a whole is valid
+ bool IsValid() const { return m_Nodes.IsValid(); }
+
+ // Invalid index
+ static I InvalidIndex() { return CUtlMap< NodeID_t, vecEdges_t*>::InvalidIndex(); }
+
+ // Remove methods
+ void RemoveAt( I i );
+ void RemoveAll();
+
+ // Makes sure we have enough memory allocated to store a requested # of elements
+ void EnsureCapacity( int num );
+
+ // Create Path Matrix once you've added all nodes and edges
+ void CreatePathMatrix();
+
+ // For Visitor classes
+ vecEdges_t *GetEdges( I i );
+
+ // shortest path costs
+ vecEdges_t *GetPathCosts( I i );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, const char *pchName );
+#endif // DBGFLAG_VALIDATE
+
+protected:
+
+ struct Node_t
+ {
+ vecEdges_t *m_pvecEdges;
+ vecEdges_t *m_pvecPaths;
+
+ Node_t()
+ {
+ m_pvecEdges = NULL;
+ m_pvecPaths = NULL;
+ }
+ };
+
+ CUtlMap< NodeID_t, Node_t > m_Nodes;
+};
+
+
+//-----------------------------------------------------------------------------
+// A Graph "visitor" class
+//
+// From the specified beginning point, visits each node in an expanding radius
+//
+//-----------------------------------------------------------------------------
+template <class T, class C = int >
+class CUtlGraphVisitor
+{
+public:
+ CUtlGraphVisitor( CUtlGraph<T, C> &graph );
+
+ bool Begin( T StartNode );
+ bool Advance();
+
+ T CurrentNode();
+ C AccumulatedCost();
+ int CurrentRadius();
+
+private:
+
+ typedef typename CUtlGraph<T,C>::IndexType_t IndexType_t;
+ typedef typename CUtlGraph<T,C>::Edge_t Edge_t;
+ typedef CUtlVector<Edge_t> vecEdges_t;
+
+ CUtlGraph<T, C> &m_Graph;
+
+ vecEdges_t m_vecVisitQueue;
+ int m_iVisiting;
+ int m_nCurrentRadius;
+
+ vecEdges_t m_vecFringeQueue;
+
+ CUtlVector<T> m_vecNodesVisited;
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template <class T, class C >
+inline CUtlGraph<T, C>::CUtlGraph()
+{
+ SetDefLessFunc( m_Nodes );
+}
+
+template <class T, class C >
+inline CUtlGraph<T, C>::~CUtlGraph()
+{
+ RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+
+template <class T, class C >
+inline T &CUtlGraph<T, C>::Element( I i )
+{
+ return m_Nodes.Key( i );
+}
+
+template <class T, class C >
+inline T const &CUtlGraph<T, C>::Element( I i ) const
+{
+ return m_Nodes.Key( i );
+}
+
+template <class T, class C >
+inline T &CUtlGraph<T, C>::operator[]( I i )
+{
+ return Element(i);
+}
+
+template <class T, class C >
+inline T const &CUtlGraph<T, C>::operator[]( I i ) const
+{
+ return Element(i);
+}
+
+//-----------------------------------------------------------------------------
+//
+// various accessors
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree
+//-----------------------------------------------------------------------------
+
+template <class T, class C >
+void CUtlGraph<T, C>::RemoveAll()
+{
+ FOR_EACH_MAP_FAST( m_Nodes, iNode )
+ {
+ delete m_Nodes[iNode].m_pvecEdges;
+ delete m_Nodes[iNode].m_pvecPaths;
+ }
+
+ m_Nodes.RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+template <class T, class C >
+void CUtlGraph<T, C>::EnsureCapacity( int num )
+{
+ m_Nodes.EnsureCapacity(num);
+}
+
+//-----------------------------------------------------------------------------
+// Add an edge
+//-----------------------------------------------------------------------------
+template <class T, class C >
+bool CUtlGraph<T, C>::AddEdge( T SourceNode, T DestNode, C nCost )
+{
+ I iSrcNode = m_Nodes.Find( SourceNode );
+ if ( !m_Nodes.IsValidIndex( iSrcNode ) )
+ {
+ Node_t Node;
+ Node.m_pvecEdges = new vecEdges_t();
+ Node.m_pvecPaths = new vecEdges_t();
+ iSrcNode = m_Nodes.Insert( SourceNode, Node );
+ }
+
+ I iDstNode = m_Nodes.Find( DestNode );
+ if ( !m_Nodes.IsValidIndex( iDstNode ) )
+ {
+ Node_t Node;
+ Node.m_pvecEdges = new vecEdges_t();
+ Node.m_pvecPaths = new vecEdges_t();
+ iDstNode = m_Nodes.Insert( DestNode, Node );
+ }
+
+ vecEdges_t &vecEdges = *m_Nodes[iSrcNode].m_pvecEdges;
+
+#ifdef _DEBUG
+ FOR_EACH_VEC( vecEdges, iEdge )
+ {
+ if ( vecEdges[iEdge].m_DestinationNode == iDstNode )
+ return false;
+ }
+#endif
+
+ Edge_t newEdge;
+ newEdge.m_DestinationNode = iDstNode;
+ newEdge.m_EdgeCost = nCost;
+
+ vecEdges[ vecEdges.AddToTail() ] = newEdge;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Remove an edge
+//-----------------------------------------------------------------------------
+template <class T, class C >
+bool CUtlGraph<T, C>::RemoveEdge( T SourceNode, T DestNode )
+{
+ I iSrcNode = m_Nodes.Find( SourceNode );
+ if ( !m_Nodes.IsValidIndex( iSrcNode ) )
+ return false;
+
+ I iDstNode = m_Nodes.Find( DestNode );
+ if ( !m_Nodes.IsValidIndex( iDstNode ) )
+ return false;
+
+ vecEdges_t &vecEdges = *m_Nodes[iSrcNode].m_pvecEdges;
+
+ FOR_EACH_VEC( vecEdges, iEdge )
+ {
+ if ( vecEdges[iEdge].m_DestinationNode == iDstNode )
+ {
+ // could use FastRemove, but nodes won't have that
+ // many edges, and the elements are small, and
+ // preserving the original ordering is nice
+ vecEdges.Remove( iEdge );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Get all of a Node's edges
+//-----------------------------------------------------------------------------
+template <class T, class C >
+typename CUtlGraph<T, C>::vecEdges_t *CUtlGraph<T, C>::GetEdges( I i )
+{
+ return m_Nodes[i].m_pvecEdges;
+}
+
+//-----------------------------------------------------------------------------
+// Get all of a Node's edges
+//-----------------------------------------------------------------------------
+template <class T, class C >
+typename CUtlGraph<T, C>::vecEdges_t *CUtlGraph<T, C>::GetPathCosts( I i )
+{
+ return m_Nodes[i].m_pvecPaths;
+}
+
+
+//-----------------------------------------------------------------------------
+// Data and memory validation
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+template <class T, class C >
+void CUtlGraph<T, C>::Validate( CValidator &validator, const char *pchName )
+{
+#ifdef _WIN32
+ validator.Push( typeid(*this).raw_name(), this, pchName );
+#else
+ validator.Push( typeid(*this).name(), this, pchName );
+#endif
+
+ ValidateObj( m_Nodes );
+
+ FOR_EACH_MAP_FAST( m_Nodes, iNode )
+ {
+ validator.ClaimMemory( m_Nodes[iNode].m_pvecEdges );
+ ValidateObj( *m_Nodes[iNode].m_pvecEdges );
+ validator.ClaimMemory( m_Nodes[iNode].m_pvecPaths );
+ ValidateObj( *m_Nodes[iNode].m_pvecPaths );
+ }
+
+ validator.Pop();
+}
+#endif // DBGFLAG_VALIDATE
+
+
+//-----------------------------------------------------------------------------
+// Get all of a Node's edges
+//-----------------------------------------------------------------------------
+template <class T, class C >
+void CUtlGraph<T, C>::CreatePathMatrix()
+{
+ int n = MaxElement();
+
+ // Notes
+ // Because CUtlMap stores its nodes in essentially a vector,
+ // we know that we can use its indices in our own path matrix
+ // vectors safely (they will be numbers in the range (0,N) where
+ // N is largest number of nodes ever present in the graph).
+ //
+ // This lets us very quickly access previous best-path estimates
+ // by indexing into a node's vecPaths directly.
+ //
+ // When we are all done, we can then compact the vector, removing
+ // "null" paths, and then sorting by cost.
+
+ // Initialize matrix with all edges
+ FOR_EACH_MAP_FAST( m_Nodes, iNode )
+ {
+ vecEdges_t &vecEdges = *m_Nodes.Element( iNode ).m_pvecEdges;
+ vecEdges_t &vecPaths = *m_Nodes.Element( iNode ).m_pvecPaths;
+
+ vecPaths.RemoveAll();
+ vecPaths.AddMultipleToTail( n );
+ FOR_EACH_VEC( vecPaths, iPath )
+ {
+ vecPaths[iPath].m_DestinationNode = InvalidIndex();
+ }
+
+ // Path to self
+ vecPaths[iNode].m_DestinationNode = iNode;
+ // zero cost to self
+ vecPaths[iNode].m_EdgeCost = 0;
+
+ FOR_EACH_VEC( vecEdges, iEdge )
+ {
+ // Path to a neighbor node - we know exactly what the cost is
+ Edge_t &edge = vecEdges[iEdge];
+ vecPaths[ edge.m_DestinationNode ].m_DestinationNode = edge.m_DestinationNode;
+ vecPaths[ edge.m_DestinationNode ].m_EdgeCost = edge.m_EdgeCost;
+ }
+ }
+
+ // Floyd-Warshall
+ // for k:= 0 to n-1
+ // for each (i,j) in (0..n-1)
+ // path[i][j] = min( path[i][j], path[i][k]+path[k][j] );
+ for ( int k = 0; k < n; ++ k )
+ {
+ if ( !m_Nodes.IsValidIndex( k ) )
+ continue;
+
+ // All current known paths from K
+ vecEdges_t &destMapFromK = *m_Nodes[k].m_pvecPaths;
+
+ for ( int i = 0; i < n; ++i )
+ {
+ if ( !m_Nodes.IsValidIndex( i ) )
+ continue;
+
+ // All current known paths from J
+ vecEdges_t &destMapFromI = *m_Nodes[i].m_pvecPaths;
+
+ // Path from I to K?
+ int iFromIToK = k;
+ bool bFromIToK = destMapFromI[iFromIToK].m_DestinationNode != InvalidIndex();
+ CostType_t cIToK = ( bFromIToK ) ? destMapFromI[iFromIToK].m_EdgeCost : INT_MAX;
+
+ for ( int j = 0; j < n; ++ j )
+ {
+ if ( !m_Nodes.IsValidIndex( j ) )
+ continue;
+
+ // Path from I to J already?
+ int iFromIToJ = j;
+ bool bFromIToJ = destMapFromI[iFromIToJ].m_DestinationNode != InvalidIndex();
+ CostType_t cIToJ = ( bFromIToJ ) ? destMapFromI[iFromIToJ].m_EdgeCost : INT_MAX;
+
+ // Path from K to J?
+ int iFromKToJ = j;
+ bool bFromKToJ = destMapFromK[iFromKToJ].m_DestinationNode != InvalidIndex();
+ CostType_t cKToJ = ( bFromKToJ ) ? destMapFromK[iFromKToJ].m_EdgeCost : INT_MAX;
+
+ // Is the new path valid?
+ bool bNewPathFound = ( bFromIToK && bFromKToJ );
+
+ if ( bNewPathFound )
+ {
+ if ( bFromIToJ )
+ {
+ // Pick min of previous best and current path
+ destMapFromI[iFromIToJ].m_EdgeCost = min( cIToJ, cIToK + cKToJ );
+ }
+ else
+ {
+ // Current path is the first, hence the best so far
+ destMapFromI[iFromIToJ].m_DestinationNode = iFromIToJ;
+ destMapFromI[iFromIToJ].m_EdgeCost = cIToK + cKToJ;
+ }
+ }
+ }
+ }
+ }
+
+ // Clean up and sort the paths
+ FOR_EACH_MAP_FAST( m_Nodes, iNode )
+ {
+ vecEdges_t &vecPaths = *m_Nodes.Element( iNode ).m_pvecPaths;
+ FOR_EACH_VEC( vecPaths, iPath )
+ {
+ Edge_t &edge = vecPaths[iPath];
+ if ( edge.m_DestinationNode == InvalidIndex() )
+ {
+ // No path to this destination was found.
+ // Remove this entry from the vector.
+ vecPaths.FastRemove( iPath );
+ --iPath; // adjust for the removal
+ }
+ }
+
+ // Sort the vector by cost, given that it
+ // is likely consumers will want to
+ // iterate destinations in that order.
+ vecPaths.Sort( Edge_t::SortFn );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+template <class T, class C >
+CUtlGraphVisitor<T, C>::CUtlGraphVisitor( CUtlGraph<T,C> &graph )
+: m_Graph( graph )
+{
+ m_iVisiting = 0;
+ m_nCurrentRadius = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Begin visiting the nodes in the graph. Returns false if the start node
+// does not exist
+//-----------------------------------------------------------------------------
+template <class T, class C >
+bool CUtlGraphVisitor<T, C>::Begin( T StartNode )
+{
+ m_vecVisitQueue.RemoveAll();
+ m_vecFringeQueue.RemoveAll();
+ m_vecNodesVisited.RemoveAll();
+ m_iVisiting = 0;
+ m_nCurrentRadius = 0;
+
+ IndexType_t iStartNode = m_Graph.Find( StartNode );
+
+ if ( !m_Graph.IsValidIndex( iStartNode ) )
+ return false;
+
+ vecEdges_t *pvecEdges = m_Graph.GetEdges( iStartNode );
+
+ Edge_t edge;
+ edge.m_DestinationNode = iStartNode;
+ edge.m_EdgeCost = 0;
+
+ m_vecVisitQueue[ m_vecVisitQueue.AddToTail() ] = edge;
+
+ m_vecNodesVisited[ m_vecNodesVisited.AddToTail() ] = iStartNode;
+
+ m_vecFringeQueue = *pvecEdges;
+
+ // cells actually get marked as "visited" as soon as we put
+ // them in the fringe queue, so we don't put them in the *next*
+ // fringe queue (we build the fringe queue before we actually visit
+ // the nodes in the new visit queue).
+ FOR_EACH_VEC( m_vecFringeQueue, iFringe )
+ {
+ m_vecNodesVisited[ m_vecNodesVisited.AddToTail() ] = m_vecFringeQueue[iFringe].m_DestinationNode;
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Advance to the next node. Returns false when all nodes have been visited
+//-----------------------------------------------------------------------------
+template <class T, class C>
+bool CUtlGraphVisitor<T, C>::Advance()
+{
+ m_iVisiting++;
+
+ // Is the VisitQueue empty? move outward one radius if so
+
+ if ( m_iVisiting >= m_vecVisitQueue.Count() )
+ {
+ m_nCurrentRadius++;
+ m_iVisiting = 0;
+ m_vecVisitQueue = m_vecFringeQueue;
+ m_vecFringeQueue.RemoveAll();
+
+ if ( !m_vecVisitQueue.Count() )
+ return false;
+
+ // create new fringe queue
+ FOR_EACH_VEC( m_vecVisitQueue, iNode )
+ {
+ Edge_t &node = m_vecVisitQueue[iNode];
+ vecEdges_t &vecEdges = *m_Graph.GetEdges( node.m_DestinationNode );
+ FOR_EACH_VEC( vecEdges, iEdge )
+ {
+ Edge_t &edge = vecEdges[iEdge];
+ if ( m_vecNodesVisited.InvalidIndex() == m_vecNodesVisited.Find( edge.m_DestinationNode ) )
+ {
+ m_vecNodesVisited[ m_vecNodesVisited.AddToTail() ] = edge.m_DestinationNode;
+
+ int iNewFringeNode = m_vecFringeQueue.AddToTail();
+ m_vecFringeQueue[ iNewFringeNode ] = edge;
+ // Accumulate the cost to get to the current point
+ m_vecFringeQueue[ iNewFringeNode ].m_EdgeCost += node.m_EdgeCost;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Get the current node in the visit sequence
+//-----------------------------------------------------------------------------
+template <class T, class C>
+T CUtlGraphVisitor<T, C>::CurrentNode()
+{
+ if ( m_iVisiting >= m_vecVisitQueue.Count() )
+ {
+ AssertMsg( false, "Visitor invalid" );
+ return T();
+ }
+
+ return m_Graph[ m_vecVisitQueue[ m_iVisiting ].m_DestinationNode ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Get the accumulated cost to traverse the graph to the current node
+//-----------------------------------------------------------------------------
+template <class T, class C>
+C CUtlGraphVisitor<T, C>::AccumulatedCost()
+{
+ if ( m_iVisiting >= m_vecVisitQueue.Count() )
+ {
+ AssertMsg( false, "Visitor invalid" );
+ return C();
+ }
+
+ return m_vecVisitQueue[ m_iVisiting ].m_EdgeCost;
+}
+
+
+//-----------------------------------------------------------------------------
+// Get the current radius from the start point to this node
+//-----------------------------------------------------------------------------
+template <class T, class C>
+int CUtlGraphVisitor<T, C>::CurrentRadius()
+{
+ if ( m_iVisiting >= m_vecVisitQueue.Count() )
+ {
+ AssertMsg( false, "Visitor invalid" );
+ return 0;
+ }
+
+ return m_nCurrentRadius;
+}
+
+#endif // UTLGRAPH_H
diff --git a/external/vpc/public/tier1/utlhash.h b/external/vpc/public/tier1/utlhash.h
new file mode 100644
index 0000000..aaddb29
--- /dev/null
+++ b/external/vpc/public/tier1/utlhash.h
@@ -0,0 +1,1299 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// Serialization/unserialization buffer
+//=============================================================================//
+
+#ifndef UTLHASH_H
+#define UTLHASH_H
+#pragma once
+
+#include <limits.h>
+#include "utlmemory.h"
+#include "utlvector.h"
+#include "utllinkedlist.h"
+#include "utllinkedlist.h"
+#include "commonmacros.h"
+#include "generichash.h"
+
+typedef unsigned int UtlHashHandle_t;
+
+template<class Data, typename C = bool (*)( Data const&, Data const& ), typename K = unsigned int (*)( Data const& ) >
+class CUtlHash
+{
+public:
+ // compare and key functions - implemented by the
+ typedef C CompareFunc_t;
+ typedef K KeyFunc_t;
+
+ // constructor/deconstructor
+ CUtlHash( int bucketCount = 0, int growCount = 0, int initCount = 0,
+ CompareFunc_t compareFunc = 0, KeyFunc_t keyFunc = 0 );
+ ~CUtlHash();
+
+ // invalid handle
+ static UtlHashHandle_t InvalidHandle( void ) { return ( UtlHashHandle_t )~0; }
+ bool IsValidHandle( UtlHashHandle_t handle ) const;
+
+ // size
+ int Count( void ) const;
+
+ // memory
+ void Purge( void );
+
+ // insertion methods
+ UtlHashHandle_t Insert( Data const &src );
+ UtlHashHandle_t Insert( Data const &src, bool *pDidInsert );
+ UtlHashHandle_t AllocEntryFromKey( Data const &src );
+
+ // removal methods
+ void Remove( UtlHashHandle_t handle );
+ void RemoveAll();
+
+ // retrieval methods
+ UtlHashHandle_t Find( Data const &src ) const;
+
+ Data &Element( UtlHashHandle_t handle );
+ Data const &Element( UtlHashHandle_t handle ) const;
+ Data &operator[]( UtlHashHandle_t handle );
+ Data const &operator[]( UtlHashHandle_t handle ) const;
+
+ UtlHashHandle_t GetFirstHandle() const;
+ UtlHashHandle_t GetNextHandle( UtlHashHandle_t h ) const;
+
+ // debugging!!
+ void Log( const char *filename );
+ void Dump();
+
+protected:
+
+ int GetBucketIndex( UtlHashHandle_t handle ) const;
+ int GetKeyDataIndex( UtlHashHandle_t handle ) const;
+ UtlHashHandle_t BuildHandle( int ndxBucket, int ndxKeyData ) const;
+
+ bool DoFind( Data const &src, unsigned int *pBucket, int *pIndex ) const;
+
+protected:
+
+ // handle upper 16 bits = bucket index (bucket heads)
+ // handle lower 16 bits = key index (bucket list)
+ typedef CUtlVector<Data> HashBucketList_t;
+ CUtlVector<HashBucketList_t> m_Buckets;
+
+ CompareFunc_t m_CompareFunc; // function used to handle unique compares on data
+ KeyFunc_t m_KeyFunc; // function used to generate the key value
+
+ bool m_bPowerOfTwo; // if the bucket value is a power of two,
+ unsigned int m_ModMask; // use the mod mask to "mod"
+};
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+CUtlHash<Data, C, K>::CUtlHash( int bucketCount, int growCount, int initCount,
+ CompareFunc_t compareFunc, KeyFunc_t keyFunc ) :
+ m_CompareFunc( compareFunc ),
+ m_KeyFunc( keyFunc )
+{
+ bucketCount = MIN(bucketCount, 65536);
+ m_Buckets.SetSize( bucketCount );
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ m_Buckets[ndxBucket].SetSize( initCount );
+ m_Buckets[ndxBucket].SetGrowSize( growCount );
+ }
+
+ // check to see if the bucket count is a power of 2 and set up
+ // optimizations appropriately
+ m_bPowerOfTwo = IsPowerOfTwo( bucketCount );
+ m_ModMask = m_bPowerOfTwo ? (bucketCount-1) : 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+CUtlHash<Data, C, K>::~CUtlHash()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline bool CUtlHash<Data, C, K>::IsValidHandle( UtlHashHandle_t handle ) const
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ // ndxBucket and ndxKeyData can't possibly be less than zero -- take a
+ // look at the definition of the Get..Index functions for why. However,
+ // if you override those functions, you will need to override this one
+ // as well.
+ if( /*( ndxBucket >= 0 ) && */ ( ndxBucket < m_Buckets.Count() ) )
+ {
+ if( /*( ndxKeyData >= 0 ) && */ ( ndxKeyData < m_Buckets[ndxBucket].Count() ) )
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline int CUtlHash<Data, C, K>::Count( void ) const
+{
+ int count = 0;
+
+ int bucketCount = m_Buckets.Count();
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ count += m_Buckets[ndxBucket].Count();
+ }
+
+ return count;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline int CUtlHash<Data, C, K>::GetBucketIndex( UtlHashHandle_t handle ) const
+{
+ return ( ( ( handle >> 16 ) & 0x0000ffff ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline int CUtlHash<Data, C, K>::GetKeyDataIndex( UtlHashHandle_t handle ) const
+{
+ return ( handle & 0x0000ffff );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::BuildHandle( int ndxBucket, int ndxKeyData ) const
+{
+ Assert( ( ndxBucket >= 0 ) && ( ndxBucket < 65536 ) );
+ Assert( ( ndxKeyData >= 0 ) && ( ndxKeyData < 65536 ) );
+
+ UtlHashHandle_t handle = ndxKeyData;
+ handle |= ( ndxBucket << 16 );
+
+ return handle;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Purge( void )
+{
+ int bucketCount = m_Buckets.Count();
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ m_Buckets[ndxBucket].Purge();
+ }
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline bool CUtlHash<Data, C, K>::DoFind( Data const &src, unsigned int *pBucket, int *pIndex ) const
+{
+ // generate the data "key"
+ unsigned int key = m_KeyFunc( src );
+
+ // hash the "key" - get the correct hash table "bucket"
+ unsigned int ndxBucket;
+ if( m_bPowerOfTwo )
+ {
+ *pBucket = ndxBucket = ( key & m_ModMask );
+ }
+ else
+ {
+ int bucketCount = m_Buckets.Count();
+ *pBucket = ndxBucket = key % bucketCount;
+ }
+
+ int ndxKeyData = 0;
+ const CUtlVector<Data> &bucket = m_Buckets[ndxBucket];
+ int keyDataCount = bucket.Count();
+ for( ndxKeyData = 0; ndxKeyData < keyDataCount; ndxKeyData++ )
+ {
+ if( m_CompareFunc( bucket.Element( ndxKeyData ), src ) )
+ break;
+ }
+
+ if( ndxKeyData == keyDataCount )
+ return false;
+
+ *pIndex = ndxKeyData;
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::Find( Data const &src ) const
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+ return ( InvalidHandle() );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::Insert( Data const &src )
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+
+ ndxKeyData = m_Buckets[ndxBucket].AddToTail( src );
+
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::Insert( Data const &src, bool *pDidInsert )
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ *pDidInsert = false;
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+
+ *pDidInsert = true;
+ ndxKeyData = m_Buckets[ndxBucket].AddToTail( src );
+
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::AllocEntryFromKey( Data const &src )
+{
+ unsigned int ndxBucket;
+ int ndxKeyData = 0;
+
+ if ( DoFind( src, &ndxBucket, &ndxKeyData ) )
+ {
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+ }
+
+ ndxKeyData = m_Buckets[ndxBucket].AddToTail();
+
+ return ( BuildHandle( ndxBucket, ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Remove( UtlHashHandle_t handle )
+{
+ Assert( IsValidHandle( handle ) );
+
+ // check to see if the bucket exists
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ if( m_Buckets[ndxBucket].IsValidIndex( ndxKeyData ) )
+ {
+ m_Buckets[ndxBucket].FastRemove( ndxKeyData );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::RemoveAll()
+{
+ int bucketCount = m_Buckets.Count();
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ m_Buckets[ndxBucket].RemoveAll();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data &CUtlHash<Data, C, K>::Element( UtlHashHandle_t handle )
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data const &CUtlHash<Data, C, K>::Element( UtlHashHandle_t handle ) const
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data &CUtlHash<Data, C, K>::operator[]( UtlHashHandle_t handle )
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline Data const &CUtlHash<Data, C, K>::operator[]( UtlHashHandle_t handle ) const
+{
+ int ndxBucket = GetBucketIndex( handle );
+ int ndxKeyData = GetKeyDataIndex( handle );
+
+ return ( m_Buckets[ndxBucket].Element( ndxKeyData ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::GetFirstHandle() const
+{
+ return GetNextHandle( ( UtlHashHandle_t )-1 );
+}
+
+template<class Data, typename C, typename K>
+inline UtlHashHandle_t CUtlHash<Data, C, K>::GetNextHandle( UtlHashHandle_t handle ) const
+{
+ ++handle; // start at the first possible handle after the one given
+
+ int bi = GetBucketIndex( handle );
+ int ki = GetKeyDataIndex( handle );
+
+ int nBuckets = m_Buckets.Count();
+ for ( ; bi < nBuckets; ++bi )
+ {
+ if ( ki < m_Buckets[ bi ].Count() )
+ return BuildHandle( bi, ki );
+
+ ki = 0;
+ }
+
+ return InvalidHandle();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Log( const char *filename )
+{
+ FILE *pDebugFp;
+ pDebugFp = fopen( filename, "w" );
+ if( !pDebugFp )
+ return;
+
+ int maxBucketSize = 0;
+ int numBucketsEmpty = 0;
+
+ int bucketCount = m_Buckets.Count();
+ fprintf( pDebugFp, "\n%d Buckets\n", bucketCount );
+
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ int count = m_Buckets[ndxBucket].Count();
+
+ if( count > maxBucketSize ) { maxBucketSize = count; }
+ if( count == 0 )
+ numBucketsEmpty++;
+
+ fprintf( pDebugFp, "Bucket %d: %d\n", ndxBucket, count );
+ }
+
+ fprintf( pDebugFp, "\nBucketHeads Used: %d\n", bucketCount - numBucketsEmpty );
+ fprintf( pDebugFp, "Max Bucket Size: %d\n", maxBucketSize );
+
+ fclose( pDebugFp );
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, typename C, typename K>
+inline void CUtlHash<Data, C, K>::Dump( )
+{
+ int maxBucketSize = 0;
+ int numBucketsEmpty = 0;
+
+ int bucketCount = m_Buckets.Count();
+ Msg( "\n%d Buckets\n", bucketCount );
+
+ for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ )
+ {
+ int count = m_Buckets[ndxBucket].Count();
+
+ if( count > maxBucketSize ) { maxBucketSize = count; }
+ if( count == 0 )
+ numBucketsEmpty++;
+
+ Msg( "Bucket %d: %d\n", ndxBucket, count );
+ }
+
+ Msg( "\nBucketHeads Used: %d\n", bucketCount - numBucketsEmpty );
+ Msg( "Max Bucket Size: %d\n", maxBucketSize );
+}
+
+//=============================================================================
+//
+// Fast Hash
+//
+// Number of buckets must be a power of 2.
+// Key must be 32-bits (unsigned int).
+//
+typedef int UtlHashFastHandle_t;
+
+#define UTLHASH_POOL_SCALAR 2
+
+class CUtlHashFastNoHash
+{
+public:
+ static int Hash( int key, int bucketMask )
+ {
+ return ( key & bucketMask );
+ }
+};
+
+class CUtlHashFastGenericHash
+{
+public:
+ static int Hash( int key, int bucketMask )
+ {
+ return ( HashIntConventional( key ) & bucketMask );
+ }
+};
+
+template<class Data, class HashFuncs = CUtlHashFastNoHash >
+class CUtlHashFast
+{
+public:
+
+ // Constructor/Deconstructor.
+ CUtlHashFast();
+ ~CUtlHashFast();
+
+ // Memory.
+ void Purge( void );
+
+ // Invalid handle.
+ static UtlHashFastHandle_t InvalidHandle( void ) { return ( UtlHashFastHandle_t )~0; }
+ inline bool IsValidHandle( UtlHashFastHandle_t hHash ) const;
+
+ // Initialize.
+ bool Init( int nBucketCount );
+
+ // Size not available; count is meaningless for multilists.
+ // int Count( void ) const;
+
+ // Insertion.
+ UtlHashFastHandle_t Insert( unsigned int uiKey, const Data &data );
+ UtlHashFastHandle_t FastInsert( unsigned int uiKey, const Data &data );
+
+ // Removal.
+ void Remove( UtlHashFastHandle_t hHash );
+ void RemoveAll( void );
+
+ // Retrieval.
+ UtlHashFastHandle_t Find( unsigned int uiKey ) const;
+
+ Data &Element( UtlHashFastHandle_t hHash );
+ Data const &Element( UtlHashFastHandle_t hHash ) const;
+ Data &operator[]( UtlHashFastHandle_t hHash );
+ Data const &operator[]( UtlHashFastHandle_t hHash ) const;
+
+ // Iteration
+ struct UtlHashFastIterator_t
+ {
+ int bucket;
+ UtlHashFastHandle_t handle;
+
+ UtlHashFastIterator_t(int _bucket, const UtlHashFastHandle_t &_handle)
+ : bucket(_bucket), handle(_handle) {};
+ // inline operator UtlHashFastHandle_t() const { return handle; };
+ };
+ inline UtlHashFastIterator_t First() const;
+ inline UtlHashFastIterator_t Next( const UtlHashFastIterator_t &hHash ) const;
+ inline bool IsValidIterator( const UtlHashFastIterator_t &iter ) const;
+ inline Data &operator[]( const UtlHashFastIterator_t &iter ) { return (*this)[iter.handle]; }
+ inline Data const &operator[]( const UtlHashFastIterator_t &iter ) const { return (*this)[iter.handle]; }
+
+//protected:
+
+ // Templatized for memory tracking purposes
+ template <typename HashData>
+ struct HashFastData_t_
+ {
+ unsigned int m_uiKey;
+ HashData m_Data;
+ };
+
+ typedef HashFastData_t_<Data> HashFastData_t;
+
+ unsigned int m_uiBucketMask;
+ CUtlVector<UtlHashFastHandle_t> m_aBuckets;
+ CUtlFixedLinkedList<HashFastData_t> m_aDataPool;
+
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> CUtlHashFast<Data,HashFuncs>::CUtlHashFast()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Deconstructor
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> CUtlHashFast<Data,HashFuncs>::~CUtlHashFast()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destroy dynamically allocated hash data.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline void CUtlHashFast<Data,HashFuncs>::Purge( void )
+{
+ m_aBuckets.Purge();
+ m_aDataPool.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Initialize the hash - set bucket count and hash grow amount.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> bool CUtlHashFast<Data,HashFuncs>::Init( int nBucketCount )
+{
+ // Verify the bucket count is power of 2.
+ if ( !IsPowerOfTwo( nBucketCount ) )
+ return false;
+
+ // Set the bucket size.
+ m_aBuckets.SetSize( nBucketCount );
+ for ( int iBucket = 0; iBucket < nBucketCount; ++iBucket )
+ {
+ m_aBuckets[iBucket] = m_aDataPool.InvalidIndex();
+ }
+
+ // Set the mod mask.
+ m_uiBucketMask = nBucketCount - 1;
+
+ // Calculate the grow size.
+ int nGrowSize = UTLHASH_POOL_SCALAR * nBucketCount;
+ m_aDataPool.SetGrowSize( nGrowSize );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Return the number of elements in the hash.
+// Not available because count isn't accurately maintained for multilists.
+//-----------------------------------------------------------------------------
+/*
+template<class Data, class HashFuncs> inline int CUtlHashFast<Data,HashFuncs>::Count( void ) const
+{
+ return m_aDataPool.Count();
+}
+*/
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int), with
+// a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline UtlHashFastHandle_t CUtlHashFast<Data,HashFuncs>::Insert( unsigned int uiKey, const Data &data )
+{
+ // Check to see if that key already exists in the buckets (should be unique).
+ UtlHashFastHandle_t hHash = Find( uiKey );
+ if( hHash != InvalidHandle() )
+ return hHash;
+
+ return FastInsert( uiKey, data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int),
+// without a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline UtlHashFastHandle_t CUtlHashFast<Data,HashFuncs>::FastInsert( unsigned int uiKey, const Data &data )
+{
+ // Get a new element from the pool.
+ int iHashData = m_aDataPool.Alloc( true );
+ HashFastData_t *pHashData = &m_aDataPool[iHashData];
+ if ( !pHashData )
+ return InvalidHandle();
+
+ // Add data to new element.
+ pHashData->m_uiKey = uiKey;
+ pHashData->m_Data = data;
+
+ // Link element.
+ int iBucket = HashFuncs::Hash( uiKey, m_uiBucketMask );
+ m_aDataPool.LinkBefore( m_aBuckets[iBucket], iHashData );
+ m_aBuckets[iBucket] = iHashData;
+
+ return iHashData;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove a given element from the hash.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline void CUtlHashFast<Data,HashFuncs>::Remove( UtlHashFastHandle_t hHash )
+{
+ int iBucket = HashFuncs::Hash( m_aDataPool[hHash].m_uiKey, m_uiBucketMask );
+ if ( m_aBuckets[iBucket] == hHash )
+ {
+ // It is a bucket head.
+ m_aBuckets[iBucket] = m_aDataPool.Next( hHash );
+ }
+ else
+ {
+ // Not a bucket head.
+ m_aDataPool.Unlink( hHash );
+ }
+
+ // Remove the element.
+ m_aDataPool.Remove( hHash );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove all elements from the hash
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline void CUtlHashFast<Data,HashFuncs>::RemoveAll( void )
+{
+ m_aBuckets.RemoveAll();
+ m_aDataPool.RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline UtlHashFastHandle_t CUtlHashFast<Data,HashFuncs>::Find( unsigned int uiKey ) const
+{
+ // hash the "key" - get the correct hash table "bucket"
+ int iBucket = HashFuncs::Hash( uiKey, m_uiBucketMask );
+
+ for ( int iElement = m_aBuckets[iBucket]; iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next( iElement ) )
+ {
+ if ( m_aDataPool[iElement].m_uiKey == uiKey )
+ return iElement;
+ }
+
+ return InvalidHandle();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data &CUtlHashFast<Data,HashFuncs>::Element( UtlHashFastHandle_t hHash )
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data const &CUtlHashFast<Data,HashFuncs>::Element( UtlHashFastHandle_t hHash ) const
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data &CUtlHashFast<Data,HashFuncs>::operator[]( UtlHashFastHandle_t hHash )
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs> inline Data const &CUtlHashFast<Data,HashFuncs>::operator[]( UtlHashFastHandle_t hHash ) const
+{
+ return ( m_aDataPool[hHash].m_Data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: For iterating over the whole hash, return the index of the first element
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs>
+ typename CUtlHashFast<Data,HashFuncs>::UtlHashFastIterator_t
+ CUtlHashFast<Data,HashFuncs>::First() const
+{
+ // walk through the buckets to find the first one that has some data
+ int bucketCount = m_aBuckets.Count();
+ const UtlHashFastHandle_t invalidIndex = m_aDataPool.InvalidIndex();
+ for ( int bucket = 0 ; bucket < bucketCount ; ++bucket )
+ {
+ UtlHashFastHandle_t iElement = m_aBuckets[bucket]; // get the head of the bucket
+ if (iElement != invalidIndex)
+ return UtlHashFastIterator_t(bucket,iElement);
+ }
+
+ // if we are down here, the list is empty
+ return UtlHashFastIterator_t(-1, invalidIndex);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: For iterating over the whole hash, return the next element after
+// the param one. Or an invalid iterator.
+//-----------------------------------------------------------------------------
+template<class Data, class HashFuncs>
+ typename CUtlHashFast<Data,HashFuncs>::UtlHashFastIterator_t
+ CUtlHashFast<Data,HashFuncs>::Next( const typename CUtlHashFast<Data,HashFuncs>::UtlHashFastIterator_t &iter ) const
+{
+ // look for the next entry in the current bucket
+ UtlHashFastHandle_t next = m_aDataPool.Next(iter.handle);
+ const UtlHashFastHandle_t invalidIndex = m_aDataPool.InvalidIndex();
+ if (next != invalidIndex)
+ {
+ // this bucket still has more elements in it
+ return UtlHashFastIterator_t(iter.bucket, next);
+ }
+
+ // otherwise look for the next bucket with data
+ int bucketCount = m_aBuckets.Count();
+ for ( int bucket = iter.bucket+1 ; bucket < bucketCount ; ++bucket )
+ {
+ UtlHashFastHandle_t next = m_aBuckets[bucket]; // get the head of the bucket
+ if (next != invalidIndex)
+ return UtlHashFastIterator_t( bucket, next );
+ }
+
+ // if we're here, there's no more data to be had
+ return UtlHashFastIterator_t(-1, invalidIndex);
+}
+
+template<class Data, class HashFuncs>
+ bool CUtlHashFast<Data,HashFuncs>::IsValidIterator( const typename CUtlHashFast::UtlHashFastIterator_t &iter ) const
+{
+ return ( (iter.bucket >= 0) && (m_aDataPool.IsValidIndex(iter.handle)) );
+}
+
+
+template<class Data, class HashFuncs> inline bool CUtlHashFast<Data,HashFuncs>::IsValidHandle( UtlHashFastHandle_t hHash ) const
+{
+ return m_aDataPool.IsValidIndex(hHash);
+}
+
+//=============================================================================
+//
+// Fixed Hash
+//
+// Number of buckets must be a power of 2.
+// Key must be 32-bits (unsigned int).
+//
+typedef int UtlHashFixedHandle_t;
+
+template <int NUM_BUCKETS>
+class CUtlHashFixedGenericHash
+{
+public:
+ static int Hash( int key, int bucketMask )
+ {
+ int hash = HashIntConventional( key );
+ if ( NUM_BUCKETS <= USHRT_MAX )
+ {
+ hash ^= ( hash >> 16 );
+ }
+ if ( NUM_BUCKETS <= UCHAR_MAX )
+ {
+ hash ^= ( hash >> 8 );
+ }
+ return ( hash & bucketMask );
+ }
+};
+
+template<class Data, int NUM_BUCKETS, class CHashFuncs = CUtlHashFastNoHash >
+class CUtlHashFixed
+{
+public:
+
+ // Constructor/Deconstructor.
+ CUtlHashFixed();
+ ~CUtlHashFixed();
+
+ // Memory.
+ void Purge( void );
+
+ // Invalid handle.
+ static UtlHashFixedHandle_t InvalidHandle( void ) { return ( UtlHashFixedHandle_t )~0; }
+
+ // Size.
+ int Count( void );
+
+ // Insertion.
+ UtlHashFixedHandle_t Insert( unsigned int uiKey, const Data &data );
+ UtlHashFixedHandle_t FastInsert( unsigned int uiKey, const Data &data );
+
+ // Removal.
+ void Remove( UtlHashFixedHandle_t hHash );
+ void RemoveAll( void );
+
+ // Retrieval.
+ UtlHashFixedHandle_t Find( unsigned int uiKey );
+
+ Data &Element( UtlHashFixedHandle_t hHash );
+ Data const &Element( UtlHashFixedHandle_t hHash ) const;
+ Data &operator[]( UtlHashFixedHandle_t hHash );
+ Data const &operator[]( UtlHashFixedHandle_t hHash ) const;
+
+ //protected:
+
+ // Templatized for memory tracking purposes
+ template <typename Data_t>
+ struct HashFixedData_t_
+ {
+ unsigned int m_uiKey;
+ Data_t m_Data;
+ };
+
+ typedef HashFixedData_t_<Data> HashFixedData_t;
+
+ enum
+ {
+ BUCKET_MASK = NUM_BUCKETS - 1
+ };
+ CUtlPtrLinkedList<HashFixedData_t> m_aBuckets[NUM_BUCKETS];
+ int m_nElements;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::CUtlHashFixed()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Deconstructor
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::~CUtlHashFixed()
+{
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destroy dynamically allocated hash data.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline void CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Purge( void )
+{
+ RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return the number of elements in the hash.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline int CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Count( void )
+{
+ return m_nElements;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int), with
+// a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline UtlHashFixedHandle_t CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Insert( unsigned int uiKey, const Data &data )
+{
+ // Check to see if that key already exists in the buckets (should be unique).
+ UtlHashFixedHandle_t hHash = Find( uiKey );
+ if( hHash != InvalidHandle() )
+ return hHash;
+
+ return FastInsert( uiKey, data );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Insert data into the hash table given its key (unsigned int),
+// without a check to see if the element already exists within the tree.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline UtlHashFixedHandle_t CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::FastInsert( unsigned int uiKey, const Data &data )
+{
+ int iBucket = HashFuncs::Hash( uiKey, NUM_BUCKETS - 1 );
+ UtlPtrLinkedListIndex_t iElem = m_aBuckets[iBucket].AddToHead();
+
+ HashFixedData_t *pHashData = &m_aBuckets[iBucket][iElem];
+
+ Assert( (UtlPtrLinkedListIndex_t)pHashData == iElem );
+
+ // Add data to new element.
+ pHashData->m_uiKey = uiKey;
+ pHashData->m_Data = data;
+
+ m_nElements++;
+ return (UtlHashFixedHandle_t)pHashData;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove a given element from the hash.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline void CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Remove( UtlHashFixedHandle_t hHash )
+{
+ HashFixedData_t *pHashData = (HashFixedData_t *)hHash;
+ Assert( Find(pHashData->m_uiKey) != InvalidHandle() );
+ int iBucket = HashFuncs::Hash( pHashData->m_uiKey, NUM_BUCKETS - 1 );
+ m_aBuckets[iBucket].Remove( (UtlPtrLinkedListIndex_t)pHashData );
+ m_nElements--;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Remove all elements from the hash
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline void CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::RemoveAll( void )
+{
+ for ( int i = 0; i < NUM_BUCKETS; i++ )
+ {
+ m_aBuckets[i].RemoveAll();
+ }
+ m_nElements = 0;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline UtlHashFixedHandle_t CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Find( unsigned int uiKey )
+{
+ int iBucket = HashFuncs::Hash( uiKey, NUM_BUCKETS - 1 );
+ CUtlPtrLinkedList<HashFixedData_t> &bucket = m_aBuckets[iBucket];
+
+ for ( UtlPtrLinkedListIndex_t iElement = bucket.Head(); iElement != bucket.InvalidIndex(); iElement = bucket.Next( iElement ) )
+ {
+ if ( bucket[iElement].m_uiKey == uiKey )
+ return (UtlHashFixedHandle_t)iElement;
+ }
+
+ return InvalidHandle();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Element( UtlHashFixedHandle_t hHash )
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data const &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::Element( UtlHashFixedHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::operator[]( UtlHashFixedHandle_t hHash )
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return data given a hash handle.
+//-----------------------------------------------------------------------------
+template<class Data, int NUM_BUCKETS, class HashFuncs> inline Data const &CUtlHashFixed<Data,NUM_BUCKETS,HashFuncs>::operator[]( UtlHashFixedHandle_t hHash ) const
+{
+ return ((HashFixedData_t *)hHash)->m_Data;
+}
+
+class CDefaultHash32
+{
+public:
+ static inline uint32 HashKey32( uint32 nKey ) { return HashIntConventional(nKey); }
+};
+
+class CPassthroughHash32
+{
+public:
+ static inline uint32 HashKey32( uint32 nKey ) { return nKey; }
+};
+
+
+// This is a simpler hash for scalar types that stores the entire hash + buckets in a single linear array
+// This is much more cache friendly for small (e.g. 32-bit) types stored in the hash
+template<class Data, class CHashFunction = CDefaultHash32>
+class CUtlScalarHash
+{
+public:
+
+ // Constructor/Destructor.
+ CUtlScalarHash();
+ ~CUtlScalarHash();
+
+ // Memory.
+ // void Purge( void );
+
+ // Invalid handle.
+ static const UtlHashFastHandle_t InvalidHandle( void ) { return (unsigned int)~0; }
+
+ // Initialize.
+ bool Init( int nBucketCount );
+
+ // Size.
+ int Count( void ) const { return m_dataCount; }
+
+ // Insertion.
+ UtlHashFastHandle_t Insert( unsigned int uiKey, const Data &data );
+
+ // Removal.
+ void FindAndRemove( unsigned int uiKey, const Data &dataRecord );
+ void Remove( UtlHashFastHandle_t hHash );
+ void RemoveAll( void );
+ void Grow();
+
+ // Retrieval. Finds by uiKey and then by comparing dataRecord
+ UtlHashFastHandle_t Find( unsigned int uiKey, const Data &dataRecord ) const;
+ UtlHashFastHandle_t FindByUniqueKey( unsigned int uiKey ) const;
+
+ Data &Element( UtlHashFastHandle_t hHash ) { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+ Data const &Element( UtlHashFastHandle_t hHash ) const { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+ Data &operator[]( UtlHashFastHandle_t hHash ) { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+ Data const &operator[]( UtlHashFastHandle_t hHash ) const { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_Data; }
+
+ unsigned int Key( UtlHashFastHandle_t hHash ) const { Assert(unsigned(hHash)<=m_uiBucketMask); return m_pData[hHash].m_uiKey; }
+
+ UtlHashFastHandle_t FirstInorder() const
+ {
+ return NextInorder(-1);
+ }
+ UtlHashFastHandle_t NextInorder( UtlHashFastHandle_t nStart ) const
+ {
+ int nElementCount = m_maxData * 2;
+ unsigned int nUnusedListElement = (unsigned int)InvalidHandle();
+ for ( int i = nStart+1; i < nElementCount; i++ )
+ {
+ if ( m_pData[i].m_uiKey != nUnusedListElement )
+ return i;
+ }
+ return nUnusedListElement;
+ }
+
+ //protected:
+
+ struct HashScalarData_t
+ {
+ unsigned int m_uiKey;
+ Data m_Data;
+ };
+
+ unsigned int m_uiBucketMask;
+ HashScalarData_t *m_pData;
+ int m_maxData;
+ int m_dataCount;
+};
+
+template<class Data, class CHashFunction> CUtlScalarHash<Data, CHashFunction>::CUtlScalarHash()
+{
+ m_pData = NULL;
+ m_uiBucketMask = 0;
+ m_maxData = 0;
+ m_dataCount = 0;
+}
+
+template<class Data, class CHashFunction> CUtlScalarHash<Data, CHashFunction>::~CUtlScalarHash()
+{
+ delete[] m_pData;
+}
+
+template<class Data, class CHashFunction> bool CUtlScalarHash<Data, CHashFunction>::Init( int nBucketCount )
+{
+ Assert(m_dataCount==0);
+ m_maxData = SmallestPowerOfTwoGreaterOrEqual(nBucketCount);
+ int elementCount = m_maxData * 2;
+ m_pData = new HashScalarData_t[elementCount];
+ m_uiBucketMask = elementCount - 1;
+ RemoveAll();
+ return true;
+}
+
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::Grow()
+{
+ ASSERT_NO_REENTRY();
+ int oldElementCount = m_maxData * 2;
+ HashScalarData_t *pOldData = m_pData;
+
+ // Grow to a minimum size of 16
+ m_maxData = MAX( oldElementCount, 16 );
+ int elementCount = m_maxData * 2;
+ m_pData = new HashScalarData_t[elementCount];
+ m_uiBucketMask = elementCount-1;
+ m_dataCount = 0;
+ for ( int i = 0; i < elementCount; i++ )
+ {
+ m_pData[i].m_uiKey = InvalidHandle();
+ }
+ for ( int i = 0; i < oldElementCount; i++ )
+ {
+ if ( pOldData[i].m_uiKey != (unsigned)InvalidHandle() )
+ {
+ Insert( pOldData[i].m_uiKey, pOldData[i].m_Data );
+ }
+ }
+ delete[] pOldData;
+}
+
+template<class Data, class CHashFunction> UtlHashFastHandle_t CUtlScalarHash<Data, CHashFunction>::Insert( unsigned int uiKey, const Data &data )
+{
+ if ( m_dataCount >= m_maxData )
+ {
+ Grow();
+ }
+ m_dataCount++;
+ Assert(uiKey != (uint)InvalidHandle()); // This hash stores less data by assuming uiKey != ~0
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ index = (index+1) & m_uiBucketMask;
+ }
+ m_pData[index].m_uiKey = uiKey;
+ m_pData[index].m_Data = data;
+
+ return index;
+}
+
+// Removal.
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::Remove( UtlHashFastHandle_t hHash )
+{
+ int mid = (m_uiBucketMask+1) / 2;
+ int lastRemoveIndex = hHash;
+ // remove the item
+ m_pData[lastRemoveIndex].m_uiKey = InvalidHandle();
+ m_dataCount--;
+
+ // now search for any items needing to be swapped down
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ for ( int index = (hHash+1) & m_uiBucketMask; m_pData[index].m_uiKey != endOfList; index = (index+1) & m_uiBucketMask )
+ {
+ int ideal = CHashFunction::HashKey32(m_pData[index].m_uiKey) & m_uiBucketMask;
+
+ // is the ideal index for this element <= (in a wrapped buffer sense) the ideal index of the removed element?
+ // if so, swap
+ int diff = ideal - lastRemoveIndex;
+ if ( diff > mid )
+ {
+ diff -= (m_uiBucketMask+1);
+ }
+ if ( diff < -mid )
+ {
+ diff += (m_uiBucketMask+1);
+ }
+
+ // should I swap this?
+ if ( diff <= 0 )
+ {
+ m_pData[lastRemoveIndex] = m_pData[index];
+ lastRemoveIndex = index;
+ m_pData[index].m_uiKey = InvalidHandle();
+ }
+ }
+}
+
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::FindAndRemove( unsigned int uiKey, const Data &dataRecord )
+{
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ if ( m_pData[index].m_uiKey == uiKey && m_pData[index].m_Data == dataRecord )
+ {
+ Remove(index);
+ return;
+ }
+ index = (index+1) & m_uiBucketMask;
+ }
+}
+
+template<class Data, class CHashFunction> void CUtlScalarHash<Data, CHashFunction>::RemoveAll( void )
+{
+ int elementCount = m_maxData * 2;
+ for ( int i = 0; i < elementCount; i++ )
+ {
+ m_pData[i].m_uiKey = (unsigned)InvalidHandle();
+ }
+ m_dataCount = 0;
+}
+
+// Retrieval.
+template<class Data, class CHashFunction> UtlHashFastHandle_t CUtlScalarHash<Data, CHashFunction>::Find( unsigned int uiKey, const Data &dataRecord ) const
+{
+ if ( m_pData == NULL )
+ return InvalidHandle();
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ if ( m_pData[index].m_uiKey == uiKey && m_pData[index].m_Data == dataRecord )
+ return index;
+ index = (index+1) & m_uiBucketMask;
+ }
+ return InvalidHandle();
+}
+
+template<class Data, class CHashFunction> UtlHashFastHandle_t CUtlScalarHash<Data, CHashFunction>::FindByUniqueKey( unsigned int uiKey ) const
+{
+ if ( m_pData == NULL )
+ return InvalidHandle();
+ int index = CHashFunction::HashKey32(uiKey) & m_uiBucketMask;
+ unsigned int endOfList = (unsigned int)InvalidHandle();
+ while ( m_pData[index].m_uiKey != endOfList )
+ {
+ if ( m_pData[index].m_uiKey == uiKey )
+ return index;
+ index = (index+1) & m_uiBucketMask;
+ }
+ return InvalidHandle();
+}
+
+
+#endif // UTLHASH_H
diff --git a/external/vpc/public/tier1/utllinkedlist.h b/external/vpc/public/tier1/utllinkedlist.h
new file mode 100644
index 0000000..fcd5ba9
--- /dev/null
+++ b/external/vpc/public/tier1/utllinkedlist.h
@@ -0,0 +1,1087 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Linked list container class
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLLINKEDLIST_H
+#define UTLLINKEDLIST_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/basetypes.h"
+#include "utlmemory.h"
+#include "utlfixedmemory.h"
+#include "utlblockmemory.h"
+#include "tier0/dbg.h"
+
+// define to enable asserts griping about things you shouldn't be doing with multilists
+// #define MULTILIST_PEDANTIC_ASSERTS 1
+
+// This is a useful macro to iterate from head to tail in a linked list.
+#define FOR_EACH_LL( listName, iteratorName ) \
+ for( int iteratorName=listName.Head(); iteratorName != listName.InvalidIndex(); iteratorName = listName.Next( iteratorName ) )
+
+//-----------------------------------------------------------------------------
+// class CUtlLinkedList:
+// description:
+// A lovely index-based linked list! T is the class type, I is the index
+// type, which usually should be an unsigned short or smaller. However,
+// you must avoid using 16- or 8-bit arithmetic on PowerPC architectures;
+// therefore you should not use UtlLinkedListElem_t::I as the type of
+// a local variable... ever. PowerPC integer arithmetic must be 32- or
+// 64-bit only; otherwise performance plummets.
+//-----------------------------------------------------------------------------
+
+template <class T, class I>
+struct UtlLinkedListElem_t
+{
+ T m_Element;
+ I m_Previous;
+ I m_Next;
+
+private:
+ // No copy constructor for these...
+ UtlLinkedListElem_t( const UtlLinkedListElem_t& );
+};
+
+
+// Class S is the storage type; the type you can use to save off indices in
+// persistent memory. Class I is the iterator type, which is what should be used
+// in local scopes. I defaults to be S, but be aware that on the 360, 16-bit
+// arithmetic is catastrophically slow. Therefore you should try to save shorts
+// in memory, but always operate on 32's or 64's in local scope.
+// The ideal parameter order would be TSMI (you are more likely to override M than I)
+// but since M depends on I we can't have the defaults in that order, alas.
+template <class T, class S = unsigned short, bool ML = false, class I = S, class M = CUtlMemory< UtlLinkedListElem_t<T, S>, I > >
+class CUtlLinkedList
+{
+public:
+ typedef T ElemType_t;
+ typedef S IndexType_t; // should really be called IndexStorageType_t, but that would be a huge change
+ typedef I IndexLocalType_t;
+ typedef M MemoryAllocator_t;
+
+ // constructor, destructor
+ CUtlLinkedList( int growSize = 0, int initSize = 0 );
+ ~CUtlLinkedList();
+
+ // gets particular elements
+ T& Element( I i );
+ T const& Element( I i ) const;
+ T& operator[]( I i );
+ T const& operator[]( I i ) const;
+
+ // Make sure we have a particular amount of memory
+ void EnsureCapacity( int num );
+
+ void SetGrowSize( int growSize );
+
+ // Memory deallocation
+ void Purge();
+
+ // Delete all the elements then call Purge.
+ void PurgeAndDeleteElements();
+
+ // Insertion methods....
+ I InsertBefore( I before );
+ I InsertAfter( I after );
+ I AddToHead( );
+ I AddToTail( );
+
+ I InsertBefore( I before, T const& src );
+ I InsertAfter( I after, T const& src );
+ I AddToHead( T const& src );
+ I AddToTail( T const& src );
+
+ // Find an element and return its index or InvalidIndex() if it couldn't be found.
+ I Find( const T &src ) const;
+
+ // Look for the element. If it exists, remove it and return true. Otherwise, return false.
+ bool FindAndRemove( const T &src );
+
+ // Removal methods
+ void Remove( I elem );
+ void RemoveAll();
+
+ // Allocation/deallocation methods
+ // If multilist == true, then list list may contain many
+ // non-connected lists, and IsInList and Head + Tail are meaningless...
+ I Alloc( bool multilist = false );
+ void Free( I elem );
+
+ // Identify the owner of this linked list's memory:
+ void SetAllocOwner( const char *pszAllocOwner );
+
+ // list modification
+ void LinkBefore( I before, I elem );
+ void LinkAfter( I after, I elem );
+ void Unlink( I elem );
+ void LinkToHead( I elem );
+ void LinkToTail( I elem );
+
+ // invalid index (M will never allocate an element at this index)
+ inline static S InvalidIndex() { return ( S )M::InvalidIndex(); }
+
+ // Is a given index valid to use? (representible by S and not the invalid index)
+ static bool IndexInRange( I index );
+
+ inline static size_t ElementSize() { return sizeof( ListElem_t ); }
+
+ // list statistics
+ int Count() const;
+ I MaxElementIndex() const;
+ I NumAllocated( void ) const { return m_NumAlloced; }
+
+ // Traversing the list
+ I Head() const;
+ I Tail() const;
+ I Previous( I i ) const;
+ I Next( I i ) const;
+
+ // Are nodes in the list or valid?
+ bool IsValidIndex( I i ) const;
+ bool IsInList( I i ) const;
+
+protected:
+
+ // What the linked list element looks like
+ typedef UtlLinkedListElem_t<T, S> ListElem_t;
+
+ // constructs the class
+ I AllocInternal( bool multilist = false );
+ void ConstructList();
+
+ // Gets at the list element....
+ ListElem_t& InternalElement( I i ) { return m_Memory[i]; }
+ ListElem_t const& InternalElement( I i ) const { return m_Memory[i]; }
+
+ // copy constructors not allowed
+ CUtlLinkedList( CUtlLinkedList<T, S, ML, I, M> const& list ) { Assert(0); }
+
+ M m_Memory;
+ I m_Head;
+ I m_Tail;
+ I m_FirstFree;
+ I m_ElementCount; // The number actually in the list
+ I m_NumAlloced; // The number of allocated elements
+ typename M::Iterator_t m_LastAlloc; // the last index allocated
+
+ // For debugging purposes;
+ // it's in release builds so this can be used in libraries correctly
+ ListElem_t *m_pElements;
+
+ FORCEINLINE M const &Memory( void ) const
+ {
+ return m_Memory;
+ }
+
+ void ResetDbgInfo()
+ {
+ m_pElements = m_Memory.Base();
+ }
+};
+
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T >
+class CUtlFixedLinkedList : public CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >
+{
+public:
+ CUtlFixedLinkedList( int growSize = 0, int initSize = 0 )
+ : CUtlLinkedList< T, intp, true, intp, CUtlFixedMemory< UtlLinkedListElem_t< T, intp > > >( growSize, initSize ) {}
+
+ bool IsValidIndex( intp i ) const
+ {
+ if ( !this->Memory().IsIdxValid( i ) )
+ return false;
+
+#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElementIndex
+ if ( this->Memory().IsIdxAfter( i, this->m_LastAlloc ) )
+ {
+ Assert( 0 );
+ return false; // don't read values that have been allocated, but not constructed
+ }
+#endif
+
+ return ( this->Memory()[ i ].m_Previous != i ) || ( this->Memory()[ i ].m_Next == i );
+ }
+
+private:
+ int MaxElementIndex() const { Assert( 0 ); return this->InvalidIndex(); } // fixedmemory containers don't support iteration from 0..maxelements-1
+ void ResetDbgInfo() {}
+};
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T, class I = unsigned short >
+class CUtlBlockLinkedList : public CUtlLinkedList< T, I, true, I, CUtlBlockMemory< UtlLinkedListElem_t< T, I >, I > >
+{
+public:
+ CUtlBlockLinkedList( int growSize = 0, int initSize = 0 )
+ : CUtlLinkedList< T, I, true, I, CUtlBlockMemory< UtlLinkedListElem_t< T, I >, I > >( growSize, initSize ) {}
+protected:
+ void ResetDbgInfo() {}
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+CUtlLinkedList<T,S,ML,I,M>::CUtlLinkedList( int growSize, int initSize ) :
+ m_Memory( growSize, initSize ), m_LastAlloc( m_Memory.InvalidIterator() )
+{
+ // Prevent signed non-int datatypes
+ COMPILE_TIME_ASSERT( sizeof(S) == 4 || ( ( (S)-1 ) > 0 ) );
+ ConstructList();
+ ResetDbgInfo();
+}
+
+template <class T, class S, bool ML, class I, class M>
+CUtlLinkedList<T,S,ML,I,M>::~CUtlLinkedList( )
+{
+ RemoveAll();
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::ConstructList()
+{
+ m_Head = InvalidIndex();
+ m_Tail = InvalidIndex();
+ m_FirstFree = InvalidIndex();
+ m_ElementCount = 0;
+ m_NumAlloced = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+inline T& CUtlLinkedList<T,S,ML,I,M>::Element( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline T const& CUtlLinkedList<T,S,ML,I,M>::Element( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline T& CUtlLinkedList<T,S,ML,I,M>::operator[]( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline T const& CUtlLinkedList<T,S,ML,I,M>::operator[]( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+//-----------------------------------------------------------------------------
+// list statistics
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+inline int CUtlLinkedList<T,S,ML,I,M>::Count() const
+{
+#ifdef MULTILIST_PEDANTIC_ASSERTS
+ AssertMsg( !ML, "CUtlLinkedList::Count() is meaningless for linked lists." );
+#endif
+ return m_ElementCount;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::MaxElementIndex() const
+{
+ return m_Memory.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Traversing the list
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Head() const
+{
+ return m_Head;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Tail() const
+{
+ return m_Tail;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Previous( I i ) const
+{
+ Assert( IsValidIndex(i) );
+ return InternalElement(i).m_Previous;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::Next( I i ) const
+{
+ Assert( IsValidIndex(i) );
+ return InternalElement(i).m_Next;
+}
+
+
+//-----------------------------------------------------------------------------
+// Are nodes in the list or valid?
+//-----------------------------------------------------------------------------
+
+#pragma warning(push)
+#pragma warning( disable: 4310 ) // Allows "(I)(S)M::INVALID_INDEX" below
+template <class T, class S, bool ML, class I, class M>
+inline bool CUtlLinkedList<T,S,ML,I,M>::IndexInRange( I index ) // Static method
+{
+ // Since S is not necessarily the type returned by M, we need to check that M returns indices
+ // which are representable by S. A common case is 'S === unsigned short', 'I == int', in which
+ // case CUtlMemory will have 'InvalidIndex == (int)-1' (which casts to 65535 in S), and will
+ // happily return elements at index 65535 and above.
+
+ // Do some static checks here:
+ // 'I' needs to be able to store 'S'
+ COMPILE_TIME_ASSERT( sizeof(I) >= sizeof(S) );
+ // 'S' should be unsigned (to avoid signed arithmetic errors for plausibly exhaustible ranges)
+ COMPILE_TIME_ASSERT( ( sizeof(S) > 2 ) || ( ( (S)-1 ) > 0 ) );
+ // M::INVALID_INDEX should be storable in S to avoid ambiguities (e.g. with 65536)
+ COMPILE_TIME_ASSERT( ( M::INVALID_INDEX == -1 ) || ( M::INVALID_INDEX == (S)M::INVALID_INDEX ) );
+
+ return ( ( (S)index == index ) && ( (S)index != InvalidIndex() ) );
+}
+#pragma warning(pop)
+
+template <class T, class S, bool ML, class I, class M>
+inline bool CUtlLinkedList<T,S,ML,I,M>::IsValidIndex( I i ) const
+{
+ if ( !m_Memory.IsIdxValid( i ) )
+ return false;
+
+ if ( m_Memory.IsIdxAfter( i, m_LastAlloc ) )
+ return false; // don't read values that have been allocated, but not constructed
+
+ return ( m_Memory[ i ].m_Previous != i ) || ( m_Memory[ i ].m_Next == i );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline bool CUtlLinkedList<T,S,ML,I,M>::IsInList( I i ) const
+{
+ if ( !m_Memory.IsIdxValid( i ) || m_Memory.IsIdxAfter( i, m_LastAlloc ) )
+ return false; // don't read values that have been allocated, but not constructed
+
+ return Previous( i ) != i;
+}
+
+/*
+template <class T>
+inline bool CUtlFixedLinkedList<T>::IsInList( int i ) const
+{
+ return m_Memory.IsIdxValid( i ) && (Previous( i ) != i);
+}
+*/
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+
+template< class T, class S, bool ML, class I, class M >
+void CUtlLinkedList<T,S,ML,I,M>::EnsureCapacity( int num )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+template< class T, class S, bool ML, class I, class M >
+void CUtlLinkedList<T,S,ML,I,M>::SetGrowSize( int growSize )
+{
+ RemoveAll();
+ m_Memory.Init( growSize );
+ ResetDbgInfo();
+}
+
+template< class T, class S, bool ML, class I, class M >
+void CUtlLinkedList<T,S,ML,I,M>::SetAllocOwner( const char *pszAllocOwner )
+{
+ m_Memory.SetAllocOwner( pszAllocOwner );
+}
+
+
+//-----------------------------------------------------------------------------
+// Deallocate memory
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Purge()
+{
+ RemoveAll();
+
+ m_Memory.Purge();
+ m_FirstFree = InvalidIndex();
+ m_NumAlloced = 0;
+
+ //Routing "m_LastAlloc = m_Memory.InvalidIterator();" through a local const to sidestep an internal compiler error on 360 builds
+ const typename M::Iterator_t scInvalidIterator = m_Memory.InvalidIterator();
+ m_LastAlloc = scInvalidIterator;
+ ResetDbgInfo();
+}
+
+
+template<class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::PurgeAndDeleteElements()
+{
+ I iNext;
+ for( I i=Head(); i != InvalidIndex(); i=iNext )
+ {
+ iNext = Next(i);
+ delete Element(i);
+ }
+
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Node allocation/deallocation
+//-----------------------------------------------------------------------------
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::AllocInternal( bool multilist )
+{
+ Assert( !multilist || ML );
+#ifdef MULTILIST_PEDANTIC_ASSERTS
+ Assert( multilist == ML );
+#endif
+ I elem;
+ if ( m_FirstFree == InvalidIndex() )
+ {
+ Assert( m_Memory.IsValidIterator( m_LastAlloc ) || m_ElementCount == 0 );
+
+ typename M::Iterator_t it = m_Memory.IsValidIterator( m_LastAlloc ) ? m_Memory.Next( m_LastAlloc ) : m_Memory.First();
+
+ if ( !m_Memory.IsValidIterator( it ) )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.Grow();
+ ResetDbgInfo();
+
+ it = m_Memory.IsValidIterator( m_LastAlloc ) ? m_Memory.Next( m_LastAlloc ) : m_Memory.First();
+
+ Assert( m_Memory.IsValidIterator( it ) );
+ if ( !m_Memory.IsValidIterator( it ) )
+ {
+ ExecuteNTimes( 10, Warning( "CUtlLinkedList overflow! (exhausted memory allocator)\n" ) );
+ return InvalidIndex();
+ }
+ }
+
+ // We can overflow before the utlmemory overflows, since S != I
+ if ( !IndexInRange( m_Memory.GetIndex( it ) ) )
+ {
+ ExecuteNTimes( 10, Warning( "CUtlLinkedList overflow! (exhausted index range)\n" ) );
+ return InvalidIndex();
+ }
+
+ m_LastAlloc = it;
+ elem = m_Memory.GetIndex( m_LastAlloc );
+ m_NumAlloced++;
+ }
+ else
+ {
+ elem = m_FirstFree;
+ m_FirstFree = InternalElement( m_FirstFree ).m_Next;
+ }
+
+ if ( !multilist )
+ {
+ InternalElement( elem ).m_Next = elem;
+ InternalElement( elem ).m_Previous = elem;
+ }
+ else
+ {
+ InternalElement( elem ).m_Next = InvalidIndex();
+ InternalElement( elem ).m_Previous = InvalidIndex();
+ }
+
+ return elem;
+}
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::Alloc( bool multilist )
+{
+ I elem = AllocInternal( multilist );
+ if ( elem == InvalidIndex() )
+ return elem;
+
+ Construct( &Element(elem) );
+
+ return elem;
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Free( I elem )
+{
+ Assert( IsValidIndex(elem) && IndexInRange( elem ) );
+ Unlink(elem);
+
+ ListElem_t &internalElem = InternalElement(elem);
+ Destruct( &internalElem.m_Element );
+ internalElem.m_Next = m_FirstFree;
+ m_FirstFree = elem;
+}
+
+//-----------------------------------------------------------------------------
+// Insertion methods; allocates and links (uses default constructor)
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertBefore( I before )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkBefore( before, newNode );
+
+ // Construct the data
+ Construct( &Element(newNode) );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertAfter( I after )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkAfter( after, newNode );
+
+ // Construct the data
+ Construct( &Element(newNode) );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToHead( )
+{
+ return InsertAfter( InvalidIndex() );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToTail( )
+{
+ return InsertBefore( InvalidIndex() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Insertion methods; allocates and links (uses copy constructor)
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertBefore( I before, T const& src )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkBefore( before, newNode );
+
+ // Construct the data
+ CopyConstruct( &Element(newNode), src );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::InsertAfter( I after, T const& src )
+{
+ // Make a new node
+ I newNode = AllocInternal();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkAfter( after, newNode );
+
+ // Construct the data
+ CopyConstruct( &Element(newNode), src );
+
+ return newNode;
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToHead( T const& src )
+{
+ return InsertAfter( InvalidIndex(), src );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline I CUtlLinkedList<T,S,ML,I,M>::AddToTail( T const& src )
+{
+ return InsertBefore( InvalidIndex(), src );
+}
+
+
+//-----------------------------------------------------------------------------
+// Removal methods
+//-----------------------------------------------------------------------------
+
+template<class T, class S, bool ML, class I, class M>
+I CUtlLinkedList<T,S,ML,I,M>::Find( const T &src ) const
+{
+ for ( I i=Head(); i != InvalidIndex(); i = Next( i ) )
+ {
+ if ( Element( i ) == src )
+ return i;
+ }
+ return InvalidIndex();
+}
+
+
+template<class T, class S, bool ML, class I, class M>
+bool CUtlLinkedList<T,S,ML,I,M>::FindAndRemove( const T &src )
+{
+ I i = Find( src );
+ if ( i == InvalidIndex() )
+ {
+ return false;
+ }
+ else
+ {
+ Remove( i );
+ return true;
+ }
+}
+
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Remove( I elem )
+{
+ Free( elem );
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::RemoveAll()
+{
+ // Have to do some convoluted stuff to invoke the destructor on all
+ // valid elements for the multilist case (since we don't have all elements
+ // connected to each other in a list).
+
+ if ( m_LastAlloc == m_Memory.InvalidIterator() )
+ {
+ Assert( m_Head == InvalidIndex() );
+ Assert( m_Tail == InvalidIndex() );
+ Assert( m_FirstFree == InvalidIndex() );
+ Assert( m_ElementCount == 0 );
+ return;
+ }
+
+ if ( ML )
+ {
+ for ( typename M::Iterator_t it = m_Memory.First(); it != m_Memory.InvalidIterator(); it = m_Memory.Next( it ) )
+ {
+ I i = m_Memory.GetIndex( it );
+ if ( IsValidIndex( i ) ) // skip elements already in the free list
+ {
+ ListElem_t &internalElem = InternalElement( i );
+ Destruct( &internalElem.m_Element );
+ internalElem.m_Previous = i;
+ internalElem.m_Next = m_FirstFree;
+ m_FirstFree = i;
+ }
+
+ if ( it == m_LastAlloc )
+ break; // don't destruct elements that haven't ever been constructed
+ }
+ }
+ else
+ {
+ I i = Head();
+ I next;
+ while ( i != InvalidIndex() )
+ {
+ next = Next( i );
+ ListElem_t &internalElem = InternalElement( i );
+ Destruct( &internalElem.m_Element );
+ internalElem.m_Previous = i;
+ internalElem.m_Next = next == InvalidIndex() ? m_FirstFree : next;
+ i = next;
+ }
+ if ( Head() != InvalidIndex() )
+ {
+ m_FirstFree = Head();
+ }
+ }
+
+ // Clear everything else out
+ m_Head = InvalidIndex();
+ m_Tail = InvalidIndex();
+ m_ElementCount = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// list modification
+//-----------------------------------------------------------------------------
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::LinkBefore( I before, I elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ // Unlink it if it's in the list at the moment
+ Unlink(elem);
+
+ ListElem_t * pNewElem = &InternalElement(elem);
+
+ // The element *after* our newly linked one is the one we linked before.
+ pNewElem->m_Next = before;
+
+ S newElem_mPrevious; // we need to hang on to this for the compairson against InvalidIndex()
+ // below; otherwise we get a a load-hit-store on pNewElem->m_Previous, even
+ // with
+ if (before == InvalidIndex())
+ {
+ // In this case, we're linking to the end of the list, so reset the tail
+ newElem_mPrevious = m_Tail;
+ pNewElem->m_Previous = m_Tail;
+ m_Tail = elem;
+ }
+ else
+ {
+ // Here, we're not linking to the end. Set the prev pointer to point to
+ // the element we're linking.
+ Assert( IsInList(before) );
+ ListElem_t * beforeElem = &InternalElement(before);
+ pNewElem->m_Previous = newElem_mPrevious = beforeElem->m_Previous;
+ beforeElem->m_Previous = elem;
+ }
+
+ // Reset the head if we linked to the head of the list
+ if (newElem_mPrevious == InvalidIndex())
+ m_Head = elem;
+ else
+ InternalElement(newElem_mPrevious).m_Next = elem;
+
+ // one more element baby
+ ++m_ElementCount;
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::LinkAfter( I after, I elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ // Unlink it if it's in the list at the moment
+ if ( IsInList(elem) )
+ Unlink(elem);
+
+ ListElem_t& newElem = InternalElement(elem);
+
+ // The element *before* our newly linked one is the one we linked after
+ newElem.m_Previous = after;
+ if (after == InvalidIndex())
+ {
+ // In this case, we're linking to the head of the list, reset the head
+ newElem.m_Next = m_Head;
+ m_Head = elem;
+ }
+ else
+ {
+ // Here, we're not linking to the end. Set the next pointer to point to
+ // the element we're linking.
+ Assert( IsInList(after) );
+ ListElem_t& afterElem = InternalElement(after);
+ newElem.m_Next = afterElem.m_Next;
+ afterElem.m_Next = elem;
+ }
+
+ // Reset the tail if we linked to the tail of the list
+ if (newElem.m_Next == InvalidIndex())
+ m_Tail = elem;
+ else
+ InternalElement(newElem.m_Next).m_Previous = elem;
+
+ // one more element baby
+ ++m_ElementCount;
+}
+
+template <class T, class S, bool ML, class I, class M>
+void CUtlLinkedList<T,S,ML,I,M>::Unlink( I elem )
+{
+ Assert( IsValidIndex(elem) );
+ if (IsInList(elem))
+ {
+ ListElem_t * pOldElem = &m_Memory[ elem ];
+
+ // If we're the first guy, reset the head
+ // otherwise, make our previous node's next pointer = our next
+ if ( pOldElem->m_Previous != InvalidIndex() )
+ {
+ m_Memory[ pOldElem->m_Previous ].m_Next = pOldElem->m_Next;
+ }
+ else
+ {
+ m_Head = pOldElem->m_Next;
+ }
+
+ // If we're the last guy, reset the tail
+ // otherwise, make our next node's prev pointer = our prev
+ if ( pOldElem->m_Next != InvalidIndex() )
+ {
+ m_Memory[ pOldElem->m_Next ].m_Previous = pOldElem->m_Previous;
+ }
+ else
+ {
+ m_Tail = pOldElem->m_Previous;
+ }
+
+ // This marks this node as not in the list,
+ // but not in the free list either
+ pOldElem->m_Previous = pOldElem->m_Next = elem;
+
+ // One less puppy
+ --m_ElementCount;
+ }
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline void CUtlLinkedList<T,S,ML,I,M>::LinkToHead( I elem )
+{
+ LinkAfter( InvalidIndex(), elem );
+}
+
+template <class T, class S, bool ML, class I, class M>
+inline void CUtlLinkedList<T,S,ML,I,M>::LinkToTail( I elem )
+{
+ LinkBefore( InvalidIndex(), elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// Class to drop in to replace a CUtlLinkedList that needs to be more memory agressive
+//-----------------------------------------------------------------------------
+
+DECLARE_POINTER_HANDLE( UtlPtrLinkedListIndex_t ); // to enforce correct usage
+
+template < typename T >
+class CUtlPtrLinkedList
+{
+public:
+ CUtlPtrLinkedList()
+ : m_pFirst( NULL ),
+ m_nElems( 0 )
+ {
+ COMPILE_TIME_ASSERT( sizeof(IndexType_t) == sizeof(Node_t *) );
+ }
+
+ ~CUtlPtrLinkedList()
+ {
+ RemoveAll();
+ }
+
+ typedef UtlPtrLinkedListIndex_t IndexType_t;
+
+ T &operator[]( IndexType_t i )
+ {
+ return (( Node_t * )i)->elem;
+ }
+
+ const T &operator[]( IndexType_t i ) const
+ {
+ return (( Node_t * )i)->elem;
+ }
+
+ IndexType_t AddToTail()
+ {
+ return DoInsertBefore( (IndexType_t)m_pFirst, NULL );
+ }
+
+ IndexType_t AddToTail( T const& src )
+ {
+ return DoInsertBefore( (IndexType_t)m_pFirst, &src );
+ }
+
+ IndexType_t AddToHead()
+ {
+ IndexType_t result = DoInsertBefore( (IndexType_t)m_pFirst, NULL );
+ m_pFirst = ((Node_t *)result);
+ return result;
+ }
+
+ IndexType_t AddToHead( T const& src )
+ {
+ IndexType_t result = DoInsertBefore( (IndexType_t)m_pFirst, &src );
+ m_pFirst = ((Node_t *)result);
+ return result;
+ }
+
+ IndexType_t InsertBefore( IndexType_t before )
+ {
+ return DoInsertBefore( before, NULL );
+ }
+
+ IndexType_t InsertAfter( IndexType_t after )
+ {
+ Node_t *pBefore = ((Node_t *)after)->next;
+ return DoInsertBefore( pBefore, NULL );
+ }
+
+ IndexType_t InsertBefore( IndexType_t before, T const& src )
+ {
+ return DoInsertBefore( before, &src );
+ }
+
+ IndexType_t InsertAfter( IndexType_t after, T const& src )
+ {
+ Node_t *pBefore = ((Node_t *)after)->next;
+ return DoInsertBefore( pBefore, &src );
+ }
+
+ void Remove( IndexType_t elem )
+ {
+ Node_t *p = (Node_t *)elem;
+
+ if ( p->pNext == p )
+ {
+ m_pFirst = NULL;
+ }
+ else
+ {
+ if ( m_pFirst == p )
+ {
+ m_pFirst = p->pNext;
+ }
+ p->pNext->pPrev = p->pPrev;
+ p->pPrev->pNext = p->pNext;
+ }
+
+ delete p;
+ m_nElems--;
+ }
+
+ void RemoveAll()
+ {
+ Node_t *p = m_pFirst;
+ if ( p )
+ {
+ do
+ {
+ Node_t *pNext = p->pNext;
+ delete p;
+ p = pNext;
+ } while( p != m_pFirst );
+ }
+
+ m_pFirst = NULL;
+ m_nElems = 0;
+ }
+
+ int Count() const
+ {
+ return m_nElems;
+ }
+
+ IndexType_t Head() const
+ {
+ return (IndexType_t)m_pFirst;
+ }
+
+ IndexType_t Next( IndexType_t i ) const
+ {
+ Node_t *p = ((Node_t *)i)->pNext;
+ if ( p != m_pFirst )
+ {
+ return (IndexType_t)p;
+ }
+ return NULL;
+ }
+
+ bool IsValidIndex( IndexType_t i ) const
+ {
+ Node_t *p = ((Node_t *)i);
+ return ( p && p->pNext && p->pPrev );
+ }
+
+ inline static IndexType_t InvalidIndex()
+ {
+ return NULL;
+ }
+private:
+
+ struct Node_t
+ {
+ Node_t() {}
+ Node_t( const T &_elem ) : elem( _elem ) {}
+
+ T elem;
+ Node_t *pPrev, *pNext;
+ };
+
+ Node_t *AllocNode( const T *pCopyFrom )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ Node_t *p;
+
+ if ( !pCopyFrom )
+ {
+ p = new Node_t;
+ }
+ else
+ {
+ p = new Node_t( *pCopyFrom );
+ }
+
+ return p;
+ }
+
+ IndexType_t DoInsertBefore( IndexType_t before, const T *pCopyFrom )
+ {
+ Node_t *p = AllocNode( pCopyFrom );
+ Node_t *pBefore = (Node_t *)before;
+ if ( pBefore )
+ {
+ p->pNext = pBefore;
+ p->pPrev = pBefore->pPrev;
+ pBefore->pPrev = p;
+ p->pPrev->pNext = p;
+ }
+ else
+ {
+ Assert( !m_pFirst );
+ m_pFirst = p->pNext = p->pPrev = p;
+ }
+
+ m_nElems++;
+ return (IndexType_t)p;
+ }
+
+ Node_t *m_pFirst;
+ unsigned m_nElems;
+};
+
+//-----------------------------------------------------------------------------
+
+#endif // UTLLINKEDLIST_H
diff --git a/external/vpc/public/tier1/utlmap.h b/external/vpc/public/tier1/utlmap.h
new file mode 100644
index 0000000..aeca2b4
--- /dev/null
+++ b/external/vpc/public/tier1/utlmap.h
@@ -0,0 +1,248 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLMAP_H
+#define UTLMAP_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include "utlrbtree.h"
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: An associative container. Pretty much identical to std::map.
+//
+//-----------------------------------------------------------------------------
+
+// This is a useful macro to iterate from start to end in order in a map
+#define FOR_EACH_MAP( mapName, iteratorName ) \
+ for ( int iteratorName = (mapName).FirstInorder(); (mapName).IsUtlMap && iteratorName != (mapName).InvalidIndex(); iteratorName = (mapName).NextInorder( iteratorName ) )
+
+// faster iteration, but in an unspecified order
+#define FOR_EACH_MAP_FAST( mapName, iteratorName ) \
+ for ( int iteratorName = 0; (mapName).IsUtlMap && iteratorName < (mapName).MaxElement(); ++iteratorName ) if ( !(mapName).IsValidIndex( iteratorName ) ) continue; else
+
+struct base_utlmap_t
+{
+public:
+ static const bool IsUtlMap = true; // Used to match this at compiletime
+};
+
+#if defined( GNUC ) && defined( DEBUG )
+const bool base_utlmap_t::IsUtlMap SELECTANY;
+#endif
+
+template <typename K, typename T, typename I = unsigned short>
+class CUtlMap : public base_utlmap_t
+{
+public:
+ typedef K KeyType_t;
+ typedef T ElemType_t;
+ typedef I IndexType_t;
+
+ // Less func typedef
+ // Returns true if the first parameter is "less" than the second
+ typedef bool (*LessFunc_t)( const KeyType_t &, const KeyType_t & );
+
+ // constructor, destructor
+ // Left at growSize = 0, the memory will first allocate 1 element and double in size
+ // at each increment.
+ // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
+ CUtlMap( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 )
+ : m_Tree( growSize, initSize, CKeyLess( lessfunc ) )
+ {
+ }
+
+ CUtlMap( LessFunc_t lessfunc )
+ : m_Tree( CKeyLess( lessfunc ) )
+ {
+ }
+
+ void EnsureCapacity( int num ) { m_Tree.EnsureCapacity( num ); }
+
+ // gets particular elements
+ ElemType_t & Element( IndexType_t i ) { return m_Tree.Element( i ).elem; }
+ const ElemType_t & Element( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
+ ElemType_t & operator[]( IndexType_t i ) { return m_Tree.Element( i ).elem; }
+ const ElemType_t & operator[]( IndexType_t i ) const { return m_Tree.Element( i ).elem; }
+ KeyType_t & Key( IndexType_t i ) { return m_Tree.Element( i ).key; }
+ const KeyType_t & Key( IndexType_t i ) const { return m_Tree.Element( i ).key; }
+
+
+ // Num elements
+ unsigned int Count() const { return m_Tree.Count(); }
+
+ // Max "size" of the vector
+ IndexType_t MaxElement() const { return m_Tree.MaxElement(); }
+
+ // Checks if a node is valid and in the map
+ bool IsValidIndex( IndexType_t i ) const { return m_Tree.IsValidIndex( i ); }
+
+ // Checks if the map as a whole is valid
+ bool IsValid() const { return m_Tree.IsValid(); }
+
+ // Invalid index
+ static IndexType_t InvalidIndex() { return CTree::InvalidIndex(); }
+
+ // Sets the less func
+ void SetLessFunc( LessFunc_t func )
+ {
+ m_Tree.SetLessFunc( CKeyLess( func ) );
+ }
+
+ // Insert method (inserts in order)
+ IndexType_t Insert( const KeyType_t &key, const ElemType_t &insert )
+ {
+ Node_t node;
+ node.key = key;
+ node.elem = insert;
+ return m_Tree.Insert( node );
+ }
+
+ IndexType_t Insert( const KeyType_t &key )
+ {
+ Node_t node;
+ node.key = key;
+ return m_Tree.Insert( node );
+ }
+
+ // Find method
+ IndexType_t Find( const KeyType_t &key ) const
+ {
+ Node_t dummyNode;
+ dummyNode.key = key;
+ return m_Tree.Find( dummyNode );
+ }
+
+ // Remove methods
+ void RemoveAt( IndexType_t i ) { m_Tree.RemoveAt( i ); }
+ bool Remove( const KeyType_t &key )
+ {
+ Node_t dummyNode;
+ dummyNode.key = key;
+ return m_Tree.Remove( dummyNode );
+ }
+
+ void RemoveAll( ) { m_Tree.RemoveAll(); }
+ void Purge( ) { m_Tree.Purge(); }
+
+ // Purges the list and calls delete on each element in it.
+ void PurgeAndDeleteElements();
+
+ // Iteration
+ IndexType_t FirstInorder() const { return m_Tree.FirstInorder(); }
+ IndexType_t NextInorder( IndexType_t i ) const { return m_Tree.NextInorder( i ); }
+ IndexType_t PrevInorder( IndexType_t i ) const { return m_Tree.PrevInorder( i ); }
+ IndexType_t LastInorder() const { return m_Tree.LastInorder(); }
+
+ // If you change the search key, this can be used to reinsert the
+ // element into the map.
+ void Reinsert( const KeyType_t &key, IndexType_t i )
+ {
+ m_Tree[i].key = key;
+ m_Tree.Reinsert(i);
+ }
+
+ IndexType_t InsertOrReplace( const KeyType_t &key, const ElemType_t &insert )
+ {
+ IndexType_t i = Find( key );
+ if ( i != InvalidIndex() )
+ {
+ Element( i ) = insert;
+ return i;
+ }
+
+ return Insert( key, insert );
+ }
+
+ void Swap( CUtlMap< K, T, I > &that )
+ {
+ m_Tree.Swap( that.m_Tree );
+ }
+
+
+ struct Node_t
+ {
+ Node_t()
+ {
+ }
+
+ Node_t( const Node_t &from )
+ : key( from.key ),
+ elem( from.elem )
+ {
+ }
+
+ KeyType_t key;
+ ElemType_t elem;
+ };
+
+ class CKeyLess
+ {
+ public:
+ CKeyLess( LessFunc_t lessFunc ) : m_LessFunc(lessFunc) {}
+
+ bool operator!() const
+ {
+ return !m_LessFunc;
+ }
+
+ bool operator()( const Node_t &left, const Node_t &right ) const
+ {
+ return m_LessFunc( left.key, right.key );
+ }
+
+ LessFunc_t m_LessFunc;
+ };
+
+ typedef CUtlRBTree<Node_t, I, CKeyLess> CTree;
+
+ CTree *AccessTree() { return &m_Tree; }
+
+protected:
+ CTree m_Tree;
+};
+
+//-----------------------------------------------------------------------------
+
+// Purges the list and calls delete on each element in it.
+template< typename K, typename T, typename I >
+inline void CUtlMap<K, T, I>::PurgeAndDeleteElements()
+{
+ for ( I i = 0; i < MaxElement(); ++i )
+ {
+ if ( !IsValidIndex( i ) )
+ continue;
+
+ delete Element( i );
+ }
+
+ Purge();
+}
+
+//-----------------------------------------------------------------------------
+
+// This is horrible and slow and meant to be used only when you're dealing with really
+// non-time/memory-critical code and desperately want to copy a whole map element-by-element
+// for whatever reason.
+template < typename K, typename T, typename I >
+void DeepCopyMap( const CUtlMap<K,T,I>& pmapIn, CUtlMap<K,T,I> *out_pmapOut )
+{
+ Assert( out_pmapOut );
+
+ out_pmapOut->Purge();
+ FOR_EACH_MAP_FAST( pmapIn, i )
+ {
+ out_pmapOut->Insert( i, pmapIn[i] );
+ }
+}
+
+#endif // UTLMAP_H
diff --git a/external/vpc/public/tier1/utlmemory.h b/external/vpc/public/tier1/utlmemory.h
new file mode 100644
index 0000000..40e6a19
--- /dev/null
+++ b/external/vpc/public/tier1/utlmemory.h
@@ -0,0 +1,1090 @@
+//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable memory class.
+//===========================================================================//
+
+#ifndef UTLMEMORY_H
+#define UTLMEMORY_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+#include <string.h>
+#include "tier0/platform.h"
+
+#include "tier0/memalloc.h"
+#include "mathlib/mathlib.h"
+#include "tier0/memdbgon.h"
+
+#pragma warning (disable:4100)
+#pragma warning (disable:4514)
+
+
+//-----------------------------------------------------------------------------
+
+
+#ifdef UTLMEMORY_TRACK
+#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlMemory||", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
+#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlMemory||", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 )
+#else
+#define UTLMEMORY_TRACK_ALLOC() ((void)0)
+#define UTLMEMORY_TRACK_FREE() ((void)0)
+#endif
+
+
+//-----------------------------------------------------------------------------
+// The CUtlMemory class:
+// A growable memory class which doubles in size by default.
+//-----------------------------------------------------------------------------
+template< class T, class I = int >
+class CUtlMemory
+{
+public:
+ // constructor, destructor
+ CUtlMemory( int nGrowSize = 0, int nInitSize = 0 );
+ CUtlMemory( T* pMemory, int numElements );
+ CUtlMemory( const T* pMemory, int numElements );
+ ~CUtlMemory();
+
+ // Set the size by which the memory grows
+ void Init( int nGrowSize = 0, int nInitSize = 0 );
+
+ class Iterator_t
+ {
+ public:
+ Iterator_t( I i ) : index( i ) {}
+ I index;
+
+ bool operator==( const Iterator_t it ) const { return index == it.index; }
+ bool operator!=( const Iterator_t it ) const { return index != it.index; }
+ };
+ Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); }
+ Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); }
+ I GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
+ bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); }
+ Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
+
+ // element access
+ T& operator[]( I i );
+ const T& operator[]( I i ) const;
+ T& Element( I i );
+ const T& Element( I i ) const;
+
+ // Can we use this index?
+ bool IsIdxValid( I i ) const;
+
+ // Specify the invalid ('null') index that we'll only return on failure
+ static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT
+ static I InvalidIndex() { return INVALID_INDEX; }
+
+ // Gets the base address (can change when adding elements!)
+ T* Base();
+ const T* Base() const;
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements );
+ void SetExternalBuffer( const T* pMemory, int numElements );
+ void AssumeMemory( T *pMemory, int nSize );
+ T* Detach();
+ void *DetachMemory();
+
+ // Fast swap
+ void Swap( CUtlMemory< T, I > &mem );
+
+ // Switches the buffer from an external memory buffer to a reallocatable buffer
+ // Will copy the current contents of the external buffer to the reallocatable buffer
+ void ConvertToGrowableMemory( int nGrowSize );
+
+ // Size
+ int NumAllocated() const;
+ int Count() const;
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 );
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num );
+
+ // Memory deallocation
+ void Purge();
+
+ // Purge all but the given number of elements
+ void Purge( int numElements );
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const;
+
+ // is the memory read only?
+ bool IsReadOnly() const;
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size );
+
+protected:
+ void ValidateGrowSize()
+ {
+#ifdef _X360
+ if ( m_nGrowSize && m_nGrowSize != EXTERNAL_BUFFER_MARKER )
+ {
+ // Max grow size at 128 bytes on XBOX
+ const int MAX_GROW = 128;
+ if ( m_nGrowSize * sizeof(T) > MAX_GROW )
+ {
+ m_nGrowSize = max( 1, MAX_GROW / sizeof(T) );
+ }
+ }
+#endif
+ }
+
+ enum
+ {
+ EXTERNAL_BUFFER_MARKER = -1,
+ EXTERNAL_CONST_BUFFER_MARKER = -2,
+ };
+
+ T* m_pMemory;
+ int m_nAllocationCount;
+ int m_nGrowSize;
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlMemory class:
+// A growable memory class which doubles in size by default.
+//-----------------------------------------------------------------------------
+template< class T, size_t SIZE, class I = int >
+class CUtlMemoryFixedGrowable : public CUtlMemory< T, I >
+{
+ typedef CUtlMemory< T, I > BaseClass;
+
+public:
+ CUtlMemoryFixedGrowable( int nGrowSize = 0, int nInitSize = SIZE ) : BaseClass( m_pFixedMemory, SIZE )
+ {
+ Assert( nInitSize == 0 || nInitSize == SIZE );
+ m_nMallocGrowSize = nGrowSize;
+ }
+
+ void Grow( int nCount = 1 )
+ {
+ if ( this->IsExternallyAllocated() )
+ {
+ this->ConvertToGrowableMemory( m_nMallocGrowSize );
+ }
+ BaseClass::Grow( nCount );
+ }
+
+ void EnsureCapacity( int num )
+ {
+ if ( CUtlMemory<T>::m_nAllocationCount >= num )
+ return;
+
+ if ( this->IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ this->ConvertToGrowableMemory( m_nMallocGrowSize );
+ }
+
+ BaseClass::EnsureCapacity( num );
+ }
+
+private:
+ int m_nMallocGrowSize;
+ T m_pFixedMemory[ SIZE ];
+};
+
+//-----------------------------------------------------------------------------
+// The CUtlMemoryFixed class:
+// A fixed memory class
+//-----------------------------------------------------------------------------
+template< typename T, size_t SIZE, int nAlignment = 0 >
+class CUtlMemoryFixed
+{
+public:
+ // constructor, destructor
+ CUtlMemoryFixed( int nGrowSize = 0, int nInitSize = 0 ) { Assert( nInitSize == 0 || nInitSize == SIZE ); }
+ CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Can we use this index?
+ bool IsIdxValid( int i ) const { return (i >= 0) && (i < SIZE); }
+
+ // Specify the invalid ('null') index that we'll only return on failure
+ static const int INVALID_INDEX = -1; // For use with COMPILE_TIME_ASSERT
+ static int InvalidIndex() { return INVALID_INDEX; }
+
+ // Gets the base address
+ T* Base() { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
+ const T* Base() const { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); }
+
+ // element access
+ T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+ T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Size
+ int NumAllocated() const { return SIZE; }
+ int Count() const { return SIZE; }
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 ) { Assert( 0 ); }
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num ) { Assert( num <= SIZE ); }
+
+ // Memory deallocation
+ void Purge() {}
+
+ // Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryFixed)
+ void Purge( int numElements ) { Assert( 0 ); }
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const { return false; }
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size ) {}
+
+ class Iterator_t
+ {
+ public:
+ Iterator_t( int i ) : index( i ) {}
+ int index;
+ bool operator==( const Iterator_t it ) const { return index == it.index; }
+ bool operator!=( const Iterator_t it ) const { return index != it.index; }
+ };
+ Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); }
+ Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); }
+ int GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( int i, const Iterator_t &it ) const { return i > it.index; }
+ bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); }
+ Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
+
+private:
+ char m_Memory[ SIZE*sizeof(T) + nAlignment ];
+};
+
+#ifdef _LINUX
+#define REMEMBER_ALLOC_SIZE_FOR_VALGRIND 1
+#endif
+
+//-----------------------------------------------------------------------------
+// The CUtlMemoryConservative class:
+// A dynamic memory class that tries to minimize overhead (itself small, no custom grow factor)
+//-----------------------------------------------------------------------------
+template< typename T >
+class CUtlMemoryConservative
+{
+
+public:
+ // constructor, destructor
+ CUtlMemoryConservative( int nGrowSize = 0, int nInitSize = 0 ) : m_pMemory( NULL )
+ {
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ m_nCurAllocSize = 0;
+#endif
+
+ }
+ CUtlMemoryConservative( T* pMemory, int numElements ) { Assert( 0 ); }
+ ~CUtlMemoryConservative() { if ( m_pMemory ) free( m_pMemory ); }
+
+ // Can we use this index?
+ bool IsIdxValid( int i ) const { return ( IsDebug() ) ? ( i >= 0 && i < NumAllocated() ) : ( i >= 0 ); }
+ static int InvalidIndex() { return -1; }
+
+ // Gets the base address
+ T* Base() { return m_pMemory; }
+ const T* Base() const { return m_pMemory; }
+
+ // element access
+ T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+ T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
+ const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
+
+ // Size
+ FORCEINLINE void RememberAllocSize( size_t sz )
+ {
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ m_nCurAllocSize = sz;
+#endif
+ }
+
+ size_t AllocSize( void ) const
+ {
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ return m_nCurAllocSize;
+#else
+ return ( m_pMemory ) ? g_pMemAlloc->GetSize( m_pMemory ) : 0;
+#endif
+ }
+
+ int NumAllocated() const
+ {
+ return AllocSize() / sizeof( T );
+ }
+ int Count() const
+ {
+ return NumAllocated();
+ }
+
+ FORCEINLINE void ReAlloc( size_t sz )
+ {
+ m_pMemory = (T*)realloc( m_pMemory, sz );
+ RememberAllocSize( sz );
+ }
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 )
+ {
+ int nCurN = NumAllocated();
+ ReAlloc( ( nCurN + num ) * sizeof( T ) );
+ }
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num )
+ {
+ size_t nSize = sizeof( T ) * MAX( num, Count() );
+ ReAlloc( nSize );
+ }
+
+ // Memory deallocation
+ void Purge()
+ {
+ free( m_pMemory );
+ RememberAllocSize( 0 );
+ m_pMemory = NULL;
+ }
+
+ // Purge all but the given number of elements
+ void Purge( int numElements ) { ReAlloc( numElements * sizeof(T) ); }
+
+ // is the memory externally allocated?
+ bool IsExternallyAllocated() const { return false; }
+
+ // Set the size by which the memory grows
+ void SetGrowSize( int size ) {}
+
+ class Iterator_t
+ {
+ public:
+ Iterator_t( int i, int _limit ) : index( i ), limit( _limit ) {}
+ int index;
+ int limit;
+ bool operator==( const Iterator_t it ) const { return index == it.index; }
+ bool operator!=( const Iterator_t it ) const { return index != it.index; }
+ };
+ Iterator_t First() const { int limit = NumAllocated(); return Iterator_t( limit ? 0 : InvalidIndex(), limit ); }
+ Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( ( it.index + 1 < it.limit ) ? it.index + 1 : InvalidIndex(), it.limit ); }
+ int GetIndex( const Iterator_t &it ) const { return it.index; }
+ bool IsIdxAfter( int i, const Iterator_t &it ) const { return i > it.index; }
+ bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ) && ( it.index < it.limit ); }
+ Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex(), 0 ); }
+
+private:
+ T *m_pMemory;
+#ifdef REMEMBER_ALLOC_SIZE_FOR_VALGRIND
+ size_t m_nCurAllocSize;
+#endif
+
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template< class T, class I >
+CUtlMemory<T,I>::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0),
+ m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize )
+{
+ ValidateGrowSize();
+ Assert( nGrowSize >= 0 );
+ if (m_nAllocationCount)
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ }
+}
+
+template< class T, class I >
+CUtlMemory<T,I>::CUtlMemory( T* pMemory, int numElements ) : m_pMemory(pMemory),
+ m_nAllocationCount( numElements )
+{
+ // Special marker indicating externally supplied modifyable memory
+ m_nGrowSize = EXTERNAL_BUFFER_MARKER;
+}
+
+template< class T, class I >
+CUtlMemory<T,I>::CUtlMemory( const T* pMemory, int numElements ) : m_pMemory( (T*)pMemory ),
+ m_nAllocationCount( numElements )
+{
+ // Special marker indicating externally supplied modifyable memory
+ m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
+}
+
+template< class T, class I >
+CUtlMemory<T,I>::~CUtlMemory()
+{
+ Purge();
+
+#ifdef _DEBUG
+ m_pMemory = reinterpret_cast< T* >( 0xFEFEBAAD );
+ m_nAllocationCount = 0x7BADF00D;
+#endif
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::Init( int nGrowSize /*= 0*/, int nInitSize /*= 0*/ )
+{
+ Purge();
+
+ m_nGrowSize = nGrowSize;
+ m_nAllocationCount = nInitSize;
+ ValidateGrowSize();
+ Assert( nGrowSize >= 0 );
+ if (m_nAllocationCount)
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Fast swap
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::Swap( CUtlMemory<T,I> &mem )
+{
+ V_swap( m_nGrowSize, mem.m_nGrowSize );
+ V_swap( m_pMemory, mem.m_pMemory );
+ V_swap( m_nAllocationCount, mem.m_nAllocationCount );
+}
+
+
+//-----------------------------------------------------------------------------
+// Switches the buffer from an external memory buffer to a reallocatable buffer
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::ConvertToGrowableMemory( int nGrowSize )
+{
+ if ( !IsExternallyAllocated() )
+ return;
+
+ m_nGrowSize = nGrowSize;
+ if (m_nAllocationCount)
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+
+ int nNumBytes = m_nAllocationCount * sizeof(T);
+ T *pMemory = (T*)malloc( nNumBytes );
+ memcpy( pMemory, m_pMemory, nNumBytes );
+ m_pMemory = pMemory;
+ }
+ else
+ {
+ m_pMemory = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Attaches the buffer to external memory....
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::SetExternalBuffer( T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ m_pMemory = pMemory;
+ m_nAllocationCount = numElements;
+
+ // Indicate that we don't own the memory
+ m_nGrowSize = EXTERNAL_BUFFER_MARKER;
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::SetExternalBuffer( const T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ m_pMemory = const_cast<T*>( pMemory );
+ m_nAllocationCount = numElements;
+
+ // Indicate that we don't own the memory
+ m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER;
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::AssumeMemory( T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ // Simply take the pointer but don't mark us as external
+ m_pMemory = pMemory;
+ m_nAllocationCount = numElements;
+}
+
+template< class T, class I >
+void *CUtlMemory<T,I>::DetachMemory()
+{
+ if ( IsExternallyAllocated() )
+ return NULL;
+
+ void *pMemory = m_pMemory;
+ m_pMemory = 0;
+ m_nAllocationCount = 0;
+ return pMemory;
+}
+
+template< class T, class I >
+inline T* CUtlMemory<T,I>::Detach()
+{
+ return (T*)DetachMemory();
+}
+
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline T& CUtlMemory<T,I>::operator[]( I i )
+{
+ Assert( !IsReadOnly() );
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline const T& CUtlMemory<T,I>::operator[]( I i ) const
+{
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline T& CUtlMemory<T,I>::Element( I i )
+{
+ Assert( !IsReadOnly() );
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+template< class T, class I >
+inline const T& CUtlMemory<T,I>::Element( I i ) const
+{
+ Assert( IsIdxValid(i) );
+ return m_pMemory[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// is the memory externally allocated?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+bool CUtlMemory<T,I>::IsExternallyAllocated() const
+{
+ return (m_nGrowSize < 0);
+}
+
+
+//-----------------------------------------------------------------------------
+// is the memory read only?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+bool CUtlMemory<T,I>::IsReadOnly() const
+{
+ return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER);
+}
+
+
+template< class T, class I >
+void CUtlMemory<T,I>::SetGrowSize( int nSize )
+{
+ Assert( !IsExternallyAllocated() );
+ Assert( nSize >= 0 );
+ m_nGrowSize = nSize;
+ ValidateGrowSize();
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the base address (can change when adding elements!)
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline T* CUtlMemory<T,I>::Base()
+{
+ Assert( !IsReadOnly() );
+ return m_pMemory;
+}
+
+template< class T, class I >
+inline const T *CUtlMemory<T,I>::Base() const
+{
+ return m_pMemory;
+}
+
+
+//-----------------------------------------------------------------------------
+// Size
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline int CUtlMemory<T,I>::NumAllocated() const
+{
+ return m_nAllocationCount;
+}
+
+template< class T, class I >
+inline int CUtlMemory<T,I>::Count() const
+{
+ return m_nAllocationCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline bool CUtlMemory<T,I>::IsIdxValid( I i ) const
+{
+ // GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
+ // We get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
+ long x = i;
+ return ( x >= 0 ) && ( x < m_nAllocationCount );
+}
+
+//-----------------------------------------------------------------------------
+// Grows the memory
+//-----------------------------------------------------------------------------
+inline int UtlMemory_CalcNewAllocationCount( int nAllocationCount, int nGrowSize, int nNewSize, int nBytesItem )
+{
+ if ( nGrowSize )
+ {
+ nAllocationCount = ((1 + ((nNewSize - 1) / nGrowSize)) * nGrowSize);
+ }
+ else
+ {
+ if ( !nAllocationCount )
+ {
+ // Compute an allocation which is at least as big as a cache line...
+ nAllocationCount = (31 + nBytesItem) / nBytesItem;
+ }
+
+ while (nAllocationCount < nNewSize)
+ {
+#ifndef _X360
+ nAllocationCount *= 2;
+#else
+ int nNewAllocationCount = ( nAllocationCount * 9) / 8; // 12.5 %
+ if ( nNewAllocationCount > nAllocationCount )
+ nAllocationCount = nNewAllocationCount;
+ else
+ nAllocationCount *= 2;
+#endif
+ }
+ }
+
+ return nAllocationCount;
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::Grow( int num )
+{
+ Assert( num > 0 );
+
+ if ( IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ // Make sure we have at least numallocated + num allocations.
+ // Use the grow rules specified for this memory (in m_nGrowSize)
+ int nAllocationRequested = m_nAllocationCount + num;
+
+ UTLMEMORY_TRACK_FREE();
+
+ int nNewAllocationCount = UtlMemory_CalcNewAllocationCount( m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T) );
+
+ // if m_nAllocationRequested wraps index type I, recalculate
+ if ( ( int )( I )nNewAllocationCount < nAllocationRequested )
+ {
+ if ( ( int )( I )nNewAllocationCount == 0 && ( int )( I )( nNewAllocationCount - 1 ) >= nAllocationRequested )
+ {
+ --nNewAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1
+ }
+ else
+ {
+ if ( ( int )( I )nAllocationRequested != nAllocationRequested )
+ {
+ // we've been asked to grow memory to a size s.t. the index type can't address the requested amount of memory
+ Assert( 0 );
+ return;
+ }
+ while ( ( int )( I )nNewAllocationCount < nAllocationRequested )
+ {
+ nNewAllocationCount = ( nNewAllocationCount + nAllocationRequested ) / 2;
+ }
+ }
+ }
+
+ m_nAllocationCount = nNewAllocationCount;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if (m_pMemory)
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) );
+ Assert( m_pMemory );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ Assert( m_pMemory );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we've got at least this much memory
+//-----------------------------------------------------------------------------
+template< class T, class I >
+inline void CUtlMemory<T,I>::EnsureCapacity( int num )
+{
+ if (m_nAllocationCount >= num)
+ return;
+
+ if ( IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ m_nAllocationCount = num;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if (m_pMemory)
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMemory<T,I>::Purge()
+{
+ if ( !IsExternallyAllocated() )
+ {
+ if (m_pMemory)
+ {
+ UTLMEMORY_TRACK_FREE();
+ free( (void*)m_pMemory );
+ m_pMemory = 0;
+ }
+ m_nAllocationCount = 0;
+ }
+}
+
+template< class T, class I >
+void CUtlMemory<T,I>::Purge( int numElements )
+{
+ Assert( numElements >= 0 );
+
+ if( numElements > m_nAllocationCount )
+ {
+ // Ensure this isn't a grow request in disguise.
+ Assert( numElements <= m_nAllocationCount );
+ return;
+ }
+
+ // If we have zero elements, simply do a purge:
+ if( numElements == 0 )
+ {
+ Purge();
+ return;
+ }
+
+ if ( IsExternallyAllocated() )
+ {
+ // Can't shrink a buffer whose memory was externally allocated, fail silently like purge
+ return;
+ }
+
+ // If the number of elements is the same as the allocation count, we are done.
+ if( numElements == m_nAllocationCount )
+ {
+ return;
+ }
+
+
+ if( !m_pMemory )
+ {
+ // Allocation count is non zero, but memory is null.
+ Assert( m_pMemory );
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ m_nAllocationCount = numElements;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ // Allocation count > 0, shrink it down.
+ MEM_ALLOC_CREDIT_CLASS();
+ m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) );
+}
+
+//-----------------------------------------------------------------------------
+// The CUtlMemory class:
+// A growable memory class which doubles in size by default.
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+class CUtlMemoryAligned : public CUtlMemory<T>
+{
+public:
+ // constructor, destructor
+ CUtlMemoryAligned( int nGrowSize = 0, int nInitSize = 0 );
+ CUtlMemoryAligned( T* pMemory, int numElements );
+ CUtlMemoryAligned( const T* pMemory, int numElements );
+ ~CUtlMemoryAligned();
+
+ // Attaches the buffer to external memory....
+ void SetExternalBuffer( T* pMemory, int numElements );
+ void SetExternalBuffer( const T* pMemory, int numElements );
+
+ // Grows the memory, so that at least allocated + num elements are allocated
+ void Grow( int num = 1 );
+
+ // Makes sure we've got at least this much memory
+ void EnsureCapacity( int num );
+
+ // Memory deallocation
+ void Purge();
+
+ // Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryAligned)
+ void Purge( int numElements ) { Assert( 0 ); }
+
+private:
+ void *Align( const void *pAddr );
+};
+
+
+//-----------------------------------------------------------------------------
+// Aligns a pointer
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void *CUtlMemoryAligned<T, nAlignment>::Align( const void *pAddr )
+{
+ size_t nAlignmentMask = nAlignment - 1;
+ return (void*)( ((size_t)pAddr + nAlignmentMask) & (~nAlignmentMask) );
+}
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned( int nGrowSize, int nInitAllocationCount )
+{
+ CUtlMemory<T>::m_pMemory = 0;
+ CUtlMemory<T>::m_nAllocationCount = nInitAllocationCount;
+ CUtlMemory<T>::m_nGrowSize = nGrowSize;
+ this->ValidateGrowSize();
+
+ // Alignment must be a power of two
+ COMPILE_TIME_ASSERT( (nAlignment & (nAlignment-1)) == 0 );
+ Assert( (nGrowSize >= 0) && (nGrowSize != CUtlMemory<T>::EXTERNAL_BUFFER_MARKER) );
+ if ( CUtlMemory<T>::m_nAllocationCount )
+ {
+ UTLMEMORY_TRACK_ALLOC();
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)_aligned_malloc( nInitAllocationCount * sizeof(T), nAlignment );
+ }
+}
+
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned( T* pMemory, int numElements )
+{
+ // Special marker indicating externally supplied memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_BUFFER_MARKER;
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+}
+
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::CUtlMemoryAligned( const T* pMemory, int numElements )
+{
+ // Special marker indicating externally supplied memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_CONST_BUFFER_MARKER;
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+}
+
+template< class T, int nAlignment >
+CUtlMemoryAligned<T, nAlignment>::~CUtlMemoryAligned()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Attaches the buffer to external memory....
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::SetExternalBuffer( T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+
+ // Indicate that we don't own the memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_BUFFER_MARKER;
+}
+
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::SetExternalBuffer( const T* pMemory, int numElements )
+{
+ // Blow away any existing allocated memory
+ Purge();
+
+ CUtlMemory<T>::m_pMemory = (T*)Align( pMemory );
+ CUtlMemory<T>::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory<T>::m_pMemory ) / sizeof(T);
+
+ // Indicate that we don't own the memory
+ CUtlMemory<T>::m_nGrowSize = CUtlMemory<T>::EXTERNAL_CONST_BUFFER_MARKER;
+}
+
+
+//-----------------------------------------------------------------------------
+// Grows the memory
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::Grow( int num )
+{
+ Assert( num > 0 );
+
+ if ( this->IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ // Make sure we have at least numallocated + num allocations.
+ // Use the grow rules specified for this memory (in m_nGrowSize)
+ int nAllocationRequested = CUtlMemory<T>::m_nAllocationCount + num;
+
+ CUtlMemory<T>::m_nAllocationCount = UtlMemory_CalcNewAllocationCount( CUtlMemory<T>::m_nAllocationCount, CUtlMemory<T>::m_nGrowSize, nAllocationRequested, sizeof(T) );
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if ( CUtlMemory<T>::m_pMemory )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_ReallocAligned( CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ Assert( CUtlMemory<T>::m_pMemory );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_AllocAligned( CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ Assert( CUtlMemory<T>::m_pMemory );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we've got at least this much memory
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+inline void CUtlMemoryAligned<T, nAlignment>::EnsureCapacity( int num )
+{
+ if ( CUtlMemory<T>::m_nAllocationCount >= num )
+ return;
+
+ if ( this->IsExternallyAllocated() )
+ {
+ // Can't grow a buffer whose memory was externally allocated
+ Assert(0);
+ return;
+ }
+
+ UTLMEMORY_TRACK_FREE();
+
+ CUtlMemory<T>::m_nAllocationCount = num;
+
+ UTLMEMORY_TRACK_ALLOC();
+
+ if ( CUtlMemory<T>::m_pMemory )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_ReallocAligned( CUtlMemory<T>::m_pMemory, CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ }
+ else
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ CUtlMemory<T>::m_pMemory = (T*)MemAlloc_AllocAligned( CUtlMemory<T>::m_nAllocationCount * sizeof(T), nAlignment );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+template< class T, int nAlignment >
+void CUtlMemoryAligned<T, nAlignment>::Purge()
+{
+ if ( !this->IsExternallyAllocated() )
+ {
+ if ( CUtlMemory<T>::m_pMemory )
+ {
+ UTLMEMORY_TRACK_FREE();
+ MemAlloc_FreeAligned( CUtlMemory<T>::m_pMemory );
+ CUtlMemory<T>::m_pMemory = 0;
+ }
+ CUtlMemory<T>::m_nAllocationCount = 0;
+ }
+}
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLMEMORY_H
diff --git a/external/vpc/public/tier1/utlmultilist.h b/external/vpc/public/tier1/utlmultilist.h
new file mode 100644
index 0000000..68e2a98
--- /dev/null
+++ b/external/vpc/public/tier1/utlmultilist.h
@@ -0,0 +1,769 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Multiple linked list container class
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLMULTILIST_H
+#define UTLMULTILIST_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "utllinkedlist.h"
+
+// memdbgon must be the last include file in a .h file!!!
+#include "tier0/memdbgon.h"
+
+
+//-----------------------------------------------------------------------------
+// class CUtlMultiList:
+// description:
+// A lovely index-based linked list! T is the class type, I is the index
+// type, which usually should be an unsigned short or smaller.
+// This list can contain multiple lists
+//-----------------------------------------------------------------------------
+template <class T, class I>
+class CUtlMultiList
+{
+protected:
+ // What the linked list element looks like
+ struct ListElem_t
+ {
+ T m_Element;
+ I m_Previous;
+ I m_Next;
+ };
+
+ struct List_t
+ {
+ I m_Head;
+ I m_Tail;
+ I m_Count;
+ };
+
+ typedef CUtlMemory<ListElem_t> M; // Keep naming similar to CUtlLinkedList
+public:
+ typedef I ListHandle_t;
+
+ // constructor, destructor
+ CUtlMultiList( int growSize = 0, int initSize = 0 );
+ CUtlMultiList( void *pMemory, int memsize );
+ ~CUtlMultiList( );
+
+ // gets particular elements
+ T& Element( I i );
+ T const& Element( I i ) const;
+ T& operator[]( I i );
+ T const& operator[]( I i ) const;
+
+ // Make sure we have a particular amount of memory
+ void EnsureCapacity( int num );
+
+ // Memory deallocation
+ void Purge();
+
+ // List Creation/deletion
+ ListHandle_t CreateList();
+ void DestroyList( ListHandle_t list );
+ bool IsValidList( ListHandle_t list ) const;
+
+ // Insertion methods (call default constructor)....
+ I InsertBefore( ListHandle_t list, I before );
+ I InsertAfter( ListHandle_t list, I after );
+ I AddToHead( ListHandle_t list );
+ I AddToTail( ListHandle_t list );
+
+ // Insertion methods (call copy constructor)....
+ I InsertBefore( ListHandle_t list, I before, T const& src );
+ I InsertAfter( ListHandle_t list, I after, T const& src );
+ I AddToHead( ListHandle_t list, T const& src );
+ I AddToTail( ListHandle_t list, T const& src );
+
+ // Removal methods
+ void Remove( ListHandle_t list, I elem );
+
+ // Removes all items in a single list
+ void RemoveAll( ListHandle_t list );
+
+ // Removes all items in all lists
+ void RemoveAll();
+
+ // Allocation/deallocation methods
+ // NOTE: To free, it must *not* be in a list!
+ I Alloc( );
+ void Free( I elem );
+
+ // list modification
+ void LinkBefore( ListHandle_t list, I before, I elem );
+ void LinkAfter( ListHandle_t list, I after, I elem );
+ void Unlink( ListHandle_t list, I elem );
+ void LinkToHead( ListHandle_t list, I elem );
+ void LinkToTail( ListHandle_t list, I elem );
+
+ // invalid index
+ static I InvalidIndex() { return (I)~0; }
+ static bool IndexInRange( int index );
+ static size_t ElementSize() { return sizeof(ListElem_t); }
+
+ // list statistics
+ int Count( ListHandle_t list ) const;
+ int TotalCount( ) const;
+ I MaxElementIndex() const;
+
+ // Traversing the list
+ I Head( ListHandle_t list ) const;
+ I Tail( ListHandle_t list ) const;
+ I Previous( I element ) const;
+ I Next( I element ) const;
+
+ // Are nodes in a list or valid?
+ bool IsValidIndex( I i ) const;
+ bool IsInList( I i ) const;
+
+protected:
+ // constructs the class
+ void ConstructList( );
+
+ // Gets at the list element....
+ ListElem_t& InternalElement( I i ) { return m_Memory[i]; }
+ ListElem_t const& InternalElement( I i ) const { return m_Memory[i]; }
+
+ // A test for debug mode only...
+ bool IsElementInList( ListHandle_t list, I elem ) const;
+
+ // copy constructors not allowed
+ CUtlMultiList( CUtlMultiList<T, I> const& list ) { Assert(0); }
+
+ M m_Memory;
+ CUtlLinkedList<List_t, I> m_List;
+ I* m_pElementList;
+
+ I m_FirstFree;
+ I m_TotalElements;
+ int m_MaxElementIndex; // The number allocated (use int so we can catch overflow)
+
+ void ResetDbgInfo()
+ {
+ m_pElements = m_Memory.Base();
+
+#ifdef _DEBUG
+ // Allocate space for the element list (which list is each element in)
+ if (m_Memory.NumAllocated() > 0)
+ {
+ if (!m_pElementList)
+ {
+ m_pElementList = (I*)malloc( m_Memory.NumAllocated() * sizeof(I) );
+ }
+ else
+ {
+ m_pElementList = (I*)realloc( m_pElementList, m_Memory.NumAllocated() * sizeof(I) );
+ }
+ }
+#endif
+ }
+
+ // For debugging purposes;
+ // it's in release builds so this can be used in libraries correctly
+ ListElem_t *m_pElements;
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template <class T, class I>
+CUtlMultiList<T,I>::CUtlMultiList( int growSize, int initSize ) :
+ m_Memory(growSize, initSize), m_pElementList(0)
+{
+ ConstructList();
+}
+
+template <class T, class I>
+CUtlMultiList<T,I>::CUtlMultiList( void* pMemory, int memsize ) :
+ m_Memory((ListElem_t *)pMemory, memsize/sizeof(ListElem_t)), m_pElementList(0)
+{
+ ConstructList();
+}
+
+template <class T, class I>
+CUtlMultiList<T,I>::~CUtlMultiList( )
+{
+ RemoveAll();
+ if (m_pElementList)
+ free(m_pElementList);
+}
+
+template <class T, class I>
+void CUtlMultiList<T,I>::ConstructList( )
+{
+ m_FirstFree = InvalidIndex();
+ m_TotalElements = 0;
+ m_MaxElementIndex = 0;
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline T& CUtlMultiList<T,I>::Element( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class I>
+inline T const& CUtlMultiList<T,I>::Element( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class I>
+inline T& CUtlMultiList<T,I>::operator[]( I i )
+{
+ return m_Memory[i].m_Element;
+}
+
+template <class T, class I>
+inline T const& CUtlMultiList<T,I>::operator[]( I i ) const
+{
+ return m_Memory[i].m_Element;
+}
+
+
+//-----------------------------------------------------------------------------
+// list creation/destruction
+//-----------------------------------------------------------------------------
+template <class T, class I>
+typename CUtlMultiList<T,I>::ListHandle_t CUtlMultiList<T,I>::CreateList()
+{
+ ListHandle_t l = m_List.AddToTail();
+ m_List[l].m_Head = m_List[l].m_Tail = InvalidIndex();
+ m_List[l].m_Count = 0;
+ return l;
+}
+
+template <class T, class I>
+void CUtlMultiList<T,I>::DestroyList( ListHandle_t list )
+{
+ Assert( IsValidList(list) );
+ RemoveAll( list );
+ m_List.Remove(list);
+}
+
+template <class T, class I>
+bool CUtlMultiList<T,I>::IsValidList( ListHandle_t list ) const
+{
+ return m_List.IsValidIndex(list);
+}
+
+
+//-----------------------------------------------------------------------------
+// list statistics
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline int CUtlMultiList<T,I>::TotalCount() const
+{
+ return m_TotalElements;
+}
+
+template <class T, class I>
+inline int CUtlMultiList<T,I>::Count( ListHandle_t list ) const
+{
+ Assert( IsValidList(list) );
+ return m_List[list].m_Count;
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::MaxElementIndex() const
+{
+ return m_MaxElementIndex;
+}
+
+
+//-----------------------------------------------------------------------------
+// Traversing the list
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline I CUtlMultiList<T,I>::Head(ListHandle_t list) const
+{
+ Assert( IsValidList(list) );
+ return m_List[list].m_Head;
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::Tail(ListHandle_t list) const
+{
+ Assert( IsValidList(list) );
+ return m_List[list].m_Tail;
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::Previous( I i ) const
+{
+ Assert( IsValidIndex(i) );
+ return InternalElement(i).m_Previous;
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::Next( I i ) const
+{
+ Assert( IsValidIndex(i) );
+ return InternalElement(i).m_Next;
+}
+
+
+//-----------------------------------------------------------------------------
+// Are nodes in the list or valid?
+//-----------------------------------------------------------------------------
+
+template <class T, class I>
+inline bool CUtlMultiList<T,I>::IndexInRange( int index ) // Static method
+{
+ // Since I is not necessarily the type returned by M (int), we need to check that M returns
+ // indices which are representable by I. A common case is 'I === unsigned short', in which case
+ // case CUtlMemory will have 'InvalidIndex == (int)-1' (which casts to 65535 in I), and will
+ // happily return elements at index 65535 and above.
+
+ // Do a couple of static checks here: the invalid index should be (I)~0 given how we use m_MaxElementIndex,
+ // and 'I' should be unsigned (to avoid signed arithmetic errors for plausibly exhaustible ranges).
+ COMPILE_TIME_ASSERT( (I)M::INVALID_INDEX == (I)~0 );
+ COMPILE_TIME_ASSERT( ( sizeof(I) > 2 ) || ( ( (I)-1 ) > 0 ) );
+
+ return ( ( (I)index == index ) && ( (I)index != InvalidIndex() ) );
+}
+
+template <class T, class I>
+inline bool CUtlMultiList<T,I>::IsValidIndex( I i ) const
+{
+ // GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
+ // We get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
+ long x = i;
+
+ return (i < m_MaxElementIndex) && (x >= 0) &&
+ ((m_Memory[i].m_Previous != i) || (m_Memory[i].m_Next == i));
+}
+
+template <class T, class I>
+inline bool CUtlMultiList<T,I>::IsInList( I i ) const
+{
+ // GCC warns if I is an unsigned type and we do a ">= 0" against it (since the comparison is always 0).
+ // We get the warning even if we cast inside the expression. It only goes away if we assign to another variable.
+ long x = i;
+ return (i < m_MaxElementIndex) && (x >= 0) && (Previous(i) != i);
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+template< class T, class I >
+void CUtlMultiList<T, I>::EnsureCapacity( int num )
+{
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Deallocate memory
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlMultiList<T,I>::Purge()
+{
+ RemoveAll();
+ m_List.Purge();
+ m_Memory.Purge( );
+ m_List.Purge();
+ m_FirstFree = InvalidIndex();
+ m_TotalElements = 0;
+ m_MaxElementIndex = 0;
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Node allocation/deallocation
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlMultiList<T,I>::Alloc( )
+{
+ I elem;
+ if (m_FirstFree == InvalidIndex())
+ {
+ // We can overflow before the utlmemory overflows, since we have have I != int
+ if ( !IndexInRange( m_MaxElementIndex ) )
+ {
+ ExecuteNTimes( 10, Warning( "CUtlMultiList overflow! (exhausted index range)\n" ) );
+ return InvalidIndex();
+ }
+
+ // Nothing in the free list; add.
+ // Since nothing is in the free list, m_TotalElements == total # of elements
+ // the list knows about.
+ if (m_MaxElementIndex == m_Memory.NumAllocated())
+ {
+ m_Memory.Grow();
+ ResetDbgInfo();
+
+ if ( m_MaxElementIndex >= m_Memory.NumAllocated() )
+ {
+ ExecuteNTimes( 10, Warning( "CUtlMultiList overflow! (exhausted memory allocator)\n" ) );
+ return InvalidIndex();
+ }
+ }
+
+ elem = (I)m_MaxElementIndex;
+ ++m_MaxElementIndex;
+ }
+ else
+ {
+ elem = m_FirstFree;
+ m_FirstFree = InternalElement(m_FirstFree).m_Next;
+ }
+
+ // Mark the element as not being in a list
+ InternalElement(elem).m_Next = InternalElement(elem).m_Previous = elem;
+
+ ++m_TotalElements;
+
+ Construct( &Element(elem) );
+
+ return elem;
+}
+
+template <class T, class I>
+void CUtlMultiList<T,I>::Free( I elem )
+{
+ Assert( IsValidIndex(elem) && !IsInList(elem) );
+ Destruct( &Element(elem) );
+ InternalElement(elem).m_Next = m_FirstFree;
+ m_FirstFree = elem;
+ --m_TotalElements;
+}
+
+
+//-----------------------------------------------------------------------------
+// A test for debug mode only...
+//-----------------------------------------------------------------------------
+template <class T, class I>
+inline bool CUtlMultiList<T,I>::IsElementInList( ListHandle_t list, I elem ) const
+{
+ if (!m_pElementList)
+ return true;
+
+ return m_pElementList[elem] == list;
+}
+
+
+//-----------------------------------------------------------------------------
+// list modification
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlMultiList<T,I>::LinkBefore( ListHandle_t list, I before, I elem )
+{
+ Assert( IsValidIndex(elem) && IsValidList(list) );
+
+ // Unlink it if it's in the list at the moment
+ Unlink(list, elem);
+
+ ListElem_t& newElem = InternalElement(elem);
+
+ // The element *after* our newly linked one is the one we linked before.
+ newElem.m_Next = before;
+
+ if (before == InvalidIndex())
+ {
+ // In this case, we're linking to the end of the list, so reset the tail
+ newElem.m_Previous = m_List[list].m_Tail;
+ m_List[list].m_Tail = elem;
+ }
+ else
+ {
+ // Here, we're not linking to the end. Set the prev pointer to point to
+ // the element we're linking.
+ Assert( IsInList(before) );
+ ListElem_t& beforeElem = InternalElement(before);
+ newElem.m_Previous = beforeElem.m_Previous;
+ beforeElem.m_Previous = elem;
+ }
+
+ // Reset the head if we linked to the head of the list
+ if (newElem.m_Previous == InvalidIndex())
+ m_List[list].m_Head = elem;
+ else
+ InternalElement(newElem.m_Previous).m_Next = elem;
+
+ // one more element baby
+ ++m_List[list].m_Count;
+
+ // Store the element into the list
+ if (m_pElementList)
+ m_pElementList[elem] = list;
+}
+
+template <class T, class I>
+void CUtlMultiList<T,I>::LinkAfter( ListHandle_t list, I after, I elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ // Unlink it if it's in the list at the moment
+ Unlink(list, elem);
+
+ ListElem_t& newElem = InternalElement(elem);
+
+ // The element *before* our newly linked one is the one we linked after
+ newElem.m_Previous = after;
+ if (after == InvalidIndex())
+ {
+ // In this case, we're linking to the head of the list, reset the head
+ newElem.m_Next = m_List[list].m_Head;
+ m_List[list].m_Head = elem;
+ }
+ else
+ {
+ // Here, we're not linking to the end. Set the next pointer to point to
+ // the element we're linking.
+ Assert( IsInList(after) );
+ ListElem_t& afterElem = InternalElement(after);
+ newElem.m_Next = afterElem.m_Next;
+ afterElem.m_Next = elem;
+ }
+
+ // Reset the tail if we linked to the tail of the list
+ if (newElem.m_Next == InvalidIndex())
+ m_List[list].m_Tail = elem;
+ else
+ InternalElement(newElem.m_Next).m_Previous = elem;
+
+ // one more element baby
+ ++m_List[list].m_Count;
+
+ // Store the element into the list
+ if (m_pElementList)
+ m_pElementList[elem] = list;
+}
+
+template <class T, class I>
+void CUtlMultiList<T,I>::Unlink( ListHandle_t list, I elem )
+{
+ Assert( IsValidIndex(elem) && IsValidList(list) );
+
+ if (IsInList(elem))
+ {
+ // Make sure the element is in the right list
+ Assert( IsElementInList( list, elem ) );
+ ListElem_t& oldElem = InternalElement(elem);
+
+ // If we're the first guy, reset the head
+ // otherwise, make our previous node's next pointer = our next
+ if (oldElem.m_Previous != InvalidIndex())
+ InternalElement(oldElem.m_Previous).m_Next = oldElem.m_Next;
+ else
+ m_List[list].m_Head = oldElem.m_Next;
+
+ // If we're the last guy, reset the tail
+ // otherwise, make our next node's prev pointer = our prev
+ if (oldElem.m_Next != InvalidIndex())
+ InternalElement(oldElem.m_Next).m_Previous = oldElem.m_Previous;
+ else
+ m_List[list].m_Tail = oldElem.m_Previous;
+
+ // This marks this node as not in the list,
+ // but not in the free list either
+ oldElem.m_Previous = oldElem.m_Next = elem;
+
+ // One less puppy
+ --m_List[list].m_Count;
+
+ // Store the element into the list
+ if (m_pElementList)
+ m_pElementList[elem] = m_List.InvalidIndex();
+ }
+}
+
+template <class T, class I>
+inline void CUtlMultiList<T,I>::LinkToHead( ListHandle_t list, I elem )
+{
+ LinkAfter( list, InvalidIndex(), elem );
+}
+
+template <class T, class I>
+inline void CUtlMultiList<T,I>::LinkToTail( ListHandle_t list, I elem )
+{
+ LinkBefore( list, InvalidIndex(), elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// Insertion methods; allocates and links (uses default constructor)
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlMultiList<T,I>::InsertBefore( ListHandle_t list, I before )
+{
+ // Make a new node
+ I newNode = Alloc();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkBefore( list, before, newNode );
+
+ // Construct the data
+ Construct( &Element(newNode) );
+
+ return newNode;
+}
+
+template <class T, class I>
+I CUtlMultiList<T,I>::InsertAfter( ListHandle_t list, I after )
+{
+ // Make a new node
+ I newNode = Alloc();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkAfter( list, after, newNode );
+
+ // Construct the data
+ Construct( &Element(newNode) );
+
+ return newNode;
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::AddToHead( ListHandle_t list )
+{
+ return InsertAfter( list, InvalidIndex() );
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::AddToTail( ListHandle_t list )
+{
+ return InsertBefore( list, InvalidIndex() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Insertion methods; allocates and links (uses copy constructor)
+//-----------------------------------------------------------------------------
+template <class T, class I>
+I CUtlMultiList<T,I>::InsertBefore( ListHandle_t list, I before, T const& src )
+{
+ // Make a new node
+ I newNode = Alloc();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkBefore( list, before, newNode );
+
+ // Construct the data
+ CopyConstruct( &Element(newNode), src );
+
+ return newNode;
+}
+
+template <class T, class I>
+I CUtlMultiList<T,I>::InsertAfter( ListHandle_t list, I after, T const& src )
+{
+ // Make a new node
+ I newNode = Alloc();
+ if ( newNode == InvalidIndex() )
+ return newNode;
+
+ // Link it in
+ LinkAfter( list, after, newNode );
+
+ // Construct the data
+ CopyConstruct( &Element(newNode), src );
+
+ return newNode;
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::AddToHead( ListHandle_t list, T const& src )
+{
+ return InsertAfter( list, InvalidIndex(), src );
+}
+
+template <class T, class I>
+inline I CUtlMultiList<T,I>::AddToTail( ListHandle_t list, T const& src )
+{
+ return InsertBefore( list, InvalidIndex(), src );
+}
+
+
+//-----------------------------------------------------------------------------
+// Removal methods
+//-----------------------------------------------------------------------------
+template <class T, class I>
+void CUtlMultiList<T,I>::Remove( ListHandle_t list, I elem )
+{
+ if (IsInList(elem))
+ Unlink(list, elem);
+ Free( elem );
+}
+
+// Removes all items in a single list
+template <class T, class I>
+void CUtlMultiList<T,I>::RemoveAll( ListHandle_t list )
+{
+ Assert( IsValidList(list) );
+ I i = Head(list);
+ I next;
+ while( i != InvalidIndex() )
+ {
+ next = Next(i);
+ Remove(list, i);
+ i = next;
+ }
+}
+
+
+template <class T, class I>
+void CUtlMultiList<T,I>::RemoveAll()
+{
+ if (m_MaxElementIndex == 0)
+ return;
+
+ // Put everything into the free list
+ I prev = InvalidIndex();
+ for (int i = (int)m_MaxElementIndex; --i >= 0; )
+ {
+ // Invoke the destructor
+ if (IsValidIndex((I)i))
+ Destruct( &Element((I)i) );
+
+ // next points to the next free list item
+ InternalElement((I)i).m_Next = prev;
+
+ // Indicates it's in the free list
+ InternalElement((I)i).m_Previous = (I)i;
+ prev = (I)i;
+ }
+
+ // First free points to the first element
+ m_FirstFree = 0;
+
+ // Clear everything else out
+ for (I list = m_List.Head(); list != m_List.InvalidIndex(); list = m_List.Next(list) )
+ {
+ m_List[list].m_Head = InvalidIndex();
+ m_List[list].m_Tail = InvalidIndex();
+ m_List[list].m_Count = 0;
+ }
+
+ m_TotalElements = 0;
+}
+
+
+#include "tier0/memdbgoff.h"
+
+#endif // UTLMULTILIST_H
diff --git a/external/vpc/public/tier1/utlqueue.h b/external/vpc/public/tier1/utlqueue.h
new file mode 100644
index 0000000..d816407
--- /dev/null
+++ b/external/vpc/public/tier1/utlqueue.h
@@ -0,0 +1,176 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLQUEUE_H
+#define UTLQUEUE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "utlvector.h"
+
+// T is the type stored in the queue
+template< class T, class M = CUtlMemory< T > >
+class CUtlQueue
+{
+public:
+
+ // constructor: lessfunc is required, but may be set after the constructor with
+ // SetLessFunc
+ CUtlQueue( int growSize = 0, int initSize = 0 );
+ CUtlQueue( T *pMemory, int numElements );
+
+ // element access
+ T& operator[]( int i );
+ T const& operator[]( int i ) const;
+ T& Element( int i );
+ T const& Element( int i ) const;
+
+ // return the item from the front of the queue and delete it
+ T const& RemoveAtHead();
+ // return the item from the end of the queue and delete it
+ T const& RemoveAtTail();
+
+ // return item at the front of the queue
+ T const& Head();
+ // return item at the end of the queue
+ T const& Tail();
+
+ // put a new item on the queue to the tail.
+ void Insert( T const &element );
+
+ // checks if an element of this value already exists on the queue, returns true if it does
+ bool Check( T const element );
+
+ // Returns the count of elements in the queue
+ int Count() const { return m_heap.Count(); }
+
+ // Is element index valid?
+ bool IsIdxValid( int i ) const;
+
+ // doesn't deallocate memory
+ void RemoveAll() { m_heap.RemoveAll(); }
+
+ // Memory deallocation
+ void Purge() { m_heap.Purge(); }
+
+protected:
+ CUtlVector<T, M> m_heap;
+ T m_current;
+};
+
+//-----------------------------------------------------------------------------
+// The CUtlQueueFixed class:
+// A queue class with a fixed allocation scheme
+//-----------------------------------------------------------------------------
+template< class T, size_t MAX_SIZE >
+class CUtlQueueFixed : public CUtlQueue< T, CUtlMemoryFixed<T, MAX_SIZE > >
+{
+ typedef CUtlQueue< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
+public:
+
+ // constructor, destructor
+ CUtlQueueFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlQueueFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+template< class T, class M >
+inline CUtlQueue<T, M>::CUtlQueue( int growSize, int initSize ) :
+ m_heap(growSize, initSize)
+{
+}
+
+template< class T, class M >
+inline CUtlQueue<T, M>::CUtlQueue( T *pMemory, int numElements ) :
+ m_heap(pMemory, numElements)
+{
+}
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T& CUtlQueue<T,M>::operator[]( int i )
+{
+ return m_heap[i];
+}
+
+template< class T, class M >
+inline T const& CUtlQueue<T,M>::operator[]( int i ) const
+{
+ return m_heap[i];
+}
+
+template< class T, class M >
+inline T& CUtlQueue<T,M>::Element( int i )
+{
+ return m_heap[i];
+}
+
+template< class T, class M >
+inline T const& CUtlQueue<T,M>::Element( int i ) const
+{
+ return m_heap[i];
+}
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline bool CUtlQueue<T,M>::IsIdxValid( int i ) const
+{
+ return (i >= 0) && (i < m_heap.Count());
+}
+
+template <class T, class M>
+inline T const& CUtlQueue<T, M>::RemoveAtHead()
+{
+ m_current = m_heap[0];
+ m_heap.Remove((int)0);
+ return m_current;
+}
+
+template <class T, class M>
+inline T const& CUtlQueue<T, M>::RemoveAtTail()
+{
+ m_current = m_heap[ m_heap.Count() - 1 ];
+ m_heap.Remove((int)(m_heap.Count() - 1));
+ return m_current;
+}
+
+template <class T, class M>
+inline T const& CUtlQueue<T, M>::Head()
+{
+ m_current = m_heap[0];
+ return m_current;
+}
+
+template <class T, class M>
+inline T const& CUtlQueue<T, M>::Tail()
+{
+ m_current = m_heap[ m_heap.Count() - 1 ];
+ return m_current;
+}
+
+template <class T, class M>
+void CUtlQueue<T, M>::Insert( T const &element )
+{
+ int index = m_heap.AddToTail();
+ m_heap[index] = element;
+}
+
+template <class T, class M>
+bool CUtlQueue<T, M>::Check( T const element )
+{
+ int index = m_heap.Find(element);
+ return ( index != -1 );
+}
+
+
+#endif // UTLQUEUE_H
diff --git a/external/vpc/public/tier1/utlrbtree.h b/external/vpc/public/tier1/utlrbtree.h
new file mode 100644
index 0000000..5031cca
--- /dev/null
+++ b/external/vpc/public/tier1/utlrbtree.h
@@ -0,0 +1,1581 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Header: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef UTLRBTREE_H
+#define UTLRBTREE_H
+
+#include "tier1/utlmemory.h"
+#include "tier1/utlfixedmemory.h"
+#include "tier1/utlblockmemory.h"
+
+
+// This is a useful macro to iterate from start to end in order in a map
+#define FOR_EACH_UTLRBTREE( treeName, iteratorName ) \
+ for ( int iteratorName = treeName.FirstInorder(); iteratorName != treeName.InvalidIndex(); iteratorName = treeName.NextInorder( iteratorName ) )
+
+
+//-----------------------------------------------------------------------------
+// Tool to generate a default compare function for any type that implements
+// operator<, including all simple types
+//-----------------------------------------------------------------------------
+
+template <typename T >
+class CDefOps
+{
+public:
+ static bool LessFunc( const T &lhs, const T &rhs ) { return ( lhs < rhs ); }
+};
+
+#define DefLessFunc( type ) CDefOps< type >::LessFunc
+
+//-------------------------------------
+
+inline bool StringLessThan( const char * const &lhs, const char * const &rhs) {
+ if ( !lhs ) return false;
+ if ( !rhs ) return true;
+ return ( strcmp( lhs, rhs) < 0 );
+}
+
+inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) {
+ if ( !lhs ) return false;
+ if ( !rhs ) return true;
+ return ( stricmp( lhs, rhs) < 0 );
+}
+
+
+// Same as CaselessStringLessThan, but it ignores differences in / and \.
+inline bool CaselessStringLessThanIgnoreSlashes( const char * const &lhs, const char * const &rhs )
+{
+ const char *pa = lhs;
+ const char *pb = rhs;
+ while ( *pa && *pb )
+ {
+ char a = *pa;
+ char b = *pb;
+
+ // Check for dir slashes.
+ if ( a == '/' || a == '\\' )
+ {
+ if ( b != '/' && b != '\\' )
+ return ('/' < b);
+ }
+ else
+ {
+ if ( a >= 'a' && a <= 'z' )
+ a = 'A' + (a - 'a');
+
+ if ( b >= 'a' && b <= 'z' )
+ b = 'A' + (b - 'a');
+
+ if ( a > b )
+ return false;
+ else if ( a < b )
+ return true;
+ }
+ ++pa;
+ ++pb;
+ }
+
+ // Filenames also must be the same length.
+ if ( *pa != *pb )
+ {
+ // If pa shorter than pb then it's "less"
+ return ( !*pa );
+ }
+
+ return false;
+}
+
+//-------------------------------------
+// inline these two templates to stop multiple definitions of the same code
+template <> inline bool CDefOps<const char *>::LessFunc( const char * const &lhs, const char * const &rhs ) { return StringLessThan( lhs, rhs ); }
+template <> inline bool CDefOps<char *>::LessFunc( char * const &lhs, char * const &rhs ) { return StringLessThan( lhs, rhs ); }
+
+//-------------------------------------
+
+template <typename RBTREE_T>
+void SetDefLessFunc( RBTREE_T &RBTree )
+{
+ RBTree.SetLessFunc( DefLessFunc( typename RBTREE_T::KeyType_t ) );
+}
+
+//-----------------------------------------------------------------------------
+// A red-black binary search tree
+//-----------------------------------------------------------------------------
+
+template < class I >
+struct UtlRBTreeLinks_t
+{
+ I m_Left;
+ I m_Right;
+ I m_Parent;
+ I m_Tag;
+};
+
+template < class T, class I >
+struct UtlRBTreeNode_t : public UtlRBTreeLinks_t< I >
+{
+ T m_Data;
+};
+
+template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ), class M = CUtlMemory< UtlRBTreeNode_t< T, I >, I > >
+class CUtlRBTree
+{
+public:
+
+ typedef T KeyType_t;
+ typedef T ElemType_t;
+ typedef I IndexType_t;
+
+ // Less func typedef
+ // Returns true if the first parameter is "less" than the second
+ typedef L LessFunc_t;
+
+ // constructor, destructor
+ // Left at growSize = 0, the memory will first allocate 1 element and double in size
+ // at each increment.
+ // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below
+ CUtlRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 );
+ CUtlRBTree( const LessFunc_t &lessfunc );
+ ~CUtlRBTree( );
+
+ void EnsureCapacity( int num );
+
+ // NOTE: CopyFrom is fast but dangerous! It just memcpy's all nodes - it does NOT run copy constructors, so
+ // it is not a true deep copy (i.e 'T' must be POD for this to work - e.g CUtlString will not work).
+ void CopyFrom( const CUtlRBTree<T, I, L, M> &other );
+
+ // gets particular elements
+ T& Element( I i );
+ T const &Element( I i ) const;
+ T& operator[]( I i );
+ T const &operator[]( I i ) const;
+
+ // Gets the root
+ I Root() const;
+
+ // Num elements
+ unsigned int Count() const;
+
+ // Max "size" of the vector
+ // it's not generally safe to iterate from index 0 to MaxElement()-1 (you could do this as a potential
+ // iteration optimization, IF CUtlMemory is the allocator, and IF IsValidIndex() is tested for each element...
+ // but this should be implemented inside the CUtlRBTree iteration API, if anywhere)
+ I MaxElement() const;
+
+ // Gets the children
+ I Parent( I i ) const;
+ I LeftChild( I i ) const;
+ I RightChild( I i ) const;
+
+ // Tests if a node is a left or right child
+ bool IsLeftChild( I i ) const;
+ bool IsRightChild( I i ) const;
+
+ // Tests if root or leaf
+ bool IsRoot( I i ) const;
+ bool IsLeaf( I i ) const;
+
+ // Checks if a node is valid and in the tree
+ bool IsValidIndex( I i ) const;
+
+ // Checks if the tree as a whole is valid
+ bool IsValid() const;
+
+ // Invalid index
+ static I InvalidIndex();
+
+ // returns the tree depth (not a very fast operation)
+ int Depth( I node ) const;
+ int Depth() const;
+
+ // Sets the less func
+ void SetLessFunc( const LessFunc_t &func );
+
+ // Allocation method
+ I NewNode();
+
+ // Insert method (inserts in order)
+ // NOTE: the returned 'index' will be valid as long as the element remains in the tree
+ // (other elements being added/removed will not affect it)
+ I Insert( T const &insert );
+ void Insert( const T *pArray, int nItems );
+ I InsertIfNotFound( T const &insert );
+
+ // Find method
+ I Find( T const &search ) const;
+
+ // Remove methods
+ void RemoveAt( I i );
+ bool Remove( T const &remove );
+ void RemoveAll( );
+ void Purge();
+
+ // Allocation, deletion
+ void FreeNode( I i );
+
+ // Iteration
+ I FirstInorder() const;
+ I NextInorder( I i ) const;
+ I PrevInorder( I i ) const;
+ I LastInorder() const;
+
+ I FirstPreorder() const;
+ I NextPreorder( I i ) const;
+ I PrevPreorder( I i ) const;
+ I LastPreorder( ) const;
+
+ I FirstPostorder() const;
+ I NextPostorder( I i ) const;
+
+ // If you change the search key, this can be used to reinsert the
+ // element into the tree.
+ void Reinsert( I elem );
+
+ // swap in place
+ void Swap( CUtlRBTree< T, I, L > &that );
+
+private:
+ // Can't copy the tree this way!
+ CUtlRBTree<T, I, L, M>& operator=( const CUtlRBTree<T, I, L, M> &other );
+
+protected:
+ enum NodeColor_t
+ {
+ RED = 0,
+ BLACK
+ };
+
+ typedef UtlRBTreeNode_t< T, I > Node_t;
+ typedef UtlRBTreeLinks_t< I > Links_t;
+
+ // Sets the children
+ void SetParent( I i, I parent );
+ void SetLeftChild( I i, I child );
+ void SetRightChild( I i, I child );
+ void LinkToParent( I i, I parent, bool isLeft );
+
+ // Gets at the links
+ Links_t const &Links( I i ) const;
+ Links_t &Links( I i );
+
+ // Checks if a link is red or black
+ bool IsRed( I i ) const;
+ bool IsBlack( I i ) const;
+
+ // Sets/gets node color
+ NodeColor_t Color( I i ) const;
+ void SetColor( I i, NodeColor_t c );
+
+ // operations required to preserve tree balance
+ void RotateLeft(I i);
+ void RotateRight(I i);
+ void InsertRebalance(I i);
+ void RemoveRebalance(I i);
+
+ // Insertion, removal
+ I InsertAt( I parent, bool leftchild );
+
+ // copy constructors not allowed
+ CUtlRBTree( CUtlRBTree<T, I, L, M> const &tree );
+
+ // Inserts a node into the tree, doesn't copy the data in.
+ void FindInsertionPosition( T const &insert, I &parent, bool &leftchild );
+
+ // Remove and add back an element in the tree.
+ void Unlink( I elem );
+ void Link( I elem );
+
+ // Used for sorting.
+ LessFunc_t m_LessFunc;
+
+ M m_Elements;
+ I m_Root;
+ I m_NumElements;
+ I m_FirstFree;
+ typename M::Iterator_t m_LastAlloc; // the last index allocated
+
+ Node_t* m_pElements;
+
+ FORCEINLINE M const &Elements( void ) const
+ {
+ return m_Elements;
+ }
+
+
+ void ResetDbgInfo()
+ {
+ m_pElements = (Node_t*)m_Elements.Base();
+ }
+};
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T, class I = int, typename L = bool (*)( const T &, const T & ) >
+class CUtlFixedRBTree : public CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >
+{
+public:
+
+ typedef L LessFunc_t;
+
+ CUtlFixedRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 )
+ : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( growSize, initSize, lessfunc ) {}
+ CUtlFixedRBTree( const LessFunc_t &lessfunc )
+ : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( lessfunc ) {}
+
+ typedef CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > > BaseClass;
+ bool IsValidIndex( I i ) const
+ {
+ if ( !BaseClass::Elements().IsIdxValid( i ) )
+ return false;
+
+#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElement()
+ if ( BaseClass::Elements().IsIdxAfter( i, this->m_LastAlloc ) )
+ {
+ Assert( 0 );
+ return false; // don't read values that have been allocated, but not constructed
+ }
+#endif
+
+ return LeftChild(i) != i;
+ }
+
+protected:
+ void ResetDbgInfo() {}
+
+private:
+ // this doesn't make sense for fixed rbtrees, since there's no useful max pointer, and the index space isn't contiguous anyways
+ I MaxElement() const;
+};
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ) >
+class CUtlBlockRBTree : public CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >
+{
+public:
+ typedef L LessFunc_t;
+ CUtlBlockRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 )
+ : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( growSize, initSize, lessfunc ) {}
+ CUtlBlockRBTree( const LessFunc_t &lessfunc )
+ : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( lessfunc ) {}
+protected:
+ void ResetDbgInfo() {}
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline CUtlRBTree<T, I, L, M>::CUtlRBTree( int growSize, int initSize, const LessFunc_t &lessfunc ) :
+m_LessFunc( lessfunc ),
+m_Elements( growSize, initSize ),
+m_Root( InvalidIndex() ),
+m_NumElements( 0 ),
+m_FirstFree( InvalidIndex() ),
+m_LastAlloc( m_Elements.InvalidIterator() )
+{
+ ResetDbgInfo();
+}
+
+template < class T, class I, typename L, class M >
+inline CUtlRBTree<T, I, L, M>::CUtlRBTree( const LessFunc_t &lessfunc ) :
+m_Elements( 0, 0 ),
+m_LessFunc( lessfunc ),
+m_Root( InvalidIndex() ),
+m_NumElements( 0 ),
+m_FirstFree( InvalidIndex() ),
+m_LastAlloc( m_Elements.InvalidIterator() )
+{
+ ResetDbgInfo();
+}
+
+template < class T, class I, typename L, class M >
+inline CUtlRBTree<T, I, L, M>::~CUtlRBTree()
+{
+ Purge();
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::EnsureCapacity( int num )
+{
+ m_Elements.EnsureCapacity( num );
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::CopyFrom( const CUtlRBTree<T, I, L, M> &other )
+{
+ Purge();
+ m_Elements.EnsureCapacity( other.m_Elements.Count() );
+ memcpy( m_Elements.Base(), other.m_Elements.Base(), other.m_Elements.Count() * sizeof( UtlRBTreeNode_t< T, I > ) );
+ m_LessFunc = other.m_LessFunc;
+ m_Root = other.m_Root;
+ m_NumElements = other.m_NumElements;
+ m_FirstFree = other.m_FirstFree;
+ m_LastAlloc = other.m_LastAlloc;
+ ResetDbgInfo();
+}
+
+//-----------------------------------------------------------------------------
+// gets particular elements
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline T &CUtlRBTree<T, I, L, M>::Element( I i )
+{
+ return m_Elements[i].m_Data;
+}
+
+template < class T, class I, typename L, class M >
+inline T const &CUtlRBTree<T, I, L, M>::Element( I i ) const
+{
+ return m_Elements[i].m_Data;
+}
+
+template < class T, class I, typename L, class M >
+inline T &CUtlRBTree<T, I, L, M>::operator[]( I i )
+{
+ return Element(i);
+}
+
+template < class T, class I, typename L, class M >
+inline T const &CUtlRBTree<T, I, L, M>::operator[]( I i ) const
+{
+ return Element(i);
+}
+
+//-----------------------------------------------------------------------------
+//
+// various accessors
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Gets the root
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::Root() const
+{
+ return m_Root;
+}
+
+//-----------------------------------------------------------------------------
+// Num elements
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline unsigned int CUtlRBTree<T, I, L, M>::Count() const
+{
+ return (unsigned int)m_NumElements;
+}
+
+//-----------------------------------------------------------------------------
+// Max "size" of the vector
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::MaxElement() const
+{
+ return ( I )m_Elements.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the children
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::Parent( I i ) const
+{
+ return Links(i).m_Parent;
+}
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::LeftChild( I i ) const
+{
+ return Links(i).m_Left;
+}
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::RightChild( I i ) const
+{
+ return Links(i).m_Right;
+}
+
+//-----------------------------------------------------------------------------
+// Tests if a node is a left or right child
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsLeftChild( I i ) const
+{
+ return LeftChild(Parent(i)) == i;
+}
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsRightChild( I i ) const
+{
+ return RightChild(Parent(i)) == i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Tests if root or leaf
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsRoot( I i ) const
+{
+ return i == m_Root;
+}
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsLeaf( I i ) const
+{
+ return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex());
+}
+
+
+//-----------------------------------------------------------------------------
+// Checks if a node is valid and in the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsValidIndex( I i ) const
+{
+ if ( !m_Elements.IsIdxValid( i ) )
+ return false;
+
+ if ( m_Elements.IsIdxAfter( i, m_LastAlloc ) )
+ return false; // don't read values that have been allocated, but not constructed
+
+ return LeftChild(i) != i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Invalid index
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline I CUtlRBTree<T, I, L, M>::InvalidIndex()
+{
+ return ( I )M::InvalidIndex();
+}
+
+
+//-----------------------------------------------------------------------------
+// returns the tree depth (not a very fast operation)
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline int CUtlRBTree<T, I, L, M>::Depth() const
+{
+ return Depth(Root());
+}
+
+//-----------------------------------------------------------------------------
+// Sets the children
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetParent( I i, I parent )
+{
+ Links(i).m_Parent = parent;
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetLeftChild( I i, I child )
+{
+ Links(i).m_Left = child;
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetRightChild( I i, I child )
+{
+ Links(i).m_Right = child;
+}
+
+//-----------------------------------------------------------------------------
+// Gets at the links
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline typename CUtlRBTree<T, I, L, M>::Links_t const &CUtlRBTree<T, I, L, M>::Links( I i ) const
+{
+ // Sentinel node, makes life easier
+ static Links_t s_Sentinel =
+ {
+ InvalidIndex(), InvalidIndex(), InvalidIndex(), CUtlRBTree<T, I, L, M>::BLACK
+ };
+
+ return (i != InvalidIndex()) ? *(Links_t*)&m_Elements[i] : *(Links_t*)&s_Sentinel;
+}
+
+template < class T, class I, typename L, class M >
+inline typename CUtlRBTree<T, I, L, M>::Links_t &CUtlRBTree<T, I, L, M>::Links( I i )
+{
+ Assert(i != InvalidIndex());
+ return *(Links_t *)&m_Elements[i];
+}
+
+//-----------------------------------------------------------------------------
+// Checks if a link is red or black
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsRed( I i ) const
+{
+ return (Links(i).m_Tag == RED);
+}
+
+template < class T, class I, typename L, class M >
+inline bool CUtlRBTree<T, I, L, M>::IsBlack( I i ) const
+{
+ return (Links(i).m_Tag == BLACK);
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets/gets node color
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+inline typename CUtlRBTree<T, I, L, M>::NodeColor_t CUtlRBTree<T, I, L, M>::Color( I i ) const
+{
+ return (NodeColor_t)Links(i).m_Tag;
+}
+
+template < class T, class I, typename L, class M >
+inline void CUtlRBTree<T, I, L, M>::SetColor( I i, typename CUtlRBTree<T, I, L, M>::NodeColor_t c )
+{
+ Links(i).m_Tag = (I)c;
+}
+
+//-----------------------------------------------------------------------------
+// Allocates/ deallocates nodes
+//-----------------------------------------------------------------------------
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NewNode()
+{
+ I elem;
+
+ // Nothing in the free list; add.
+ if ( m_FirstFree == InvalidIndex() )
+ {
+ Assert( m_Elements.IsValidIterator( m_LastAlloc ) || m_NumElements == 0 );
+ typename M::Iterator_t it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First();
+ if ( !m_Elements.IsValidIterator( it ) )
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Elements.Grow();
+
+ it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First();
+
+ Assert( m_Elements.IsValidIterator( it ) );
+ if ( !m_Elements.IsValidIterator( it ) )
+ {
+ Error( "CUtlRBTree overflow!\n" );
+ }
+ }
+ m_LastAlloc = it;
+ elem = m_Elements.GetIndex( m_LastAlloc );
+ Assert( m_Elements.IsValidIterator( m_LastAlloc ) );
+ }
+ else
+ {
+ elem = m_FirstFree;
+ m_FirstFree = Links( m_FirstFree ).m_Right;
+ }
+
+#ifdef _DEBUG
+ // reset links to invalid....
+ Links_t &node = Links( elem );
+ node.m_Left = node.m_Right = node.m_Parent = InvalidIndex();
+#endif
+
+ Construct( &Element( elem ) );
+ ResetDbgInfo();
+
+ return elem;
+}
+#pragma warning(pop)
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::FreeNode( I i )
+{
+ Assert( IsValidIndex(i) && (i != InvalidIndex()) );
+ Destruct( &Element(i) );
+ SetLeftChild( i, i ); // indicates it's in not in the tree
+ SetRightChild( i, m_FirstFree );
+ m_FirstFree = i;
+}
+
+
+//-----------------------------------------------------------------------------
+// Rotates node i to the left
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RotateLeft(I elem)
+{
+ I rightchild = RightChild(elem);
+ SetRightChild( elem, LeftChild(rightchild) );
+ if (LeftChild(rightchild) != InvalidIndex())
+ SetParent( LeftChild(rightchild), elem );
+
+ if (rightchild != InvalidIndex())
+ SetParent( rightchild, Parent(elem) );
+ if (!IsRoot(elem))
+ {
+ if (IsLeftChild(elem))
+ SetLeftChild( Parent(elem), rightchild );
+ else
+ SetRightChild( Parent(elem), rightchild );
+ }
+ else
+ m_Root = rightchild;
+
+ SetLeftChild( rightchild, elem );
+ if (elem != InvalidIndex())
+ SetParent( elem, rightchild );
+}
+
+
+//-----------------------------------------------------------------------------
+// Rotates node i to the right
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RotateRight(I elem)
+{
+ I leftchild = LeftChild(elem);
+ SetLeftChild( elem, RightChild(leftchild) );
+ if (RightChild(leftchild) != InvalidIndex())
+ SetParent( RightChild(leftchild), elem );
+
+ if (leftchild != InvalidIndex())
+ SetParent( leftchild, Parent(elem) );
+ if (!IsRoot(elem))
+ {
+ if (IsRightChild(elem))
+ SetRightChild( Parent(elem), leftchild );
+ else
+ SetLeftChild( Parent(elem), leftchild );
+ }
+ else
+ m_Root = leftchild;
+
+ SetRightChild( leftchild, elem );
+ if (elem != InvalidIndex())
+ SetParent( elem, leftchild );
+}
+
+
+//-----------------------------------------------------------------------------
+// Rebalances the tree after an insertion
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::InsertRebalance(I elem)
+{
+ while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) )
+ {
+ I parent = Parent(elem);
+ I grandparent = Parent(parent);
+
+ /* we have a violation */
+ if (IsLeftChild(parent))
+ {
+ I uncle = RightChild(grandparent);
+ if (IsRed(uncle))
+ {
+ /* uncle is RED */
+ SetColor(parent, BLACK);
+ SetColor(uncle, BLACK);
+ SetColor(grandparent, RED);
+ elem = grandparent;
+ }
+ else
+ {
+ /* uncle is BLACK */
+ if (IsRightChild(elem))
+ {
+ /* make x a left child, will change parent and grandparent */
+ elem = parent;
+ RotateLeft(elem);
+ parent = Parent(elem);
+ grandparent = Parent(parent);
+ }
+ /* recolor and rotate */
+ SetColor(parent, BLACK);
+ SetColor(grandparent, RED);
+ RotateRight(grandparent);
+ }
+ }
+ else
+ {
+ /* mirror image of above code */
+ I uncle = LeftChild(grandparent);
+ if (IsRed(uncle))
+ {
+ /* uncle is RED */
+ SetColor(parent, BLACK);
+ SetColor(uncle, BLACK);
+ SetColor(grandparent, RED);
+ elem = grandparent;
+ }
+ else
+ {
+ /* uncle is BLACK */
+ if (IsLeftChild(elem))
+ {
+ /* make x a right child, will change parent and grandparent */
+ elem = parent;
+ RotateRight(parent);
+ parent = Parent(elem);
+ grandparent = Parent(parent);
+ }
+ /* recolor and rotate */
+ SetColor(parent, BLACK);
+ SetColor(grandparent, RED);
+ RotateLeft(grandparent);
+ }
+ }
+ }
+ SetColor( m_Root, BLACK );
+}
+
+
+//-----------------------------------------------------------------------------
+// Insert a node into the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::InsertAt( I parent, bool leftchild )
+{
+ I i = NewNode();
+ LinkToParent( i, parent, leftchild );
+ ++m_NumElements;
+
+ Assert(IsValid());
+
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::LinkToParent( I i, I parent, bool isLeft )
+{
+ Links_t &elem = Links(i);
+ elem.m_Parent = parent;
+ elem.m_Left = elem.m_Right = InvalidIndex();
+ elem.m_Tag = RED;
+
+ /* insert node in tree */
+ if (parent != InvalidIndex())
+ {
+ if (isLeft)
+ Links(parent).m_Left = i;
+ else
+ Links(parent).m_Right = i;
+ }
+ else
+ {
+ m_Root = i;
+ }
+
+ InsertRebalance(i);
+}
+
+//-----------------------------------------------------------------------------
+// Rebalance the tree after a deletion
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RemoveRebalance(I elem)
+{
+ while (elem != m_Root && IsBlack(elem))
+ {
+ I parent = Parent(elem);
+
+ // If elem is the left child of the parent
+ if (elem == LeftChild(parent))
+ {
+ // Get our sibling
+ I sibling = RightChild(parent);
+ if (IsRed(sibling))
+ {
+ SetColor(sibling, BLACK);
+ SetColor(parent, RED);
+ RotateLeft(parent);
+
+ // We may have a new parent now
+ parent = Parent(elem);
+ sibling = RightChild(parent);
+ }
+ if ( (IsBlack(LeftChild(sibling))) && (IsBlack(RightChild(sibling))) )
+ {
+ if (sibling != InvalidIndex())
+ SetColor(sibling, RED);
+ elem = parent;
+ }
+ else
+ {
+ if (IsBlack(RightChild(sibling)))
+ {
+ SetColor(LeftChild(sibling), BLACK);
+ SetColor(sibling, RED);
+ RotateRight(sibling);
+
+ // rotation may have changed this
+ parent = Parent(elem);
+ sibling = RightChild(parent);
+ }
+ SetColor( sibling, Color(parent) );
+ SetColor( parent, BLACK );
+ SetColor( RightChild(sibling), BLACK );
+ RotateLeft( parent );
+ elem = m_Root;
+ }
+ }
+ else
+ {
+ // Elem is the right child of the parent
+ I sibling = LeftChild(parent);
+ if (IsRed(sibling))
+ {
+ SetColor(sibling, BLACK);
+ SetColor(parent, RED);
+ RotateRight(parent);
+
+ // We may have a new parent now
+ parent = Parent(elem);
+ sibling = LeftChild(parent);
+ }
+ if ( (IsBlack(RightChild(sibling))) && (IsBlack(LeftChild(sibling))) )
+ {
+ if (sibling != InvalidIndex())
+ SetColor( sibling, RED );
+ elem = parent;
+ }
+ else
+ {
+ if (IsBlack(LeftChild(sibling)))
+ {
+ SetColor( RightChild(sibling), BLACK );
+ SetColor( sibling, RED );
+ RotateLeft( sibling );
+
+ // rotation may have changed this
+ parent = Parent(elem);
+ sibling = LeftChild(parent);
+ }
+ SetColor( sibling, Color(parent) );
+ SetColor( parent, BLACK );
+ SetColor( LeftChild(sibling), BLACK );
+ RotateRight( parent );
+ elem = m_Root;
+ }
+ }
+ }
+ SetColor( elem, BLACK );
+}
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Unlink( I elem )
+{
+ if ( elem != InvalidIndex() )
+ {
+ I x, y;
+
+ if ((LeftChild(elem) == InvalidIndex()) ||
+ (RightChild(elem) == InvalidIndex()))
+ {
+ /* y has a NIL node as a child */
+ y = elem;
+ }
+ else
+ {
+ /* find tree successor with a NIL node as a child */
+ y = RightChild(elem);
+ while (LeftChild(y) != InvalidIndex())
+ y = LeftChild(y);
+ }
+
+ /* x is y's only child */
+ if (LeftChild(y) != InvalidIndex())
+ x = LeftChild(y);
+ else
+ x = RightChild(y);
+
+ /* remove y from the parent chain */
+ if (x != InvalidIndex())
+ SetParent( x, Parent(y) );
+ if (!IsRoot(y))
+ {
+ if (IsLeftChild(y))
+ SetLeftChild( Parent(y), x );
+ else
+ SetRightChild( Parent(y), x );
+ }
+ else
+ m_Root = x;
+
+ // need to store this off now, we'll be resetting y's color
+ NodeColor_t ycolor = Color(y);
+ if (y != elem)
+ {
+ // Standard implementations copy the data around, we cannot here.
+ // Hook in y to link to the same stuff elem used to.
+ SetParent( y, Parent(elem) );
+ SetRightChild( y, RightChild(elem) );
+ SetLeftChild( y, LeftChild(elem) );
+
+ if (!IsRoot(elem))
+ if (IsLeftChild(elem))
+ SetLeftChild( Parent(elem), y );
+ else
+ SetRightChild( Parent(elem), y );
+ else
+ m_Root = y;
+
+ if (LeftChild(y) != InvalidIndex())
+ SetParent( LeftChild(y), y );
+ if (RightChild(y) != InvalidIndex())
+ SetParent( RightChild(y), y );
+
+ SetColor( y, Color(elem) );
+ }
+
+ if ((x != InvalidIndex()) && (ycolor == BLACK))
+ RemoveRebalance(x);
+ }
+}
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Link( I elem )
+{
+ if ( elem != InvalidIndex() )
+ {
+ I parent = InvalidIndex();
+ bool leftchild = false;
+
+ FindInsertionPosition( Element( elem ), parent, leftchild );
+
+ LinkToParent( elem, parent, leftchild );
+
+ Assert(IsValid());
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Delete a node from the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RemoveAt(I elem)
+{
+ if ( elem != InvalidIndex() )
+ {
+ Unlink( elem );
+
+ FreeNode(elem);
+ --m_NumElements;
+
+ Assert(IsValid());
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// remove a node in the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M > bool CUtlRBTree<T, I, L, M>::Remove( T const &search )
+{
+ I node = Find( search );
+ if (node != InvalidIndex())
+ {
+ RemoveAt(node);
+ return true;
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::RemoveAll()
+{
+ // Have to do some convoluted stuff to invoke the destructor on all
+ // valid elements for the multilist case (since we don't have all elements
+ // connected to each other in a list).
+
+ if ( m_LastAlloc == m_Elements.InvalidIterator() )
+ {
+ Assert( m_Root == InvalidIndex() );
+ Assert( m_FirstFree == InvalidIndex() );
+ Assert( m_NumElements == 0 );
+ return;
+ }
+
+ for ( typename M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) )
+ {
+ I i = m_Elements.GetIndex( it );
+ if ( IsValidIndex( i ) ) // skip elements in the free list
+ {
+ Destruct( &Element( i ) );
+ SetRightChild( i, m_FirstFree );
+ SetLeftChild( i, i );
+ m_FirstFree = i;
+ }
+
+ if ( it == m_LastAlloc )
+ break; // don't destruct elements that haven't ever been constucted
+ }
+
+ // Clear everything else out
+ m_Root = InvalidIndex();
+ m_NumElements = 0;
+
+ Assert( IsValid() );
+}
+
+//-----------------------------------------------------------------------------
+// Removes all nodes from the tree and purges memory
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Purge()
+{
+ RemoveAll();
+ m_FirstFree = InvalidIndex();
+ m_Elements.Purge();
+ m_LastAlloc = m_Elements.InvalidIterator();
+}
+
+
+//-----------------------------------------------------------------------------
+// iteration
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::FirstInorder() const
+{
+ I i = m_Root;
+ while (LeftChild(i) != InvalidIndex())
+ i = LeftChild(i);
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NextInorder( I i ) const
+{
+ Assert(IsValidIndex(i));
+
+ if (RightChild(i) != InvalidIndex())
+ {
+ i = RightChild(i);
+ while (LeftChild(i) != InvalidIndex())
+ i = LeftChild(i);
+ return i;
+ }
+
+ I parent = Parent(i);
+ while (IsRightChild(i))
+ {
+ i = parent;
+ if (i == InvalidIndex()) break;
+ parent = Parent(i);
+ }
+ return parent;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::PrevInorder( I i ) const
+{
+ Assert(IsValidIndex(i));
+
+ if (LeftChild(i) != InvalidIndex())
+ {
+ i = LeftChild(i);
+ while (RightChild(i) != InvalidIndex())
+ i = RightChild(i);
+ return i;
+ }
+
+ I parent = Parent(i);
+ while (IsLeftChild(i))
+ {
+ i = parent;
+ if (i == InvalidIndex()) break;
+ parent = Parent(i);
+ }
+ return parent;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::LastInorder() const
+{
+ I i = m_Root;
+ while (RightChild(i) != InvalidIndex())
+ i = RightChild(i);
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::FirstPreorder() const
+{
+ return m_Root;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NextPreorder( I i ) const
+{
+ if (LeftChild(i) != InvalidIndex())
+ return LeftChild(i);
+
+ if (RightChild(i) != InvalidIndex())
+ return RightChild(i);
+
+ I parent = Parent(i);
+ while( parent != InvalidIndex())
+ {
+ if (IsLeftChild(i) && (RightChild(parent) != InvalidIndex()))
+ return RightChild(parent);
+ i = parent;
+ parent = Parent(parent);
+ }
+ return InvalidIndex();
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::PrevPreorder( I i ) const
+{
+ Assert(0); // not implemented yet
+ return InvalidIndex();
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::LastPreorder() const
+{
+ I i = m_Root;
+ while (1)
+ {
+ while (RightChild(i) != InvalidIndex())
+ i = RightChild(i);
+
+ if (LeftChild(i) != InvalidIndex())
+ i = LeftChild(i);
+ else
+ break;
+ }
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::FirstPostorder() const
+{
+ I i = m_Root;
+ while (!IsLeaf(i))
+ {
+ if (LeftChild(i))
+ i = LeftChild(i);
+ else
+ i = RightChild(i);
+ }
+ return i;
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::NextPostorder( I i ) const
+{
+ I parent = Parent(i);
+ if (parent == InvalidIndex())
+ return InvalidIndex();
+
+ if (IsRightChild(i))
+ return parent;
+
+ if (RightChild(parent) == InvalidIndex())
+ return parent;
+
+ i = RightChild(parent);
+ while (!IsLeaf(i))
+ {
+ if (LeftChild(i))
+ i = LeftChild(i);
+ else
+ i = RightChild(i);
+ }
+ return i;
+}
+
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Reinsert( I elem )
+{
+ Unlink( elem );
+ Link( elem );
+}
+
+
+//-----------------------------------------------------------------------------
+// returns the tree depth (not a very fast operation)
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+int CUtlRBTree<T, I, L, M>::Depth( I node ) const
+{
+ if (node == InvalidIndex())
+ return 0;
+
+ int depthright = Depth( RightChild(node) );
+ int depthleft = Depth( LeftChild(node) );
+ return MAX( depthright, depthleft ) + 1;
+}
+
+
+//#define UTLTREE_PARANOID
+
+//-----------------------------------------------------------------------------
+// Makes sure the tree is valid after every operation
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+bool CUtlRBTree<T, I, L, M>::IsValid() const
+{
+ if ( !Count() )
+ return true;
+
+ if ( m_LastAlloc == m_Elements.InvalidIterator() )
+ return false;
+
+ if ( !m_Elements.IsIdxValid( Root() ) )
+ return false;
+
+ if ( Parent( Root() ) != InvalidIndex() )
+ return false;
+
+#ifdef UTLTREE_PARANOID
+
+ // First check to see that mNumEntries matches reality.
+ // count items on the free list
+ int numFree = 0;
+ for ( int i = m_FirstFree; i != InvalidIndex(); i = RightChild( i ) )
+ {
+ ++numFree;
+ if ( !m_Elements.IsIdxValid( i ) )
+ return false;
+ }
+
+ // iterate over all elements, looking for validity
+ // based on the self pointers
+ int nElements = 0;
+ int numFree2 = 0;
+ for ( M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) )
+ {
+ I i = m_Elements.GetIndex( it );
+ if ( !IsValidIndex( i ) )
+ {
+ ++numFree2;
+ }
+ else
+ {
+ ++nElements;
+
+ int right = RightChild( i );
+ int left = LeftChild( i );
+ if ( ( right == left ) && ( right != InvalidIndex() ) )
+ return false;
+
+ if ( right != InvalidIndex() )
+ {
+ if ( !IsValidIndex( right ) )
+ return false;
+ if ( Parent( right ) != i )
+ return false;
+ if ( IsRed( i ) && IsRed( right ) )
+ return false;
+ }
+
+ if ( left != InvalidIndex() )
+ {
+ if ( !IsValidIndex( left ) )
+ return false;
+ if ( Parent( left ) != i )
+ return false;
+ if ( IsRed( i ) && IsRed( left ) )
+ return false;
+ }
+ }
+
+ if ( it == m_LastAlloc )
+ break;
+ }
+ if ( numFree2 != numFree )
+ return false;
+
+ if ( nElements != m_NumElements )
+ return false;
+
+#endif // UTLTREE_PARANOID
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the less func
+//-----------------------------------------------------------------------------
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::SetLessFunc( const typename CUtlRBTree<T, I, L, M>::LessFunc_t &func )
+{
+ if (!m_LessFunc)
+ {
+ m_LessFunc = func;
+ }
+ else if ( Count() > 0 )
+ {
+ // need to re-sort the tree here....
+ Assert(0);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// inserts a node into the tree
+//-----------------------------------------------------------------------------
+
+// Inserts a node into the tree, doesn't copy the data in.
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::FindInsertionPosition( T const &insert, I &parent, bool &leftchild )
+{
+ Assert( !!m_LessFunc );
+
+ /* find where node belongs */
+ I current = m_Root;
+ parent = InvalidIndex();
+ leftchild = false;
+ while (current != InvalidIndex())
+ {
+ parent = current;
+ if (m_LessFunc( insert, Element(current) ))
+ {
+ leftchild = true; current = LeftChild(current);
+ }
+ else
+ {
+ leftchild = false; current = RightChild(current);
+ }
+ }
+}
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::Insert( T const &insert )
+{
+ // use copy constructor to copy it in
+ I parent = InvalidIndex();
+ bool leftchild = false;
+ FindInsertionPosition( insert, parent, leftchild );
+ I newNode = InsertAt( parent, leftchild );
+ CopyConstruct( &Element( newNode ), insert );
+ return newNode;
+}
+
+
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Insert( const T *pArray, int nItems )
+{
+ while ( nItems-- )
+ {
+ Insert( *pArray++ );
+ }
+}
+
+
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::InsertIfNotFound( T const &insert )
+{
+ // use copy constructor to copy it in
+ I parent;
+ bool leftchild;
+
+ I current = m_Root;
+ parent = InvalidIndex();
+ leftchild = false;
+ while (current != InvalidIndex())
+ {
+ parent = current;
+ if (m_LessFunc( insert, Element(current) ))
+ {
+ leftchild = true; current = LeftChild(current);
+ }
+ else if (m_LessFunc( Element(current), insert ))
+ {
+ leftchild = false; current = RightChild(current);
+ }
+ else
+ // Match found, no insertion
+ return InvalidIndex();
+ }
+
+ I newNode = InsertAt( parent, leftchild );
+ CopyConstruct( &Element( newNode ), insert );
+ return newNode;
+}
+
+
+//-----------------------------------------------------------------------------
+// finds a node in the tree
+//-----------------------------------------------------------------------------
+template < class T, class I, typename L, class M >
+I CUtlRBTree<T, I, L, M>::Find( T const &search ) const
+{
+ Assert( !!m_LessFunc );
+
+ I current = m_Root;
+ while (current != InvalidIndex())
+ {
+ if (m_LessFunc( search, Element(current) ))
+ current = LeftChild(current);
+ else if (m_LessFunc( Element(current), search ))
+ current = RightChild(current);
+ else
+ break;
+ }
+ return current;
+}
+
+
+//-----------------------------------------------------------------------------
+// swap in place
+//-----------------------------------------------------------------------------
+template < class T, class I, typename L, class M >
+void CUtlRBTree<T, I, L, M>::Swap( CUtlRBTree< T, I, L > &that )
+{
+ m_Elements.Swap( that.m_Elements );
+ V_swap( m_LessFunc, that.m_LessFunc );
+ V_swap( m_Root, that.m_Root );
+ V_swap( m_NumElements, that.m_NumElements );
+ V_swap( m_FirstFree, that.m_FirstFree );
+ V_swap( m_pElements, that.m_pElements );
+ V_swap( m_LastAlloc, that.m_LastAlloc );
+ Assert( IsValid() );
+ Assert( m_Elements.IsValidIterator( m_LastAlloc ) || ( m_NumElements == 0 && m_FirstFree == InvalidIndex() ) );
+}
+
+
+#endif // UTLRBTREE_H
diff --git a/external/vpc/public/tier1/utlsortvector.h b/external/vpc/public/tier1/utlsortvector.h
new file mode 100644
index 0000000..c12de27
--- /dev/null
+++ b/external/vpc/public/tier1/utlsortvector.h
@@ -0,0 +1,354 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// $Header: $
+// $NoKeywords: $
+//
+// A growable array class that keeps all elements in order using binary search
+//===========================================================================//
+
+#ifndef UTLSORTVECTOR_H
+#define UTLSORTVECTOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "utlvector.h"
+
+
+//-----------------------------------------------------------------------------
+// class CUtlSortVector:
+// description:
+// This in an sorted order-preserving vector. Items may be inserted or removed
+// at any point in the vector. When an item is inserted, all elements are
+// moved down by one element using memmove. When an item is removed, all
+// elements are shifted back down. Items are searched for in the vector
+// using a binary search technique. Clients must pass in a Less() function
+// into the constructor of the vector to determine the sort order.
+//-----------------------------------------------------------------------------
+
+#ifndef _WIN32
+// gcc has no qsort_s, so i need to use a static var to hold the sort context. this makes cutlsortvector _not_ thread sfae under linux
+extern void *g_pUtlSortVectorQSortContext;
+#endif
+
+template <class T>
+class CUtlSortVectorDefaultLess
+{
+public:
+ bool Less( const T& lhs, const T& rhs, void * )
+ {
+ return lhs < rhs;
+ }
+};
+
+template <class T, class LessFunc = CUtlSortVectorDefaultLess<T>, class BaseVector = CUtlVector<T> >
+class CUtlSortVector : public BaseVector
+{
+public:
+
+ // constructor
+ CUtlSortVector( int nGrowSize = 0, int initSize = 0 );
+ CUtlSortVector( T* pMemory, int numElements );
+
+ // inserts (copy constructs) an element in sorted order into the list
+ int Insert( const T& src );
+
+ // Finds an element within the list using a binary search
+ int Find( const T& search ) const;
+ int FindLessOrEqual( const T& search ) const;
+ int FindLess( const T& search ) const;
+ template <typename K>
+ int FindAs( const K& key ) const;
+
+ // Removes a particular element
+ void Remove( const T& search );
+ void Remove( int i );
+
+ // Allows methods to set a context to be used with the less function..
+ void SetLessContext( void *pCtx );
+
+ // Note that you can only use this index until sorting is redone!!!
+ int InsertNoSort( const T& src );
+ void RedoSort( bool bForceSort = false );
+
+protected:
+ // No copy constructor
+ CUtlSortVector( const CUtlSortVector<T, LessFunc> & );
+
+ // never call these; illegal for this class
+ int AddToHead();
+ int AddToTail();
+ int InsertBefore( int elem );
+ int InsertAfter( int elem );
+ int AddToHead( const T& src );
+ int AddToTail( const T& src );
+ int InsertBefore( int elem, const T& src );
+ int InsertAfter( int elem, const T& src );
+ int AddMultipleToHead( int num );
+ int AddMultipleToTail( int num, const T *pToCopy=NULL );
+ int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL );
+ int InsertMultipleAfter( int elem, int num );
+ int AddVectorToTail( CUtlVector<T> const &src );
+
+ struct QSortContext_t
+ {
+ void *m_pLessContext;
+ LessFunc *m_pLessFunc;
+ };
+
+#ifdef _WIN32
+ static int CompareHelper( void *context, const T *lhs, const T *rhs )
+ {
+ QSortContext_t *ctx = reinterpret_cast< QSortContext_t * >( context );
+ if ( ctx->m_pLessFunc->Less( *lhs, *rhs, ctx->m_pLessContext ) )
+ return -1;
+ if ( ctx->m_pLessFunc->Less( *rhs, *lhs, ctx->m_pLessContext ) )
+ return 1;
+ return 0;
+ }
+#else
+ static int CompareHelper( const T *lhs, const T *rhs )
+ {
+ QSortContext_t *ctx = reinterpret_cast< QSortContext_t * >( g_pUtlSortVectorQSortContext );
+ if ( ctx->m_pLessFunc->Less( *lhs, *rhs, ctx->m_pLessContext ) )
+ return -1;
+ if ( ctx->m_pLessFunc->Less( *rhs, *lhs, ctx->m_pLessContext ) )
+ return 1;
+ return 0;
+ }
+#endif
+
+ void *m_pLessContext;
+ bool m_bNeedsSort;
+
+private:
+ void QuickSort( LessFunc& less, int X, int I );
+};
+
+
+//-----------------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+CUtlSortVector<T, LessFunc, BaseVector>::CUtlSortVector( int nGrowSize, int initSize ) :
+ m_pLessContext(NULL), BaseVector( nGrowSize, initSize ), m_bNeedsSort( false )
+{
+}
+
+template <class T, class LessFunc, class BaseVector>
+CUtlSortVector<T, LessFunc, BaseVector>::CUtlSortVector( T* pMemory, int numElements ) :
+ m_pLessContext(NULL), BaseVector( pMemory, numElements ), m_bNeedsSort( false )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Allows methods to set a context to be used with the less function..
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+void CUtlSortVector<T, LessFunc, BaseVector>::SetLessContext( void *pCtx )
+{
+ m_pLessContext = pCtx;
+}
+
+//-----------------------------------------------------------------------------
+// grows the vector
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+int CUtlSortVector<T, LessFunc, BaseVector>::Insert( const T& src )
+{
+ AssertFatal( !m_bNeedsSort );
+
+ int pos = FindLessOrEqual( src ) + 1;
+ this->GrowVector();
+ this->ShiftElementsRight(pos);
+ CopyConstruct<T>( &this->Element(pos), src );
+ return pos;
+}
+
+template <class T, class LessFunc, class BaseVector>
+int CUtlSortVector<T, LessFunc, BaseVector>::InsertNoSort( const T& src )
+{
+ m_bNeedsSort = true;
+ int lastElement = BaseVector::m_Size;
+ // Just stick the new element at the end of the vector, but don't do a sort
+ this->GrowVector();
+ this->ShiftElementsRight(lastElement);
+ CopyConstruct( &this->Element(lastElement), src );
+ return lastElement;
+}
+
+template <class T, class LessFunc, class BaseVector>
+void CUtlSortVector<T, LessFunc, BaseVector>::QuickSort( LessFunc& less, int nLower, int nUpper )
+{
+#ifdef _WIN32
+ typedef int (__cdecl *QSortCompareFunc_t)(void *context, const void *, const void *);
+ if ( this->Count() > 1 )
+ {
+ QSortContext_t ctx;
+ ctx.m_pLessContext = m_pLessContext;
+ ctx.m_pLessFunc = &less;
+
+ qsort_s( Base(), Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector<T, LessFunc>::CompareHelper, &ctx );
+ }
+#else
+ typedef int (__cdecl *QSortCompareFunc_t)( const void *, const void *);
+ if ( this->Count() > 1 )
+ {
+ QSortContext_t ctx;
+ ctx.m_pLessContext = m_pLessContext;
+ ctx.m_pLessFunc = &less;
+ g_pUtlSortVectorQSortContext = &ctx;
+
+ qsort( this->Base(), this->Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector<T, LessFunc>::CompareHelper );
+ }
+#endif
+}
+
+template <class T, class LessFunc, class BaseVector>
+void CUtlSortVector<T, LessFunc, BaseVector>::RedoSort( bool bForceSort /*= false */ )
+{
+ if ( !m_bNeedsSort && !bForceSort )
+ return;
+
+ m_bNeedsSort = false;
+ LessFunc less;
+ QuickSort( less, 0, this->Count() - 1 );
+}
+
+//-----------------------------------------------------------------------------
+// finds a particular element
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+int CUtlSortVector<T, LessFunc, BaseVector>::Find( const T& src ) const
+{
+ AssertFatal( !m_bNeedsSort );
+
+ LessFunc less;
+
+ int start = 0, end = this->Count() - 1;
+ while (start <= end)
+ {
+ int mid = (start + end) >> 1;
+ if ( less.Less( this->Element(mid), src, m_pLessContext ) )
+ {
+ start = mid + 1;
+ }
+ else if ( less.Less( src, this->Element(mid), m_pLessContext ) )
+ {
+ end = mid - 1;
+ }
+ else
+ {
+ return mid;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// finds a particular element
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+template <typename K>
+int CUtlSortVector<T, LessFunc, BaseVector>::FindAs( const K& key ) const
+{
+ AssertFatal( !m_bNeedsSort );
+
+ LessFunc less;
+
+ int start = 0, end = this->Count() - 1;
+ while (start <= end)
+ {
+ int mid = (start + end) >> 1;
+ int nResult = less.Compare( this->Element(mid), key, m_pLessContext );
+ if ( nResult < 0 )
+ {
+ start = mid + 1;
+ }
+ else if ( nResult > 0 )
+ {
+ end = mid - 1;
+ }
+ else
+ {
+ return mid;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// finds a particular element
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+int CUtlSortVector<T, LessFunc, BaseVector>::FindLessOrEqual( const T& src ) const
+{
+ AssertFatal( !m_bNeedsSort );
+
+ LessFunc less;
+ int start = 0, end = this->Count() - 1;
+ while (start <= end)
+ {
+ int mid = (start + end) >> 1;
+ if ( less.Less( this->Element(mid), src, m_pLessContext ) )
+ {
+ start = mid + 1;
+ }
+ else if ( less.Less( src, this->Element(mid), m_pLessContext ) )
+ {
+ end = mid - 1;
+ }
+ else
+ {
+ return mid;
+ }
+ }
+ return end;
+}
+
+template <class T, class LessFunc, class BaseVector>
+int CUtlSortVector<T, LessFunc, BaseVector>::FindLess( const T& src ) const
+{
+ AssertFatal( !m_bNeedsSort );
+
+ LessFunc less;
+ int start = 0, end = this->Count() - 1;
+ while (start <= end)
+ {
+ int mid = (start + end) >> 1;
+ if ( less.Less( this->Element(mid), src, m_pLessContext ) )
+ {
+ start = mid + 1;
+ }
+ else
+ {
+ end = mid - 1;
+ }
+ }
+ return end;
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes a particular element
+//-----------------------------------------------------------------------------
+template <class T, class LessFunc, class BaseVector>
+void CUtlSortVector<T, LessFunc, BaseVector>::Remove( const T& search )
+{
+ AssertFatal( !m_bNeedsSort );
+
+ int pos = Find(search);
+ if (pos != -1)
+ {
+ BaseVector::Remove(pos);
+ }
+}
+
+template <class T, class LessFunc, class BaseVector>
+void CUtlSortVector<T, LessFunc, BaseVector>::Remove( int i )
+{
+ BaseVector::Remove( i );
+}
+
+#endif // UTLSORTVECTOR_H
diff --git a/external/vpc/public/tier1/utlstack.h b/external/vpc/public/tier1/utlstack.h
new file mode 100644
index 0000000..c7ab48d
--- /dev/null
+++ b/external/vpc/public/tier1/utlstack.h
@@ -0,0 +1,331 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A stack based on a growable array
+//=============================================================================//
+
+#ifndef UTLSTACK_H
+#define UTLSTACK_H
+
+#include <assert.h>
+#include <string.h>
+#include "utlmemory.h"
+
+
+//-----------------------------------------------------------------------------
+// The CUtlStack class:
+// A growable stack class which doubles in size by default.
+// It will always keep all elements consecutive in memory, and may move the
+// elements around in memory (via a realloc) when elements are pushed or
+// popped. Clients should therefore refer to the elements of the stack
+// by index (they should *never* maintain pointers to elements in the stack).
+//-----------------------------------------------------------------------------
+
+template< class T, class M = CUtlMemory< T > >
+class CUtlStack
+{
+public:
+ // constructor, destructor
+ CUtlStack( int growSize = 0, int initSize = 0 );
+ ~CUtlStack();
+
+ void CopyFrom( const CUtlStack<T, M> &from );
+
+ // element access
+ T& operator[]( int i );
+ T const& operator[]( int i ) const;
+ T& Element( int i );
+ T const& Element( int i ) const;
+
+ // Gets the base address (can change when adding elements!)
+ T* Base();
+ T const* Base() const;
+
+ // Looks at the stack top
+ T& Top();
+ T const& Top() const;
+
+ // Size
+ int Count() const;
+
+ // Is element index valid?
+ bool IsIdxValid( int i ) const;
+
+ // Adds an element, uses default constructor
+ int Push();
+
+ // Adds an element, uses copy constructor
+ int Push( T const& src );
+
+ // Pops the stack
+ void Pop();
+ void Pop( T& oldTop );
+ void PopMultiple( int num );
+
+ // Makes sure we have enough memory allocated to store a requested # of elements
+ void EnsureCapacity( int num );
+
+ // Clears the stack, no deallocation
+ void Clear();
+
+ // Memory deallocation
+ void Purge();
+
+private:
+ // Grows the stack allocation
+ void GrowStack();
+
+ // For easier access to the elements through the debugger
+ void ResetDbgInfo();
+
+ M m_Memory;
+ int m_Size;
+
+ // For easier access to the elements through the debugger
+ T* m_pElements;
+};
+
+
+//-----------------------------------------------------------------------------
+// For easier access to the elements through the debugger
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline void CUtlStack<T,M>::ResetDbgInfo()
+{
+ m_pElements = m_Memory.Base();
+}
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+CUtlStack<T,M>::CUtlStack( int growSize, int initSize ) :
+ m_Memory(growSize, initSize), m_Size(0)
+{
+ ResetDbgInfo();
+}
+
+template< class T, class M >
+CUtlStack<T,M>::~CUtlStack()
+{
+ Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// copy into
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::CopyFrom( const CUtlStack<T, M> &from )
+{
+ Purge();
+ EnsureCapacity( from.Count() );
+ for ( int i = 0; i < from.Count(); i++ )
+ {
+ Push( from[i] );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T& CUtlStack<T,M>::operator[]( int i )
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+template< class T, class M >
+inline T const& CUtlStack<T,M>::operator[]( int i ) const
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+template< class T, class M >
+inline T& CUtlStack<T,M>::Element( int i )
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+template< class T, class M >
+inline T const& CUtlStack<T,M>::Element( int i ) const
+{
+ assert( IsIdxValid(i) );
+ return m_Memory[i];
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the base address (can change when adding elements!)
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T* CUtlStack<T,M>::Base()
+{
+ return m_Memory.Base();
+}
+
+template< class T, class M >
+inline T const* CUtlStack<T,M>::Base() const
+{
+ return m_Memory.Base();
+}
+
+//-----------------------------------------------------------------------------
+// Returns the top of the stack
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline T& CUtlStack<T,M>::Top()
+{
+ assert( m_Size > 0 );
+ return Element(m_Size-1);
+}
+
+template< class T, class M >
+inline T const& CUtlStack<T,M>::Top() const
+{
+ assert( m_Size > 0 );
+ return Element(m_Size-1);
+}
+
+//-----------------------------------------------------------------------------
+// Size
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline int CUtlStack<T,M>::Count() const
+{
+ return m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+inline bool CUtlStack<T,M>::IsIdxValid( int i ) const
+{
+ return (i >= 0) && (i < m_Size);
+}
+
+//-----------------------------------------------------------------------------
+// Grows the stack
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::GrowStack()
+{
+ if (m_Size >= m_Memory.NumAllocated())
+ m_Memory.Grow();
+
+ ++m_Size;
+
+ ResetDbgInfo();
+}
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::EnsureCapacity( int num )
+{
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses default constructor
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+int CUtlStack<T,M>::Push()
+{
+ GrowStack();
+ Construct( &Element(m_Size-1) );
+ return m_Size - 1;
+}
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses copy constructor
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+int CUtlStack<T,M>::Push( T const& src )
+{
+ GrowStack();
+ CopyConstruct( &Element(m_Size-1), src );
+ return m_Size - 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Pops the stack
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::Pop()
+{
+ assert( m_Size > 0 );
+ Destruct( &Element(m_Size-1) );
+ --m_Size;
+}
+
+template< class T, class M >
+void CUtlStack<T,M>::Pop( T& oldTop )
+{
+ assert( m_Size > 0 );
+ oldTop = Top();
+ Pop();
+}
+
+template< class T, class M >
+void CUtlStack<T,M>::PopMultiple( int num )
+{
+ assert( m_Size >= num );
+ for ( int i = 0; i < num; ++i )
+ Destruct( &Element( m_Size - i - 1 ) );
+ m_Size -= num;
+}
+
+
+//-----------------------------------------------------------------------------
+// Element removal
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::Clear()
+{
+ for (int i = m_Size; --i >= 0; )
+ Destruct(&Element(i));
+
+ m_Size = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+
+template< class T, class M >
+void CUtlStack<T,M>::Purge()
+{
+ Clear();
+ m_Memory.Purge( );
+ ResetDbgInfo();
+}
+
+#endif // UTLSTACK_H
diff --git a/external/vpc/public/tier1/utlstring.h b/external/vpc/public/tier1/utlstring.h
new file mode 100644
index 0000000..0bd60f0
--- /dev/null
+++ b/external/vpc/public/tier1/utlstring.h
@@ -0,0 +1,373 @@
+//====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef UTLSTRING_H
+#define UTLSTRING_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "tier1/utlmemory.h"
+#include "tier1/strtools.h"
+#include "limits.h"
+
+
+//-----------------------------------------------------------------------------
+// Base class, containing simple memory management
+//-----------------------------------------------------------------------------
+class CUtlBinaryBlock
+{
+public:
+ CUtlBinaryBlock( int growSize = 0, int initSize = 0 );
+ ~CUtlBinaryBlock()
+ {
+#ifdef _DEBUG
+ m_nActualLength = 0x7BADF00D;
+#else
+ m_nActualLength = 0;
+#endif
+ }
+
+ // NOTE: nInitialLength indicates how much of the buffer starts full
+ CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength );
+ CUtlBinaryBlock( const void* pMemory, int nSizeInBytes );
+ CUtlBinaryBlock( const CUtlBinaryBlock& src );
+
+ void Get( void *pValue, int nMaxLen ) const;
+ void Set( const void *pValue, int nLen );
+ const void *Get( ) const;
+ void *Get( );
+
+ unsigned char& operator[]( int i );
+ const unsigned char& operator[]( int i ) const;
+
+ int Length() const;
+ void SetLength( int nLength ); // Undefined memory will result
+ bool IsEmpty() const;
+ void Clear();
+ void Purge();
+
+ bool IsReadOnly() const;
+
+ CUtlBinaryBlock &operator=( const CUtlBinaryBlock &src );
+
+ // Test for equality
+ bool operator==( const CUtlBinaryBlock &src ) const;
+
+private:
+ CUtlMemory<unsigned char> m_Memory;
+ int m_nActualLength;
+};
+
+
+//-----------------------------------------------------------------------------
+// class inlines
+//-----------------------------------------------------------------------------
+inline const void *CUtlBinaryBlock::Get( ) const
+{
+ return m_Memory.Base();
+}
+
+inline void *CUtlBinaryBlock::Get( )
+{
+ return m_Memory.Base();
+}
+
+inline int CUtlBinaryBlock::Length() const
+{
+ return m_nActualLength;
+}
+
+inline unsigned char& CUtlBinaryBlock::operator[]( int i )
+{
+ return m_Memory[i];
+}
+
+inline const unsigned char& CUtlBinaryBlock::operator[]( int i ) const
+{
+ return m_Memory[i];
+}
+
+inline bool CUtlBinaryBlock::IsReadOnly() const
+{
+ return m_Memory.IsReadOnly();
+}
+
+inline bool CUtlBinaryBlock::IsEmpty() const
+{
+ return Length() == 0;
+}
+
+inline void CUtlBinaryBlock::Clear()
+{
+ SetLength( 0 );
+}
+
+inline void CUtlBinaryBlock::Purge()
+{
+ SetLength( 0 );
+ m_Memory.Purge();
+}
+
+
+//-----------------------------------------------------------------------------
+// Simple string class.
+// NOTE: This is *not* optimal! Use in tools, but not runtime code
+//-----------------------------------------------------------------------------
+class CUtlString
+{
+public:
+ typedef enum
+ {
+ PATTERN_NONE = 0x00000000,
+ PATTERN_DIRECTORY = 0x00000001
+ } TUtlStringPattern;
+
+public:
+ CUtlString();
+ CUtlString( const char *pString );
+ CUtlString( const CUtlString& string );
+
+ // Attaches the string to external memory. Useful for avoiding a copy
+ CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength );
+ CUtlString( const void* pMemory, int nSizeInBytes );
+
+ const char *Get( ) const;
+ void Set( const char *pValue );
+
+ void Clear() { Set( NULL ); }
+
+ // Converts to c-strings
+ operator const char*() const;
+
+ // for compatibility switching items from UtlSymbol
+ const char *String() const { return Get(); }
+
+ // Returns strlen
+ int Length() const;
+ bool IsEmpty() const;
+
+ // Sets the length (used to serialize into the buffer )
+ // Note: If nLen != 0, then this adds an extra byte for a null-terminator.
+ void SetLength( int nLen );
+ char *Get();
+ void Purge();
+
+ // Case Change
+ void ToLower( );
+
+ void Append( const char *pchAddition );
+
+ // Strips the trailing slash
+ void StripTrailingSlash();
+
+ CUtlString &operator=( const CUtlString &src );
+ CUtlString &operator=( const char *src );
+
+ // Test for equality
+ bool operator==( const CUtlString &src ) const;
+ bool operator==( const char *src ) const;
+ bool operator!=( const CUtlString &src ) const { return !operator==( src ); }
+ bool operator!=( const char *src ) const { return !operator==( src ); }
+
+ // If these are not defined, CUtlString as rhs will auto-convert
+ // to const char* and do logical operations on the raw pointers. Ugh.
+ inline friend bool operator==( const char *lhs, const CUtlString &rhs ) { return rhs.operator==( lhs ); }
+ inline friend bool operator!=( const char *lhs, const CUtlString &rhs ) { return rhs.operator!=( lhs ); }
+
+ CUtlString &operator+=( const CUtlString &rhs );
+ CUtlString &operator+=( const char *rhs );
+ CUtlString &operator+=( char c );
+ CUtlString &operator+=( int rhs );
+ CUtlString &operator+=( double rhs );
+
+ CUtlString operator+( const char *pOther ) const;
+
+ bool MatchesPattern( const CUtlString &Pattern, int nFlags = 0 ) const; // case SENSITIVE, use * for wildcard in pattern string
+
+ int Format( const char *pFormat, ... );
+ void SetDirect( const char *pValue, int nChars );
+
+ // Defining AltArgumentType_t hints that associative container classes should
+ // also implement Find/Insert/Remove functions that take const char* params.
+ typedef const char *AltArgumentType_t;
+
+ // Take a piece out of the string.
+ // If you only specify nStart, it'll go from nStart to the end.
+ // You can use negative numbers and it'll wrap around to the start.
+ CUtlString Slice( int32 nStart=0, int32 nEnd=INT_MAX ) const;
+
+ // Grab a substring starting from the left or the right side.
+ CUtlString Left( int32 nChars ) const;
+ CUtlString Right( int32 nChars ) const;
+
+ // Replace all instances of one character with another.
+ CUtlString Replace( char cFrom, char cTo ) const;
+
+ // Calls right through to V_MakeAbsolutePath.
+ CUtlString AbsPath( const char *pStartingDir=NULL ) const;
+
+ // Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt).
+ CUtlString UnqualifiedFilename() const;
+
+ // Strips off one directory. Uses V_StripLastDir but strips the last slash also!
+ CUtlString DirName() const;
+
+ // Works like V_ComposeFileName.
+ static CUtlString PathJoin( const char *pStr1, const char *pStr2 );
+
+ // These can be used for utlvector sorts.
+ static int __cdecl SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 );
+ static int __cdecl SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 );
+
+private:
+ CUtlBinaryBlock m_Storage;
+};
+
+//-----------------------------------------------------------------------------
+// Inline methods
+//-----------------------------------------------------------------------------
+inline bool CUtlString::IsEmpty() const
+{
+ return Length() == 0;
+}
+
+inline int __cdecl CUtlString::SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 )
+{
+ return V_stricmp( pString1->String(), pString2->String() );
+}
+
+inline int __cdecl CUtlString::SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 )
+{
+ return V_strcmp( pString1->String(), pString2->String() );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Implementation of low-level string functionality for character types.
+//-----------------------------------------------------------------------------
+
+template < typename T >
+class StringFuncs
+{
+public:
+ static T *Duplicate( const T *pValue );
+ static void Copy( T *out_pOut, const T *pIn, int iLength );
+ static int Compare( const T *pLhs, const T *pRhs );
+ static int Length( const T *pValue );
+ static const T *FindChar( const T *pStr, const T cSearch );
+ static const T *EmptyString();
+};
+
+template < >
+class StringFuncs<char>
+{
+public:
+ static char *Duplicate( const char *pValue ) { return strdup( pValue ); }
+ static void Copy( char *out_pOut, const char *pIn, int iLength ) { strncpy( out_pOut, pIn, iLength ); }
+ static int Compare( const char *pLhs, const char *pRhs ) { return strcmp( pLhs, pRhs ); }
+ static int Length( const char *pValue ) { return strlen( pValue ); }
+ static const char *FindChar( const char *pStr, const char cSearch ) { return strchr( pStr, cSearch ); }
+ static const char *EmptyString() { return ""; }
+};
+
+template < >
+class StringFuncs<wchar_t>
+{
+public:
+ static wchar_t *Duplicate( const wchar_t *pValue ) { return wcsdup( pValue ); }
+ static void Copy( wchar_t *out_pOut, const wchar_t *pIn, int iLength ) { wcsncpy( out_pOut, pIn, iLength ); }
+ static int Compare( const wchar_t *pLhs, const wchar_t *pRhs ) { return wcscmp( pLhs, pRhs ); }
+ static int Length( const wchar_t *pValue ) { return wcslen( pValue ); }
+ static const wchar_t *FindChar( const wchar_t *pStr, const wchar_t cSearch ) { return wcschr( pStr, cSearch ); }
+ static const wchar_t *EmptyString() { return L""; }
+};
+
+//-----------------------------------------------------------------------------
+// Dirt-basic auto-release string class. Not intended for manipulation,
+// can be stored in a container or forwarded as a functor parameter.
+// Note the benefit over CUtlString: sizeof(CUtlConstString) == sizeof(char*).
+// Also note: null char* pointers are treated identically to empty strings.
+//-----------------------------------------------------------------------------
+
+template < typename T = char >
+class CUtlConstStringBase
+{
+public:
+ CUtlConstStringBase() : m_pString( NULL ) {}
+ CUtlConstStringBase( const T *pString ) : m_pString( NULL ) { Set( pString ); }
+ CUtlConstStringBase( const CUtlConstStringBase& src ) : m_pString( NULL ) { Set( src.m_pString ); }
+ ~CUtlConstStringBase() { Set( NULL ); }
+
+ void Set( const T *pValue );
+ void Clear() { Set( NULL ); }
+
+ const T *Get() const { return m_pString ? m_pString : StringFuncs<T>::EmptyString(); }
+ operator const T*() const { return m_pString ? m_pString : StringFuncs<T>::EmptyString(); }
+
+ bool IsEmpty() const { return m_pString == NULL; } // Note: empty strings are never stored by Set
+
+ int Compare( const T *rhs ) const;
+
+ // Logical ops
+ bool operator<( const T *rhs ) const { return Compare( rhs ) < 0; }
+ bool operator==( const T *rhs ) const { return Compare( rhs ) == 0; }
+ bool operator!=( const T *rhs ) const { return Compare( rhs ) != 0; }
+ bool operator<( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) < 0; }
+ bool operator==( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) == 0; }
+ bool operator!=( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) != 0; }
+
+ // If these are not defined, CUtlConstString as rhs will auto-convert
+ // to const char* and do logical operations on the raw pointers. Ugh.
+ inline friend bool operator<( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) > 0; }
+ inline friend bool operator==( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) == 0; }
+ inline friend bool operator!=( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) != 0; }
+
+ CUtlConstStringBase &operator=( const T *src ) { Set( src ); return *this; }
+ CUtlConstStringBase &operator=( const CUtlConstStringBase &src ) { Set( src.m_pString ); return *this; }
+
+ // Defining AltArgumentType_t is a hint to containers that they should
+ // implement Find/Insert/Remove functions that take const char* params.
+ typedef const T *AltArgumentType_t;
+
+protected:
+ const T *m_pString;
+};
+
+template < typename T >
+void CUtlConstStringBase<T>::Set( const T *pValue )
+{
+ if ( pValue != m_pString )
+ {
+ free( ( void* ) m_pString );
+ m_pString = pValue && pValue[0] ? StringFuncs<T>::Duplicate( pValue ) : NULL;
+ }
+}
+
+template < typename T >
+int CUtlConstStringBase<T>::Compare( const T *rhs ) const
+{
+ if ( m_pString )
+ {
+ if ( rhs )
+ return StringFuncs<T>::Compare( m_pString, rhs );
+ else
+ return 1;
+ }
+ else
+ {
+ if ( rhs )
+ return -1;
+ else
+ return 0;
+ }
+}
+
+typedef CUtlConstStringBase<char> CUtlConstString;
+typedef CUtlConstStringBase<wchar_t> CUtlConstWideString;
+
+
+#endif // UTLSTRING_H
diff --git a/external/vpc/public/tier1/utlsymbol.h b/external/vpc/public/tier1/utlsymbol.h
new file mode 100644
index 0000000..06b8f04
--- /dev/null
+++ b/external/vpc/public/tier1/utlsymbol.h
@@ -0,0 +1,345 @@
+//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: Defines a symbol table
+//
+// $Header: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef UTLSYMBOL_H
+#define UTLSYMBOL_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/threadtools.h"
+#include "tier1/utlrbtree.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlbuffer.h"
+#include "tier1/utllinkedlist.h"
+#include "tier1/stringpool.h"
+
+
+//-----------------------------------------------------------------------------
+// forward declarations
+//-----------------------------------------------------------------------------
+class CUtlSymbolTable;
+class CUtlSymbolTableMT;
+
+
+//-----------------------------------------------------------------------------
+// This is a symbol, which is a easier way of dealing with strings.
+//-----------------------------------------------------------------------------
+typedef unsigned short UtlSymId_t;
+
+#define UTL_INVAL_SYMBOL ((UtlSymId_t)~0)
+
+class CUtlSymbol
+{
+public:
+ // constructor, destructor
+ CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {}
+ CUtlSymbol( UtlSymId_t id ) : m_Id(id) {}
+ CUtlSymbol( const char* pStr );
+ CUtlSymbol( CUtlSymbol const& sym ) : m_Id(sym.m_Id) {}
+
+ // operator=
+ CUtlSymbol& operator=( CUtlSymbol const& src ) { m_Id = src.m_Id; return *this; }
+
+ // operator==
+ bool operator==( CUtlSymbol const& src ) const { return m_Id == src.m_Id; }
+ bool operator==( const char* pStr ) const;
+
+ // Is valid?
+ bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
+
+ // Gets at the symbol
+ operator UtlSymId_t () const { return m_Id; }
+
+ // Gets the string associated with the symbol
+ const char* String( ) const;
+
+ // Modules can choose to disable the static symbol table so to prevent accidental use of them.
+ static void DisableStaticSymbolTable();
+
+ // Methods with explicit locking mechanism. Only use for optimization reasons.
+ static void LockTableForRead();
+ static void UnlockTableForRead();
+ const char * StringNoLock() const;
+
+protected:
+ UtlSymId_t m_Id;
+
+ // Initializes the symbol table
+ static void Initialize();
+
+ // returns the current symbol table
+ static CUtlSymbolTableMT* CurrTable();
+
+ // The standard global symbol table
+ static CUtlSymbolTableMT* s_pSymbolTable;
+
+ static bool s_bAllowStaticSymbolTable;
+
+ friend class CCleanupUtlSymbolTable;
+};
+
+
+//-----------------------------------------------------------------------------
+// CUtlSymbolTable:
+// description:
+// This class defines a symbol table, which allows us to perform mappings
+// of strings to symbols and back. The symbol class itself contains
+// a static version of this class for creating global strings, but this
+// class can also be instanced to create local symbol tables.
+//
+// This class stores the strings in a series of string pools. The first
+// two bytes of each string are decorated with a hash to speed up
+// comparisons.
+//-----------------------------------------------------------------------------
+
+class CUtlSymbolTable
+{
+public:
+ // constructor, destructor
+ CUtlSymbolTable( int growSize = 0, int initSize = 16, bool caseInsensitive = false );
+ ~CUtlSymbolTable();
+
+ // Finds and/or creates a symbol based on the string
+ CUtlSymbol AddString( const char* pString );
+
+ // Finds the symbol for pString
+ CUtlSymbol Find( const char* pString ) const;
+
+ // Look up the string associated with a particular symbol
+ const char* String( CUtlSymbol id ) const;
+
+ // Remove all symbols in the table.
+ void RemoveAll();
+
+ int GetNumStrings( void ) const
+ {
+ return m_Lookup.Count();
+ }
+
+ // We store one of these at the beginning of every string to speed
+ // up comparisons.
+ typedef unsigned short hashDecoration_t;
+
+protected:
+ class CStringPoolIndex
+ {
+ public:
+ inline CStringPoolIndex()
+ {
+ }
+
+ inline CStringPoolIndex( unsigned short iPool, unsigned short iOffset )
+ : m_iPool(iPool), m_iOffset(iOffset)
+ {}
+
+ inline bool operator==( const CStringPoolIndex &other ) const
+ {
+ return m_iPool == other.m_iPool && m_iOffset == other.m_iOffset;
+ }
+
+ unsigned short m_iPool; // Index into m_StringPools.
+ unsigned short m_iOffset; // Index into the string pool.
+ };
+
+ class CLess
+ {
+ public:
+ CLess( int ignored = 0 ) {} // permits default initialization to NULL in CUtlRBTree
+ bool operator!() const { return false; }
+ bool operator()( const CStringPoolIndex &left, const CStringPoolIndex &right ) const;
+ };
+
+ // Stores the symbol lookup
+ class CTree : public CUtlRBTree<CStringPoolIndex, unsigned short, CLess>
+ {
+ public:
+ CTree( int growSize, int initSize ) : CUtlRBTree<CStringPoolIndex, unsigned short, CLess>( growSize, initSize ) {}
+ friend class CUtlSymbolTable::CLess; // Needed to allow CLess to calculate pointer to symbol table
+ };
+
+ struct StringPool_t
+ {
+ int m_TotalLen; // How large is
+ int m_SpaceUsed;
+ char m_Data[1];
+ };
+
+ CTree m_Lookup;
+
+ bool m_bInsensitive;
+ mutable unsigned short m_nUserSearchStringHash;
+ mutable const char* m_pUserSearchString;
+
+ // stores the string data
+ CUtlVector<StringPool_t*> m_StringPools;
+
+private:
+ int FindPoolWithSpace( int len ) const;
+ const char* StringFromIndex( const CStringPoolIndex &index ) const;
+ const char* DecoratedStringFromIndex( const CStringPoolIndex &index ) const;
+
+ friend class CLess;
+ friend class CSymbolHash;
+
+};
+
+class CUtlSymbolTableMT : public CUtlSymbolTable
+{
+public:
+ CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false )
+ : CUtlSymbolTable( growSize, initSize, caseInsensitive )
+ {
+ }
+
+ CUtlSymbol AddString( const char* pString )
+ {
+ m_lock.LockForWrite();
+ CUtlSymbol result = CUtlSymbolTable::AddString( pString );
+ m_lock.UnlockWrite();
+ return result;
+ }
+
+ CUtlSymbol Find( const char* pString ) const
+ {
+ m_lock.LockForWrite();
+ CUtlSymbol result = CUtlSymbolTable::Find( pString );
+ m_lock.UnlockWrite();
+ return result;
+ }
+
+ const char* String( CUtlSymbol id ) const
+ {
+ m_lock.LockForRead();
+ const char *pszResult = CUtlSymbolTable::String( id );
+ m_lock.UnlockRead();
+ return pszResult;
+ }
+
+ const char * StringNoLock( CUtlSymbol id ) const
+ {
+ return CUtlSymbolTable::String( id );
+ }
+
+ void LockForRead()
+ {
+ m_lock.LockForRead();
+ }
+
+ void UnlockForRead()
+ {
+ m_lock.UnlockRead();
+ }
+
+private:
+#ifdef WIN32
+ mutable CThreadSpinRWLock m_lock;
+#else
+ mutable CThreadRWLock m_lock;
+#endif
+};
+
+
+
+//-----------------------------------------------------------------------------
+// CUtlFilenameSymbolTable:
+// description:
+// This class defines a symbol table of individual filenames, stored more
+// efficiently than a standard symbol table. Internally filenames are broken
+// up into file and path entries, and a file handle class allows convenient
+// access to these.
+//-----------------------------------------------------------------------------
+
+// The handle is a CUtlSymbol for the dirname and the same for the filename, the accessor
+// copies them into a static char buffer for return.
+typedef void* FileNameHandle_t;
+
+// Symbol table for more efficiently storing filenames by breaking paths and filenames apart.
+// Refactored from Basefilesystem.h
+class CUtlFilenameSymbolTable
+{
+ // Internal representation of a FileHandle_t
+ // If we get more than 64K filenames, we'll have to revisit...
+ // Right now CUtlSymbol is a short, so this packs into an int/void * pointer size...
+ struct FileNameHandleInternal_t
+ {
+ FileNameHandleInternal_t()
+ {
+ path = 0;
+ file = 0;
+ }
+
+ // Part before the final '/' character
+ unsigned short path;
+ // Part after the final '/', including extension
+ unsigned short file;
+ };
+
+public:
+ FileNameHandle_t FindOrAddFileName( const char *pFileName );
+ FileNameHandle_t FindFileName( const char *pFileName );
+ int PathIndex(const FileNameHandle_t &handle) { return (( const FileNameHandleInternal_t * )&handle)->path; }
+ bool String( const FileNameHandle_t& handle, char *buf, int buflen );
+ void RemoveAll();
+ void SpewStrings();
+ bool SaveToBuffer( CUtlBuffer &buffer );
+ bool RestoreFromBuffer( CUtlBuffer &buffer );
+
+private:
+ CCountedStringPool m_StringPool;
+ mutable CThreadSpinRWLock m_lock;
+};
+
+// This creates a simple class that includes the underlying CUtlSymbol
+// as a private member and then instances a private symbol table to
+// manage those symbols. Avoids the possibility of the code polluting the
+// 'global'/default symbol table, while letting the code look like
+// it's just using = and .String() to look at CUtlSymbol type objects
+//
+// NOTE: You can't pass these objects between .dlls in an interface (also true of CUtlSymbol of course)
+//
+#define DECLARE_PRIVATE_SYMBOLTYPE( typename ) \
+ class typename \
+ { \
+ public: \
+ typename(); \
+ typename( const char* pStr ); \
+ typename& operator=( typename const& src ); \
+ bool operator==( typename const& src ) const; \
+ const char* String( ) const; \
+ private: \
+ CUtlSymbol m_SymbolId; \
+ };
+
+// Put this in the .cpp file that uses the above typename
+#define IMPLEMENT_PRIVATE_SYMBOLTYPE( typename ) \
+ static CUtlSymbolTable g_##typename##SymbolTable; \
+ typename::typename() \
+ { \
+ m_SymbolId = UTL_INVAL_SYMBOL; \
+ } \
+ typename::typename( const char* pStr ) \
+ { \
+ m_SymbolId = g_##typename##SymbolTable.AddString( pStr ); \
+ } \
+ typename& typename::operator=( typename const& src ) \
+ { \
+ m_SymbolId = src.m_SymbolId; \
+ return *this; \
+ } \
+ bool typename::operator==( typename const& src ) const \
+ { \
+ return ( m_SymbolId == src.m_SymbolId ); \
+ } \
+ const char* typename::String( ) const \
+ { \
+ return g_##typename##SymbolTable.String( m_SymbolId ); \
+ }
+
+#endif // UTLSYMBOL_H
diff --git a/external/vpc/public/tier1/utlvector.h b/external/vpc/public/tier1/utlvector.h
new file mode 100644
index 0000000..f98698f
--- /dev/null
+++ b/external/vpc/public/tier1/utlvector.h
@@ -0,0 +1,1275 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+// A growable array class that maintains a free list and keeps elements
+// in the same location
+//=============================================================================//
+
+#ifndef UTLVECTOR_H
+#define UTLVECTOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include <string.h>
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+#include "tier1/utlmemory.h"
+#include "tier1/utlblockmemory.h"
+#include "tier1/strtools.h"
+
+#define FOR_EACH_VEC( vecName, iteratorName ) \
+ for ( int iteratorName = 0; iteratorName < (vecName).Count(); iteratorName++ )
+#define FOR_EACH_VEC_BACK( vecName, iteratorName ) \
+ for ( int iteratorName = (vecName).Count()-1; iteratorName >= 0; iteratorName-- )
+
+//-----------------------------------------------------------------------------
+// The CUtlVector class:
+// A growable array class which doubles in size by default.
+// It will always keep all elements consecutive in memory, and may move the
+// elements around in memory (via a PvRealloc) when elements are inserted or
+// removed. Clients should therefore refer to the elements of the vector
+// by index (they should *never* maintain pointers to elements in the vector).
+//-----------------------------------------------------------------------------
+template< class T, class A = CUtlMemory<T> >
+class CUtlVector
+{
+ typedef A CAllocator;
+public:
+ typedef T ElemType_t;
+
+ // constructor, destructor
+ CUtlVector( int growSize = 0, int initSize = 0 );
+ CUtlVector( T* pMemory, int allocationCount, int numElements = 0 );
+ ~CUtlVector();
+
+ // Copy the array.
+ CUtlVector<T, A>& operator=( const CUtlVector<T, A> &other );
+
+ // element access
+ T& operator[]( int i );
+ const T& operator[]( int i ) const;
+ T& Element( int i );
+ const T& Element( int i ) const;
+ T& Head();
+ const T& Head() const;
+ T& Tail();
+ const T& Tail() const;
+
+ // Gets the base address (can change when adding elements!)
+ T* Base() { return m_Memory.Base(); }
+ const T* Base() const { return m_Memory.Base(); }
+
+ // Returns the number of elements in the vector
+ int Count() const;
+
+ // Is element index valid?
+ bool IsValidIndex( int i ) const;
+ static int InvalidIndex();
+
+ // Adds an element, uses default constructor
+ int AddToHead();
+ int AddToTail();
+ int InsertBefore( int elem );
+ int InsertAfter( int elem );
+
+ // Adds an element, uses copy constructor
+ int AddToHead( const T& src );
+ int AddToTail( const T& src );
+ int InsertBefore( int elem, const T& src );
+ int InsertAfter( int elem, const T& src );
+
+ // Adds multiple elements, uses default constructor
+ int AddMultipleToHead( int num );
+ int AddMultipleToTail( int num );
+ int AddMultipleToTail( int num, const T *pToCopy );
+ int InsertMultipleBefore( int elem, int num );
+ int InsertMultipleBefore( int elem, int num, const T *pToCopy );
+ int InsertMultipleAfter( int elem, int num );
+
+ // Calls RemoveAll() then AddMultipleToTail.
+ void SetSize( int size );
+ void SetCount( int count );
+ void SetCountNonDestructively( int count ); //sets count by adding or removing elements to tail TODO: This should probably be the default behavior for SetCount
+
+ // Calls SetSize and copies each element.
+ void CopyArray( const T *pArray, int size );
+
+ // Fast swap
+ void Swap( CUtlVector< T, A > &vec );
+
+ // Add the specified array to the tail.
+ int AddVectorToTail( CUtlVector<T, A> const &src );
+
+ // Finds an element (element needs operator== defined)
+ int Find( const T& src ) const;
+ void FillWithValue( const T& src );
+
+ bool HasElement( const T& src ) const;
+
+ // Makes sure we have enough memory allocated to store a requested # of elements
+ void EnsureCapacity( int num );
+
+ // Makes sure we have at least this many elements
+ void EnsureCount( int num );
+
+ // Element removal
+ void FastRemove( int elem ); // doesn't preserve order
+ void Remove( int elem ); // preserves order, shifts elements
+ bool FindAndRemove( const T& src ); // removes first occurrence of src, preserves order, shifts elements
+ bool FindAndFastRemove( const T& src ); // removes first occurrence of src, doesn't preserve order
+ void RemoveMultiple( int elem, int num ); // preserves order, shifts elements
+ void RemoveMultipleFromHead(int num); // removes num elements from tail
+ void RemoveMultipleFromTail(int num); // removes num elements from tail
+ void RemoveAll(); // doesn't deallocate memory
+
+ // Memory deallocation
+ void Purge();
+
+ // Purges the list and calls delete on each element in it.
+ void PurgeAndDeleteElements();
+
+ // Compacts the vector to the number of elements actually in use
+ void Compact();
+
+ // Set the size by which it grows when it needs to allocate more memory.
+ void SetGrowSize( int size ) { m_Memory.SetGrowSize( size ); }
+
+ int NumAllocated() const; // Only use this if you really know what you're doing!
+
+ void Sort( int (__cdecl *pfnCompare)(const T *, const T *) );
+
+ // Call this to quickly sort non-contiguously allocated vectors
+ void InPlaceQuickSort( int (__cdecl *pfnCompare)(const T *, const T *) );
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, char *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+protected:
+ // Can't copy this unless we explicitly do it!
+ CUtlVector( CUtlVector const& vec ) { Assert(0); }
+
+ // Grows the vector
+ void GrowVector( int num = 1 );
+
+
+ // Shifts elements....
+ void ShiftElementsRight( int elem, int num = 1 );
+ void ShiftElementsLeft( int elem, int num = 1 );
+
+ CAllocator m_Memory;
+ int m_Size;
+
+#ifndef _X360
+ // For easier access to the elements through the debugger
+ // it's in release builds so this can be used in libraries correctly
+ T *m_pElements;
+
+ inline void ResetDbgInfo()
+ {
+ m_pElements = Base();
+ }
+#else
+ inline void ResetDbgInfo() {}
+#endif
+
+private:
+ void InPlaceQuickSort_r( int (__cdecl *pfnCompare)(const T *, const T *), int nLeft, int nRight );
+};
+
+
+// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice
+template < class T >
+class CUtlBlockVector : public CUtlVector< T, CUtlBlockMemory< T, int > >
+{
+public:
+ CUtlBlockVector( int growSize = 0, int initSize = 0 )
+ : CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {}
+};
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorMT class:
+// An array class with spurious mutex protection. Nothing is actually protected
+// unless you call Lock and Unlock. Also, the Mutex_t is actually not a type
+// but a member which probably isn't used.
+//-----------------------------------------------------------------------------
+
+template< class BASE_UTLVECTOR, class MUTEX_TYPE = CThreadFastMutex >
+class CUtlVectorMT : public BASE_UTLVECTOR, public MUTEX_TYPE
+{
+ typedef BASE_UTLVECTOR BaseClass;
+public:
+ // MUTEX_TYPE Mutex_t;
+
+ // constructor, destructor
+ CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlVectorMT( typename BaseClass::ElemType_t* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorFixed class:
+// A array class with a fixed allocation scheme
+//-----------------------------------------------------------------------------
+template< class T, size_t MAX_SIZE >
+class CUtlVectorFixed : public CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > >
+{
+ typedef CUtlVector< T, CUtlMemoryFixed<T, MAX_SIZE > > BaseClass;
+public:
+
+ // constructor, destructor
+ CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorFixedGrowable class:
+// A array class with a fixed allocation scheme backed by a dynamic one
+//-----------------------------------------------------------------------------
+template< class T, size_t MAX_SIZE >
+class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > >
+{
+ typedef CUtlVector< T, CUtlMemoryFixedGrowable<T, MAX_SIZE > > BaseClass;
+
+public:
+ // constructor, destructor
+ CUtlVectorFixedGrowable( int growSize = 0 ) : BaseClass( growSize, MAX_SIZE ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorConservative class:
+// A array class with a conservative allocation scheme
+//-----------------------------------------------------------------------------
+template< class T >
+class CUtlVectorConservative : public CUtlVector< T, CUtlMemoryConservative<T> >
+{
+ typedef CUtlVector< T, CUtlMemoryConservative<T> > BaseClass;
+public:
+
+ // constructor, destructor
+ CUtlVectorConservative( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+};
+
+
+//-----------------------------------------------------------------------------
+// The CUtlVectorUltra Conservative class:
+// A array class with a very conservative allocation scheme, with customizable allocator
+// Especialy useful if you have a lot of vectors that are sparse, or if you're
+// carefully packing holders of vectors
+//-----------------------------------------------------------------------------
+#pragma warning(push)
+#pragma warning(disable : 4200) // warning C4200: nonstandard extension used : zero-sized array in struct/union
+#pragma warning(disable : 4815 ) // warning C4815: 'staticData' : zero-sized array in stack object will have no elements
+
+class CUtlVectorUltraConservativeAllocator
+{
+public:
+ static void *Alloc( size_t nSize )
+ {
+ return malloc( nSize );
+ }
+
+ static void *Realloc( void *pMem, size_t nSize )
+ {
+ return realloc( pMem, nSize );
+ }
+
+ static void Free( void *pMem )
+ {
+ free( pMem );
+ }
+
+ static size_t GetSize( void *pMem )
+ {
+ return mallocsize( pMem );
+ }
+
+};
+
+template <typename T, typename A = CUtlVectorUltraConservativeAllocator >
+class CUtlVectorUltraConservative : private A
+{
+public:
+ CUtlVectorUltraConservative()
+ {
+ m_pData = StaticData();
+ }
+
+ ~CUtlVectorUltraConservative()
+ {
+ RemoveAll();
+ }
+
+ int Count() const
+ {
+ return m_pData->m_Size;
+ }
+
+ static int InvalidIndex()
+ {
+ return -1;
+ }
+
+ inline bool IsValidIndex( int i ) const
+ {
+ return (i >= 0) && (i < Count());
+ }
+
+ T& operator[]( int i )
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ const T& operator[]( int i ) const
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ T& Element( int i )
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ const T& Element( int i ) const
+ {
+ Assert( IsValidIndex( i ) );
+ return m_pData->m_Elements[i];
+ }
+
+ void EnsureCapacity( int num )
+ {
+ int nCurCount = Count();
+ if ( num <= nCurCount )
+ {
+ return;
+ }
+ if ( m_pData == StaticData() )
+ {
+ m_pData = (Data_t *)A::Alloc( sizeof(int) + ( num * sizeof(T) ) );
+ m_pData->m_Size = 0;
+ }
+ else
+ {
+ int nNeeded = sizeof(int) + ( num * sizeof(T) );
+ int nHave = A::GetSize( m_pData );
+ if ( nNeeded > nHave )
+ {
+ m_pData = (Data_t *)A::Realloc( m_pData, nNeeded );
+ }
+ }
+ }
+
+ int AddToTail( const T& src )
+ {
+ int iNew = Count();
+ EnsureCapacity( Count() + 1 );
+ m_pData->m_Elements[iNew] = src;
+ m_pData->m_Size++;
+ return iNew;
+ }
+
+ void RemoveAll()
+ {
+ if ( Count() )
+ {
+ for (int i = m_pData->m_Size; --i >= 0; )
+ {
+ Destruct(&m_pData->m_Elements[i]);
+ }
+ }
+ if ( m_pData != StaticData() )
+ {
+ A::Free( m_pData );
+ m_pData = StaticData();
+
+ }
+ }
+
+ void PurgeAndDeleteElements()
+ {
+ if ( m_pData != StaticData() )
+ {
+ for( int i=0; i < m_pData->m_Size; i++ )
+ {
+ delete Element(i);
+ }
+ RemoveAll();
+ }
+ }
+
+ void FastRemove( int elem )
+ {
+ Assert( IsValidIndex(elem) );
+
+ Destruct( &Element(elem) );
+ if (Count() > 0)
+ {
+ if ( elem != m_pData->m_Size -1 )
+ memcpy( &Element(elem), &Element(m_pData->m_Size-1), sizeof(T) );
+ --m_pData->m_Size;
+ }
+ if ( !m_pData->m_Size )
+ {
+ A::Free( m_pData );
+ m_pData = StaticData();
+ }
+ }
+
+ void Remove( int elem )
+ {
+ Destruct( &Element(elem) );
+ ShiftElementsLeft(elem);
+ --m_pData->m_Size;
+ if ( !m_pData->m_Size )
+ {
+ A::Free( m_pData );
+ m_pData = StaticData();
+ }
+ }
+
+ int Find( const T& src ) const
+ {
+ int nCount = Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if (Element(i) == src)
+ return i;
+ }
+ return -1;
+ }
+
+ bool FindAndRemove( const T& src )
+ {
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ Remove( elem );
+ return true;
+ }
+ return false;
+ }
+
+
+ bool FindAndFastRemove( const T& src )
+ {
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ FastRemove( elem );
+ return true;
+ }
+ return false;
+ }
+
+ struct Data_t
+ {
+ int m_Size;
+ T m_Elements[];
+ };
+
+ Data_t *m_pData;
+private:
+ void ShiftElementsLeft( int elem, int num = 1 )
+ {
+ int Size = Count();
+ Assert( IsValidIndex(elem) || ( Size == 0 ) || ( num == 0 ));
+ int numToMove = Size - elem - num;
+ if ((numToMove > 0) && (num > 0))
+ {
+ V_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
+
+#ifdef _DEBUG
+ V_memset( &Element(Size-num), 0xDD, num * sizeof(T) );
+#endif
+ }
+ }
+
+
+
+ static Data_t *StaticData()
+ {
+ static Data_t staticData;
+ Assert( staticData.m_Size == 0 );
+ return &staticData;
+ }
+};
+
+#pragma warning(pop)
+
+
+//-----------------------------------------------------------------------------
+// The CCopyableUtlVector class:
+// A array class that allows copy construction (so you can nest a CUtlVector inside of another one of our containers)
+// WARNING - this class lets you copy construct which can be an expensive operation if you don't carefully control when it happens
+// Only use this when nesting a CUtlVector() inside of another one of our container classes (i.e a CUtlMap)
+//-----------------------------------------------------------------------------
+template< class T >
+class CCopyableUtlVector : public CUtlVector< T, CUtlMemory<T> >
+{
+ typedef CUtlVector< T, CUtlMemory<T> > BaseClass;
+public:
+ CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {}
+ CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {}
+ virtual ~CCopyableUtlVector() {}
+ CCopyableUtlVector( CCopyableUtlVector const& vec ) { CopyArray( vec.Base(), vec.Count() ); }
+};
+
+// TODO (Ilya): It seems like all the functions in CUtlVector are simple enough that they should be inlined.
+
+//-----------------------------------------------------------------------------
+// constructor, destructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline CUtlVector<T, A>::CUtlVector( int growSize, int initSize ) :
+ m_Memory(growSize, initSize), m_Size(0)
+{
+ ResetDbgInfo();
+}
+
+template< typename T, class A >
+inline CUtlVector<T, A>::CUtlVector( T* pMemory, int allocationCount, int numElements ) :
+ m_Memory(pMemory, allocationCount), m_Size(numElements)
+{
+ ResetDbgInfo();
+}
+
+template< typename T, class A >
+inline CUtlVector<T, A>::~CUtlVector()
+{
+ Purge();
+}
+
+template< typename T, class A >
+inline CUtlVector<T, A>& CUtlVector<T, A>::operator=( const CUtlVector<T, A> &other )
+{
+ int nCount = other.Count();
+ SetSize( nCount );
+ for ( int i = 0; i < nCount; i++ )
+ {
+ (*this)[ i ] = other[ i ];
+ }
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+// element access
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline T& CUtlVector<T, A>::operator[]( int i )
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::operator[]( int i ) const
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Element( int i )
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Element( int i ) const
+{
+ Assert( i < m_Size );
+ return m_Memory[ i ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Head()
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ 0 ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Head() const
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ 0 ];
+}
+
+template< typename T, class A >
+inline T& CUtlVector<T, A>::Tail()
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ m_Size - 1 ];
+}
+
+template< typename T, class A >
+inline const T& CUtlVector<T, A>::Tail() const
+{
+ Assert( m_Size > 0 );
+ return m_Memory[ m_Size - 1 ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Count
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::Count() const
+{
+ return m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Is element index valid?
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline bool CUtlVector<T, A>::IsValidIndex( int i ) const
+{
+ return (i >= 0) && (i < m_Size);
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns in invalid index
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::InvalidIndex()
+{
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Grows the vector
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::GrowVector( int num )
+{
+ if (m_Size + num > m_Memory.NumAllocated())
+ {
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() );
+ }
+
+ m_Size += num;
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Sorts the vector
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::Sort( int (__cdecl *pfnCompare)(const T *, const T *) )
+{
+ typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *);
+ if ( Count() <= 1 )
+ return;
+
+ if ( Base() )
+ {
+ qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare) );
+ }
+ else
+ {
+ Assert( 0 );
+ // this path is untested
+ // if you want to sort vectors that use a non-sequential memory allocator,
+ // you'll probably want to patch in a quicksort algorithm here
+ // I just threw in this bubble sort to have something just in case...
+
+ for ( int i = m_Size - 1; i >= 0; --i )
+ {
+ for ( int j = 1; j <= i; ++j )
+ {
+ if ( pfnCompare( &Element( j - 1 ), &Element( j ) ) < 0 )
+ {
+ V_swap( Element( j - 1 ), Element( j ) );
+ }
+ }
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------------------------------
+// Private function that does the in-place quicksort for non-contiguously allocated vectors.
+//----------------------------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::InPlaceQuickSort_r( int (__cdecl *pfnCompare)(const T *, const T *), int nLeft, int nRight )
+{
+ int nPivot;
+ int nLeftIdx = nLeft;
+ int nRightIdx = nRight;
+
+ if ( nRight - nLeft > 0 )
+ {
+ nPivot = ( nLeft + nRight ) / 2;
+
+ while ( ( nLeftIdx <= nPivot ) && ( nRightIdx >= nPivot ) )
+ {
+ while ( ( pfnCompare( &Element( nLeftIdx ), &Element( nPivot ) ) < 0 ) && ( nLeftIdx <= nPivot ) )
+ {
+ nLeftIdx++;
+ }
+
+ while ( ( pfnCompare( &Element( nRightIdx ), &Element( nPivot ) ) > 0 ) && ( nRightIdx >= nPivot ) )
+ {
+ nRightIdx--;
+ }
+
+ V_swap( Element( nLeftIdx ), Element( nRightIdx ) );
+
+ nLeftIdx++;
+ nRightIdx--;
+
+ if ( ( nLeftIdx - 1 ) == nPivot )
+ {
+ nPivot = nRightIdx = nRightIdx + 1;
+ }
+ else if ( nRightIdx + 1 == nPivot )
+ {
+ nPivot = nLeftIdx = nLeftIdx - 1;
+ }
+ }
+
+ InPlaceQuickSort_r( pfnCompare, nLeft, nPivot - 1 );
+ InPlaceQuickSort_r( pfnCompare, nPivot + 1, nRight );
+ }
+}
+
+
+//----------------------------------------------------------------------------------------------
+// Call this to quickly sort non-contiguously allocated vectors. Sort uses a slower bubble sort.
+//----------------------------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::InPlaceQuickSort( int (__cdecl *pfnCompare)(const T *, const T *) )
+{
+ InPlaceQuickSort_r( pfnCompare, 0, Count() - 1 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we have enough memory allocated to store a requested # of elements
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::EnsureCapacity( int num )
+{
+ MEM_ALLOC_CREDIT_CLASS();
+ m_Memory.EnsureCapacity(num);
+ ResetDbgInfo();
+}
+
+
+//-----------------------------------------------------------------------------
+// Makes sure we have at least this many elements
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::EnsureCount( int num )
+{
+ if (Count() < num)
+ {
+ AddMultipleToTail( num - Count() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Shifts elements
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::ShiftElementsRight( int elem, int num )
+{
+ Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
+ int numToMove = m_Size - elem - num;
+ if ((numToMove > 0) && (num > 0))
+ V_memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) );
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::ShiftElementsLeft( int elem, int num )
+{
+ Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
+ int numToMove = m_Size - elem - num;
+ if ((numToMove > 0) && (num > 0))
+ {
+ V_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
+
+#ifdef _DEBUG
+ V_memset( &Element(m_Size-num), 0xDD, num * sizeof(T) );
+#endif
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses default constructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToHead()
+{
+ return InsertBefore(0);
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToTail()
+{
+ return InsertBefore( m_Size );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertAfter( int elem )
+{
+ return InsertBefore( elem + 1 );
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::InsertBefore( int elem )
+{
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector();
+ ShiftElementsRight(elem);
+ Construct( &Element(elem) );
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds an element, uses copy constructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToHead( const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+ return InsertBefore( 0, src );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddToTail( const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+ return InsertBefore( m_Size, src );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertAfter( int elem, const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+ return InsertBefore( elem + 1, src );
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::InsertBefore( int elem, const T& src )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) );
+
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector();
+ ShiftElementsRight(elem);
+ CopyConstruct( &Element(elem), src );
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Adds multiple elements, uses default constructor
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddMultipleToHead( int num )
+{
+ return InsertMultipleBefore( 0, num );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddMultipleToTail( int num )
+{
+ return InsertMultipleBefore( m_Size, num );
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::AddMultipleToTail( int num, const T *pToCopy )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || !pToCopy || (pToCopy + num <= Base()) || (pToCopy >= (Base() + Count()) ) );
+
+ return InsertMultipleBefore( m_Size, num, pToCopy );
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::InsertMultipleAfter( int elem, int num )
+{
+ return InsertMultipleBefore( elem + 1, num );
+}
+
+
+template< typename T, class A >
+void CUtlVector<T, A>::SetCount( int count )
+{
+ RemoveAll();
+ AddMultipleToTail( count );
+}
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::SetSize( int size )
+{
+ SetCount( size );
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::SetCountNonDestructively( int count )
+{
+ int delta = count - m_Size;
+ if(delta > 0) AddMultipleToTail( delta );
+ else if(delta < 0) RemoveMultipleFromTail( -delta );
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::CopyArray( const T *pArray, int size )
+{
+ // Can't insert something that's in the list... reallocation may hose us
+ Assert( (Base() == NULL) || !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count()) ) );
+
+ SetSize( size );
+ for( int i=0; i < size; i++ )
+ {
+ (*this)[i] = pArray[i];
+ }
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::Swap( CUtlVector< T, A > &vec )
+{
+ m_Memory.Swap( vec.m_Memory );
+ V_swap( m_Size, vec.m_Size );
+#ifndef _X360
+ V_swap( m_pElements, vec.m_pElements );
+#endif
+}
+
+template< typename T, class A >
+int CUtlVector<T, A>::AddVectorToTail( CUtlVector const &src )
+{
+ Assert( &src != this );
+
+ int base = Count();
+
+ // Make space.
+ int nSrcCount = src.Count();
+ EnsureCapacity( base + nSrcCount );
+
+ // Copy the elements.
+ m_Size += nSrcCount;
+ for ( int i=0; i < nSrcCount; i++ )
+ {
+ CopyConstruct( &Element(base+i), src[i] );
+ }
+ return base;
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num )
+{
+ if( num == 0 )
+ return elem;
+
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector(num);
+ ShiftElementsRight( elem, num );
+
+ // Invoke default constructors
+ for (int i = 0; i < num; ++i )
+ {
+ Construct( &Element( elem+i ) );
+ }
+
+ return elem;
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::InsertMultipleBefore( int elem, int num, const T *pToInsert )
+{
+ if( num == 0 )
+ return elem;
+
+ // Can insert at the end
+ Assert( (elem == Count()) || IsValidIndex(elem) );
+
+ GrowVector(num);
+ ShiftElementsRight( elem, num );
+
+ // Invoke default constructors
+ if ( !pToInsert )
+ {
+ for (int i = 0; i < num; ++i )
+ {
+ Construct( &Element( elem+i ) );
+ }
+ }
+ else
+ {
+ for ( int i=0; i < num; i++ )
+ {
+ CopyConstruct( &Element( elem+i ), pToInsert[i] );
+ }
+ }
+
+ return elem;
+}
+
+
+//-----------------------------------------------------------------------------
+// Finds an element (element needs operator== defined)
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+int CUtlVector<T, A>::Find( const T& src ) const
+{
+ for ( int i = 0; i < Count(); ++i )
+ {
+ if (Element(i) == src)
+ return i;
+ }
+ return -1;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::FillWithValue( const T& src )
+{
+ for ( int i = 0; i < Count(); i++ )
+ {
+ Element(i) = src;
+ }
+}
+
+template< typename T, class A >
+bool CUtlVector<T, A>::HasElement( const T& src ) const
+{
+ return ( Find(src) >= 0 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Element removal
+//-----------------------------------------------------------------------------
+template< typename T, class A >
+void CUtlVector<T, A>::FastRemove( int elem )
+{
+ Assert( IsValidIndex(elem) );
+
+ Destruct( &Element(elem) );
+ if (m_Size > 0)
+ {
+ if ( elem != m_Size -1 )
+ memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) );
+ --m_Size;
+ }
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::Remove( int elem )
+{
+ Destruct( &Element(elem) );
+ ShiftElementsLeft(elem);
+ --m_Size;
+}
+
+template< typename T, class A >
+bool CUtlVector<T, A>::FindAndRemove( const T& src )
+{
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ Remove( elem );
+ return true;
+ }
+ return false;
+}
+
+template< typename T, class A >
+bool CUtlVector<T, A>::FindAndFastRemove( const T& src )
+{
+ int elem = Find( src );
+ if ( elem != -1 )
+ {
+ FastRemove( elem );
+ return true;
+ }
+ return false;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveMultiple( int elem, int num )
+{
+ Assert( elem >= 0 );
+ Assert( elem + num <= Count() );
+
+ for (int i = elem + num; --i >= elem; )
+ Destruct(&Element(i));
+
+ ShiftElementsLeft(elem, num);
+ m_Size -= num;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveMultipleFromHead( int num )
+{
+ Assert( num <= Count() );
+
+ for (int i = num; --i >= 0; )
+ Destruct(&Element(i));
+
+ ShiftElementsLeft(0, num);
+ m_Size -= num;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveMultipleFromTail( int num )
+{
+ Assert( num <= Count() );
+
+ for (int i = m_Size-num; i < m_Size; i++)
+ Destruct(&Element(i));
+
+ m_Size -= num;
+}
+
+template< typename T, class A >
+void CUtlVector<T, A>::RemoveAll()
+{
+ for (int i = m_Size; --i >= 0; )
+ {
+ Destruct(&Element(i));
+ }
+
+ m_Size = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Memory deallocation
+//-----------------------------------------------------------------------------
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::Purge()
+{
+ RemoveAll();
+ m_Memory.Purge();
+ ResetDbgInfo();
+}
+
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::PurgeAndDeleteElements()
+{
+ for( int i=0; i < m_Size; i++ )
+ {
+ delete Element(i);
+ }
+ Purge();
+}
+
+template< typename T, class A >
+inline void CUtlVector<T, A>::Compact()
+{
+ m_Memory.Purge(m_Size);
+}
+
+template< typename T, class A >
+inline int CUtlVector<T, A>::NumAllocated() const
+{
+ return m_Memory.NumAllocated();
+}
+
+
+//-----------------------------------------------------------------------------
+// Data and memory validation
+//-----------------------------------------------------------------------------
+#ifdef DBGFLAG_VALIDATE
+template< typename T, class A >
+void CUtlVector<T, A>::Validate( CValidator &validator, char *pchName )
+{
+ validator.Push( typeid(*this).name(), this, pchName );
+
+ m_Memory.Validate( validator, "m_Memory" );
+
+ validator.Pop();
+}
+#endif // DBGFLAG_VALIDATE
+
+// A vector class for storing pointers, so that the elements pointed to by the pointers are deleted
+// on exit.
+template<class T> class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> >
+{
+public:
+ ~CUtlVectorAutoPurge( void )
+ {
+ this->PurgeAndDeleteElements();
+ }
+
+};
+
+// easy string list class with dynamically allocated strings. For use with V_SplitString, etc.
+// Frees the dynamic strings in destructor.
+class CUtlStringList : public CUtlVectorAutoPurge< char *>
+{
+public:
+ void CopyAndAddToTail( char const *pString ) // clone the string and add to the end
+ {
+ char *pNewStr = new char[1 + strlen( pString )];
+ V_strcpy( pNewStr, pString );
+ AddToTail( pNewStr );
+ }
+
+ static int __cdecl SortFunc( char * const * sz1, char * const * sz2 )
+ {
+ return strcmp( *sz1, *sz2 );
+ }
+
+};
+
+
+
+// <Sergiy> placing it here a few days before Cert to minimize disruption to the rest of codebase
+class CSplitString: public CUtlVector<char*, CUtlMemory<char*, int> >
+{
+public:
+ CSplitString(const char *pString, const char *pSeparator);
+ CSplitString(const char *pString, const char **pSeparators, int nSeparators);
+ ~CSplitString();
+ //
+ // NOTE: If you want to make Construct() public and implement Purge() here, you'll have to free m_szBuffer there
+ //
+private:
+ void Construct(const char *pString, const char **pSeparators, int nSeparators);
+ void PurgeAndDeleteElements();
+private:
+ char *m_szBuffer; // a copy of original string, with '\0' instead of separators
+};
+
+
+#endif // CCVECTOR_H
diff --git a/external/vpc/public/tier2/tier2.h b/external/vpc/public/tier2/tier2.h
new file mode 100644
index 0000000..29f16bb
--- /dev/null
+++ b/external/vpc/public/tier2/tier2.h
@@ -0,0 +1,122 @@
+//===== Copyright � 2005-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: A higher level link library for general use in the game and tools.
+//
+//===========================================================================//
+
+
+#ifndef TIER2_H
+#define TIER2_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "tier1/tier1.h"
+
+
+//-----------------------------------------------------------------------------
+// Call this to connect to/disconnect from all tier 2 libraries.
+// It's up to the caller to check the globals it cares about to see if ones are missing
+//-----------------------------------------------------------------------------
+void ConnectTier2Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount );
+void DisconnectTier2Libraries();
+
+
+//-----------------------------------------------------------------------------
+// Call this to get the file system set up to stdio for utilities, etc:
+//-----------------------------------------------------------------------------
+void InitDefaultFileSystem(void);
+void ShutdownDefaultFileSystem(void);
+
+
+//-----------------------------------------------------------------------------
+// for simple utilities using valve libraries, call the entry point below in main(). It will
+// init a filesystem for you, init mathlib, and create the command line. Note that this function
+// may modify argc/argv because it filters out arguments (like -allowdebug).
+//-----------------------------------------------------------------------------
+void InitCommandLineProgram( int &argc, char ** &argv );
+
+
+//-----------------------------------------------------------------------------
+// Helper empty implementation of an IAppSystem for tier2 libraries
+//-----------------------------------------------------------------------------
+template< class IInterface, int ConVarFlag = 0 >
+class CTier2AppSystem : public CTier1AppSystem< IInterface, ConVarFlag >
+{
+ typedef CTier1AppSystem< IInterface, ConVarFlag > BaseClass;
+
+public:
+ virtual bool Connect( CreateInterfaceFn factory )
+ {
+ if ( !BaseClass::Connect( factory ) )
+ return false;
+
+ ConnectTier2Libraries( &factory, 1 );
+ return true;
+ }
+
+ virtual InitReturnVal_t Init()
+ {
+ InitReturnVal_t nRetVal = BaseClass::Init();
+ if ( nRetVal != INIT_OK )
+ return nRetVal;
+
+ return INIT_OK;
+ }
+
+ virtual AppSystemTier_t GetTier()
+ {
+ return APP_SYSTEM_TIER2;
+ }
+
+ virtual void Shutdown()
+ {
+ BaseClass::Shutdown();
+ }
+
+ virtual void Disconnect()
+ {
+ DisconnectTier2Libraries();
+ BaseClass::Disconnect();
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Distance fade information
+//-----------------------------------------------------------------------------
+enum FadeMode_t
+{
+ // These map directly to cpu_level, and g_aFadeData contains settings for each given cpu_level.
+ // The exception is 'FADE_MODE_LEVEL', which refers to level-specific values in the map entity.
+ FADE_MODE_NONE = 0,
+ FADE_MODE_LOW,
+ FADE_MODE_MED,
+ FADE_MODE_HIGH,
+ FADE_MODE_360,
+ FADE_MODE_LEVEL,
+
+ FADE_MODE_COUNT,
+};
+
+struct FadeData_t
+{
+ float m_flPixelMin; // Size (height in pixels) above which objects start to fade in
+ float m_flPixelMax; // Size (height in pixels) above which objects are fully faded in
+ float m_flWidth; // Reference screen res w.r.t which the above pixel values were chosen
+ float m_flFadeDistScale; // Scale factor applied before entity distance-based fade is calculated
+};
+
+// see tier2.cpp for data!
+extern FadeData_t g_aFadeData[FADE_MODE_COUNT];
+
+
+//-----------------------------------------------------------------------------
+// Used by the resource system for fast resource frame counter
+//-----------------------------------------------------------------------------
+extern uint32 g_nResourceFrameCount;
+
+
+#endif // TIER2_H
+
diff --git a/external/vpc/public/unitlib/unitlib.h b/external/vpc/public/unitlib/unitlib.h
new file mode 100644
index 0000000..66b1aec
--- /dev/null
+++ b/external/vpc/public/unitlib/unitlib.h
@@ -0,0 +1,271 @@
+//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef UNITLIB_H
+#define UNITLIB_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+
+//-----------------------------------------------------------------------------
+// Usage model for the UnitTest library
+//
+// The general methodology here is that clients are expected to create unit
+// test DLLs that statically link to the unit test DLL and which implement
+// tests of various libraries. The unit test application will dynamically
+// load all DLLs in a directory, which causes them to install their test cases
+// into the unit test system. The application then runs through all tests and
+// executes them all, displaying the results.
+//
+// *** NOTE: The test suites are compiled in both debug and release builds,
+// even though it's expected to only be useful in debug builds. This is because
+// I couldn't come up with a good way of disabling the code in release builds.
+// (The only options I could come up with would still compile in the functions,
+// just not install them into the unit test library, or would make it so that
+// you couldn't step through the unit test code).
+//
+// Even though this is the case, there's no reason not to add test cases
+// directly into your shipping DLLs, as long as you surround the code with
+// #ifdef _DEBUG. To error check a project to make sure it's not compiling
+// in unit tests in Release build, just don't link in unitlib.lib in Release.
+// You can of course also put your test suites into separate DLLs.
+//
+// All tests inherit from the ITestCase interface. There are two major kinds
+// of tests; the first is a single test case meant to run a piece of
+// code and check its results match expected values using the Assert macros.
+// The second kind is a test suite which is simply a list of other tests.
+//
+// The following classes and macros are used to easily create unit test cases
+// and suites:
+//
+// Use DEFINE_TESTSUITE to define a particular test suite, and DEFINE_TESTCASE
+// to add as many test cases as you like to that test suite, as follows:
+//
+// DEFINE_TESTSUITE( VectorTestSuite )
+//
+// DEFINE_TESTCASE( VectorAdditionTest, VectorTestSuite )
+// {
+// .. test code here ..
+// }
+//
+// Note that the definition of the test suite can occur in a different file
+// as the test case. A link error will occur if the test suite to which a
+// test case is added has not been defined.
+//
+// To create a test case that is not part of a suite, use...
+//
+// DEFINE_TESTCASE_NOSUITE( VectorAdditionTest )
+// {
+// .. test code here ..
+// }
+//
+// You can also create a suite which is a child of another suite using
+//
+// DEFINE_SUBSUITE( VectorTestSuite, MathTestSuite )
+//
+//-----------------------------------------------------------------------------
+
+
+
+//-----------------------------------------------------------------------------
+// dll export stuff
+//-----------------------------------------------------------------------------
+#ifdef TIER0_DLL_EXPORT
+#define UNITLIB_DLL_EXPORT
+#endif
+
+
+#ifdef UNITLIB_DLL_EXPORT
+#define UNITLIB_INTERFACE DLL_EXPORT
+#define UNITLIB_CLASS_INTERFACE DLL_CLASS_EXPORT
+#define UNITLIB_GLOBAL_INTERFACE DLL_GLOBAL_EXPORT
+#else
+#define UNITLIB_INTERFACE DLL_IMPORT
+#define UNITLIB_CLASS_INTERFACE DLL_CLASS_IMPORT
+#define UNITLIB_GLOBAL_INTERFACE DLL_GLOBAL_IMPORT
+#endif
+
+
+//-----------------------------------------------------------------------------
+// All unit test libraries can be asked for a unit test
+// AppSystem to perform connection
+//-----------------------------------------------------------------------------
+#define UNITTEST_INTERFACE_VERSION "UnitTestV001"
+
+
+//-----------------------------------------------------------------------------
+//
+// NOTE: All classes and interfaces below you shouldn't use directly.
+// Use the DEFINE_TESTSUITE and DEFINE_TESTCASE macros instead.
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Test case + suite interface
+//-----------------------------------------------------------------------------
+class ITestCase
+{
+public:
+ // This returns the test name
+ virtual char const* GetName() = 0;
+
+ // This runs the test
+ virtual void RunTest() = 0;
+};
+
+class ITestSuite : public ITestCase
+{
+public:
+ // Add a test to the suite...
+ virtual void AddTest( ITestCase* pTest ) = 0;
+};
+
+
+
+//-----------------------------------------------------------------------------
+// This is the main function exported by the unit test library used by
+// unit test DLLs to install their test cases into a list to be run
+//-----------------------------------------------------------------------------
+UNITLIB_INTERFACE void UnitTestInstallTestCase( ITestCase* pTest );
+
+
+//-----------------------------------------------------------------------------
+// These are the methods used by the unit test running program to run all tests
+//-----------------------------------------------------------------------------
+UNITLIB_INTERFACE int UnitTestCount();
+UNITLIB_INTERFACE ITestCase* GetUnitTest( int i );
+
+
+//-----------------------------------------------------------------------------
+// Helper for unit test DLLs to expose IAppSystems
+//-----------------------------------------------------------------------------
+#define USE_UNITTEST_APPSYSTEM( _className ) \
+ static _className s_UnitTest ## _className; \
+ EXPOSE_SINGLE_INTERFACE_GLOBALVAR( _className, IAppSystem, UNITTEST_INTERFACE_VERSION, s_UnitTest ## _className );
+
+
+//-----------------------------------------------------------------------------
+// Base class for test cases
+//-----------------------------------------------------------------------------
+class UNITLIB_CLASS_INTERFACE CTestCase : public ITestCase
+{
+public:
+ CTestCase( char const* pName, ITestSuite* pParent = 0 );
+ ~CTestCase();
+
+ // Returns the test name
+ char const* GetName();
+
+private:
+ char* m_pName;
+};
+
+
+//-----------------------------------------------------------------------------
+// Test suite class
+//-----------------------------------------------------------------------------
+class UNITLIB_CLASS_INTERFACE CTestSuite : public ITestSuite
+{
+public:
+ CTestSuite( char const* pName, ITestSuite* pParent = 0 );
+ ~CTestSuite();
+
+ // This runs the test
+ void RunTest();
+
+ // Add a test to the suite...
+ void AddTest( ITestCase* pTest );
+
+ // Returns the test name
+ char const* GetName();
+
+protected:
+ int m_TestCount;
+ ITestCase** m_ppTestCases;
+ char* m_pName;
+};
+
+#define TESTSUITE_CLASS( _suite ) \
+ class CTS ## _suite : public CTestSuite \
+ { \
+ public: \
+ CTS ## _suite(); \
+ };
+
+#define TESTSUITE_ACCESSOR( _suite ) \
+ CTS ## _suite* GetTS ## _suite() \
+ { \
+ static CTS ## _suite s_TS ## _suite; \
+ return &s_TS ## _suite; \
+ }
+
+#define FWD_DECLARE_TESTSUITE( _suite ) \
+ class CTS ## _suite; \
+ CTS ## _suite* GetTS ## _suite();
+
+#define DEFINE_TESTSUITE( _suite ) \
+ TESTSUITE_CLASS( _suite ) \
+ TESTSUITE_ACCESSOR( _suite ) \
+ CTS ## _suite::CTS ## _suite() : CTestSuite( #_suite ) {}
+
+#define DEFINE_SUBSUITE( _suite, _parent ) \
+ TESTSUITE_CLASS( _suite ) \
+ TESTSUITE_ACCESSOR( _suite ) \
+ FWD_DECLARE_TESTSUITE( _parent ) \
+ CTS ## _suite::CTS ## _suite() : CTestSuite( #_suite, GetTS ## _parent() ) {}
+
+#define TESTCASE_CLASS( _case ) \
+ class CTC ## _case : public CTestCase \
+ { \
+ public: \
+ CTC ## _case (); \
+ void RunTest(); \
+ };
+
+#define DEFINE_TESTCASE_NOSUITE( _case ) \
+ TESTCASE_CLASS( _case ) \
+ CTC ## _case::CTC ## _case () : CTestCase( #_case ) {} \
+ \
+ CTC ## _case s_TC ## _case; \
+ \
+ void CTC ## _case ::RunTest()
+
+#define DEFINE_TESTCASE( _case, _suite ) \
+ TESTCASE_CLASS( _case ) \
+ FWD_DECLARE_TESTSUITE( _suite ) \
+ CTC ## _case::CTC ## _case () : CTestCase( #_case, GetTS ## _suite() ) {} \
+ \
+ CTC ## _case s_TC ## _case; \
+ \
+ void CTC ## _case ::RunTest()
+
+
+#define _Shipping_AssertMsg( _exp, _msg, _executeExp, _bFatal ) \
+ do { \
+ if (!(_exp)) \
+ { \
+ LoggingResponse_t ret = Log_Assert( "%s (%d) : %s\n", __TFILE__, __LINE__, _msg ); \
+ _executeExp; \
+ if ( ret == LR_DEBUGGER ) \
+ { \
+ if ( !ShouldUseNewAssertDialog() || DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \
+ DebuggerBreak(); \
+ if ( _bFatal ) \
+ _ExitOnFatalAssert( __TFILE__, __LINE__ ); \
+ } \
+ } \
+ } while (0)
+
+#define Shipping_Assert( _exp ) _Shipping_AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
+
+
+#endif // UNITLIB_H
diff --git a/external/vpc/public/vstdlib/cvar.h b/external/vpc/public/vstdlib/cvar.h
new file mode 100644
index 0000000..1f26e0d
--- /dev/null
+++ b/external/vpc/public/vstdlib/cvar.h
@@ -0,0 +1,25 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#if !defined( CVAR_H )
+#define CVAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vstdlib/vstdlib.h"
+#include "icvar.h"
+
+
+//-----------------------------------------------------------------------------
+// Returns a CVar dictionary for tool usage
+//-----------------------------------------------------------------------------
+VSTDLIB_INTERFACE CreateInterfaceFn VStdLib_GetICVarFactory();
+
+
+#endif // CVAR_H
diff --git a/external/vpc/public/vstdlib/ikeyvaluessystem.h b/external/vpc/public/vstdlib/ikeyvaluessystem.h
new file mode 100644
index 0000000..3477ed3
--- /dev/null
+++ b/external/vpc/public/vstdlib/ikeyvaluessystem.h
@@ -0,0 +1,56 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifndef VSTDLIB_IKEYVALUESSYSTEM_H
+#define VSTDLIB_IKEYVALUESSYSTEM_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vstdlib/vstdlib.h"
+
+// handle to a KeyValues key name symbol
+typedef int HKeySymbol;
+#define INVALID_KEY_SYMBOL (-1)
+
+//-----------------------------------------------------------------------------
+// Purpose: Interface to shared data repository for KeyValues (included in vgui_controls.lib)
+// allows for central data storage point of KeyValues symbol table
+//-----------------------------------------------------------------------------
+class IKeyValuesSystem
+{
+public:
+ // registers the size of the KeyValues in the specified instance
+ // so it can build a properly sized memory pool for the KeyValues objects
+ // the sizes will usually never differ but this is for versioning safety
+ virtual void RegisterSizeofKeyValues(int size) = 0;
+
+ // allocates/frees a KeyValues object from the shared mempool
+ virtual void *AllocKeyValuesMemory(int size) = 0;
+ virtual void FreeKeyValuesMemory(void *pMem) = 0;
+
+ // symbol table access (used for key names)
+ virtual HKeySymbol GetSymbolForString( const char *name, bool bCreate = true ) = 0;
+ virtual const char *GetStringForSymbol(HKeySymbol symbol) = 0;
+
+ // for debugging, adds KeyValues record into global list so we can track memory leaks
+ virtual void AddKeyValuesToMemoryLeakList(void *pMem, HKeySymbol name) = 0;
+ virtual void RemoveKeyValuesFromMemoryLeakList(void *pMem) = 0;
+
+ // set/get a value for keyvalues resolution symbol
+ // e.g.: SetKeyValuesExpressionSymbol( "LOWVIOLENCE", true ) - enables [$LOWVIOLENCE]
+ virtual void SetKeyValuesExpressionSymbol( const char *name, bool bValue ) = 0;
+ virtual bool GetKeyValuesExpressionSymbol( const char *name ) = 0;
+
+ // symbol table access from code with case-preserving requirements (used for key names)
+ virtual HKeySymbol GetSymbolForStringCaseSensitive( HKeySymbol &hCaseInsensitiveSymbol, const char *name, bool bCreate = true ) = 0;
+};
+
+VSTDLIB_INTERFACE IKeyValuesSystem *KeyValuesSystem();
+
+// #define KEYVALUESSYSTEM_INTERFACE_VERSION "KeyValuesSystem002"
+
+#endif // VSTDLIB_IKEYVALUESSYSTEM_H
diff --git a/external/vpc/public/vstdlib/pch_vstdlib.h b/external/vpc/public/vstdlib/pch_vstdlib.h
new file mode 100644
index 0000000..03754dd
--- /dev/null
+++ b/external/vpc/public/vstdlib/pch_vstdlib.h
@@ -0,0 +1,51 @@
+//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ========
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose:
+//
+// $Workfile: $
+// $NoKeywords: $
+//=============================================================================
+
+
+#pragma warning(disable: 4514)
+
+// First include standard libraries
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <malloc.h>
+#include <memory.h>
+#include <ctype.h>
+
+// Next, include public
+#include "tier0/basetypes.h"
+#include "tier0/dbg.h"
+#include "tier0/valobject.h"
+
+// Next, include vstdlib
+#include "vstdlib/vstdlib.h"
+#include "tier1/strtools.h"
+#include "vstdlib/random.h"
+#include "tier1/keyvalues.h"
+#include "tier1/utlmemory.h"
+#include "tier1/utlrbtree.h"
+#include "tier1/utlvector.h"
+#include "tier1/utllinkedlist.h"
+#include "tier1/utlmultilist.h"
+#include "tier1/utlsymbol.h"
+#include "tier0/icommandline.h"
+#include "tier1/netadr.h"
+#include "tier1/mempool.h"
+#include "tier1/utlbuffer.h"
+#include "tier1/utlstring.h"
+#include "tier1/utlmap.h"
+
+#include "tier0/memdbgon.h"
+
+
+
diff --git a/external/vpc/public/vstdlib/random.h b/external/vpc/public/vstdlib/random.h
new file mode 100644
index 0000000..3f05a1d
--- /dev/null
+++ b/external/vpc/public/vstdlib/random.h
@@ -0,0 +1,111 @@
+//===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose: Random number generator
+//
+// $Workfile: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef VSTDLIB_RANDOM_H
+#define VSTDLIB_RANDOM_H
+
+#include "vstdlib/vstdlib.h"
+#include "tier0/basetypes.h"
+#include "tier0/threadtools.h"
+#include "tier1/interface.h"
+
+#define NTAB 32
+
+#pragma warning(push)
+#pragma warning( disable:4251 )
+
+//-----------------------------------------------------------------------------
+// A generator of uniformly distributed random numbers
+//-----------------------------------------------------------------------------
+class IUniformRandomStream
+{
+public:
+ // Sets the seed of the random number generator
+ virtual void SetSeed( int iSeed ) = 0;
+
+ // Generates random numbers
+ virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ) = 0;
+ virtual int RandomInt( int iMinVal, int iMaxVal ) = 0;
+ virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// The standard generator of uniformly distributed random numbers
+//-----------------------------------------------------------------------------
+class VSTDLIB_CLASS CUniformRandomStream : public IUniformRandomStream
+{
+public:
+ CUniformRandomStream();
+
+ // Sets the seed of the random number generator
+ virtual void SetSeed( int iSeed );
+
+ // Generates random numbers
+ virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f );
+ virtual int RandomInt( int iMinVal, int iMaxVal );
+ virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f );
+
+private:
+ int GenerateRandomNumber();
+
+ int m_idum;
+ int m_iy;
+ int m_iv[NTAB];
+
+ CThreadFastMutex m_mutex;
+};
+
+
+//-----------------------------------------------------------------------------
+// A generator of gaussian distributed random numbers
+//-----------------------------------------------------------------------------
+class VSTDLIB_CLASS CGaussianRandomStream
+{
+public:
+ // Passing in NULL will cause the gaussian stream to use the
+ // installed global random number generator
+ CGaussianRandomStream( IUniformRandomStream *pUniformStream = NULL );
+
+ // Attaches to a random uniform stream
+ void AttachToStream( IUniformRandomStream *pUniformStream = NULL );
+
+ // Generates random numbers
+ float RandomFloat( float flMean = 0.0f, float flStdDev = 1.0f );
+
+private:
+ IUniformRandomStream *m_pUniformStream;
+ bool m_bHaveValue;
+ float m_flRandomValue;
+
+ CThreadFastMutex m_mutex;
+};
+
+
+//-----------------------------------------------------------------------------
+// A couple of convenience functions to access the library's global uniform stream
+//-----------------------------------------------------------------------------
+VSTDLIB_INTERFACE void RandomSeed( int iSeed );
+VSTDLIB_INTERFACE float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f );
+VSTDLIB_INTERFACE float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f );
+VSTDLIB_INTERFACE int RandomInt( int iMinVal, int iMaxVal );
+VSTDLIB_INTERFACE float RandomGaussianFloat( float flMean = 0.0f, float flStdDev = 1.0f );
+
+
+//-----------------------------------------------------------------------------
+// Installs a global random number generator, which will affect the Random functions above
+//-----------------------------------------------------------------------------
+VSTDLIB_INTERFACE void InstallUniformRandomStream( IUniformRandomStream *pStream );
+
+
+#pragma warning(pop)
+
+#endif // VSTDLIB_RANDOM_H
+
+
+
diff --git a/external/vpc/public/vstdlib/vstdlib.h b/external/vpc/public/vstdlib/vstdlib.h
new file mode 100644
index 0000000..ffdb31a
--- /dev/null
+++ b/external/vpc/public/vstdlib/vstdlib.h
@@ -0,0 +1,40 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef VSTDLIB_H
+#define VSTDLIB_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+//-----------------------------------------------------------------------------
+// dll export stuff
+//-----------------------------------------------------------------------------
+#ifdef STATIC_VSTDLIB
+#define VSTDLIB_INTERFACE
+#define VSTDLIB_OVERLOAD
+#define VSTDLIB_CLASS
+#define VSTDLIB_GLOBAL
+#else
+#ifdef VSTDLIB_DLL_EXPORT
+#define VSTDLIB_INTERFACE DLL_EXPORT
+#define VSTDLIB_OVERLOAD DLL_GLOBAL_EXPORT
+#define VSTDLIB_CLASS DLL_CLASS_EXPORT
+#define VSTDLIB_GLOBAL DLL_GLOBAL_EXPORT
+#else
+#define VSTDLIB_INTERFACE DLL_IMPORT
+#define VSTDLIB_OVERLOAD DLL_GLOBAL_IMPORT
+#define VSTDLIB_CLASS DLL_CLASS_IMPORT
+#define VSTDLIB_GLOBAL DLL_GLOBAL_IMPORT
+#endif
+#endif
+
+#endif // VSTDLIB_H
diff --git a/external/vpc/public/vstdlib/vstrtools.h b/external/vpc/public/vstdlib/vstrtools.h
new file mode 100644
index 0000000..04b351c
--- /dev/null
+++ b/external/vpc/public/vstdlib/vstrtools.h
@@ -0,0 +1,275 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Functions for UCS/UTF/Unicode string operations. These functions are in vstdlib
+// instead of tier1, because on PS/3 they need to load and initialize a system module,
+// which is more frugal to do from a single place rather than multiple times in different PRX'es.
+// The functions themselves aren't supposed to be called frequently enough for the DLL/PRX boundary
+// marshalling, if any, to have any measureable impact on performance.
+//
+#ifndef VSTRTOOLS_HDR
+#define VSTRTOOLS_HDR
+
+#include "tier0/platform.h"
+#include "tier0/basetypes.h"
+#include "tier1/strtools.h"
+
+#ifdef STATIC_VSTDLIB
+#define VSTRTOOLS_INTERFACE
+#else
+#ifdef VSTDLIB_DLL_EXPORT
+#define VSTRTOOLS_INTERFACE DLL_EXPORT
+#else
+#define VSTRTOOLS_INTERFACE DLL_IMPORT
+#endif
+#endif
+
+// conversion functions wchar_t <-> char, returning the number of characters converted
+VSTRTOOLS_INTERFACE int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes );
+VSTRTOOLS_INTERFACE int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes );
+VSTRTOOLS_INTERFACE int V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInBytes );
+VSTRTOOLS_INTERFACE int V_UCS2ToUTF8( const ucs2 *pUCS2, char *pUTF8, int cubDestSizeInBytes );
+VSTRTOOLS_INTERFACE int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, char *pUCS2, int cubDestSizeInBytes );
+VSTRTOOLS_INTERFACE int V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, ucs2 *pUCS2, int cubDestSizeInBytes );
+
+// copy at most n bytes into destination, will not corrupt utf-8 multi-byte sequences
+VSTRTOOLS_INTERFACE void * V_UTF8_strncpy( char *pDest, const char *pSrc, size_t nMaxBytes );
+
+
+//
+// This utility class is for performing UTF-8 <-> UTF-16 conversion.
+// It is intended for use with function/method parameters.
+//
+// For example, you can call
+// FunctionTakingUTF16( CStrAutoEncode( utf8_string ).ToWString() )
+// or
+// FunctionTakingUTF8( CStrAutoEncode( utf16_string ).ToString() )
+//
+// The converted string is allocated off the heap, and destroyed when
+// the object goes out of scope.
+//
+// if the string cannot be converted, NULL is returned.
+//
+// This class doesn't have any conversion operators; the intention is
+// to encourage the developer to get used to having to think about which
+// encoding is desired.
+//
+class CStrAutoEncode
+{
+public:
+
+ // ctor
+ explicit CStrAutoEncode( const char *pch )
+ {
+ m_pch = pch;
+ m_pwch = NULL;
+#if !defined( WIN32 ) && !defined(_WIN32)
+ m_pucs2 = NULL;
+ m_bCreatedUCS2 = false;
+#endif
+ m_bCreatedUTF16 = false;
+ }
+
+ // ctor
+ explicit CStrAutoEncode( const wchar_t *pwch )
+ {
+ m_pch = NULL;
+ m_pwch = pwch;
+#if !defined( WIN32 ) && !defined(_WIN32)
+ m_pucs2 = NULL;
+ m_bCreatedUCS2 = false;
+#endif
+ m_bCreatedUTF16 = true;
+ }
+
+#if !defined(WIN32) && !defined(_WINDOWS) && !defined(_WIN32) && !defined(_PS3)
+ explicit CStrAutoEncode( const ucs2 *pwch )
+ {
+ m_pch = NULL;
+ m_pwch = NULL;
+ m_pucs2 = pwch;
+ m_bCreatedUCS2 = true;
+ m_bCreatedUTF16 = false;
+ }
+#endif
+
+ // returns the UTF-8 string, converting on the fly.
+ const char* ToString()
+ {
+ PopulateUTF8();
+ return m_pch;
+ }
+
+ // returns the UTF-8 string - a writable pointer.
+ // only use this if you don't want to call const_cast
+ // yourself. We need this for cases like CreateProcess.
+ char* ToStringWritable()
+ {
+ PopulateUTF8();
+ return const_cast< char* >( m_pch );
+ }
+
+ // returns the UTF-16 string, converting on the fly.
+ const wchar_t* ToWString()
+ {
+ PopulateUTF16();
+ return m_pwch;
+ }
+
+#if !defined( WIN32 ) && !defined(_WIN32)
+ // returns the UTF-16 string, converting on the fly.
+ const ucs2* ToUCS2String()
+ {
+ PopulateUCS2();
+ return m_pucs2;
+ }
+#endif
+
+ // returns the UTF-16 string - a writable pointer.
+ // only use this if you don't want to call const_cast
+ // yourself. We need this for cases like CreateProcess.
+ wchar_t* ToWStringWritable()
+ {
+ PopulateUTF16();
+ return const_cast< wchar_t* >( m_pwch );
+ }
+
+ // dtor
+ ~CStrAutoEncode()
+ {
+ // if we're "native unicode" then the UTF-8 string is something we allocated,
+ // and vice versa.
+ if ( m_bCreatedUTF16 )
+ {
+ delete [] m_pch;
+ }
+ else
+ {
+ delete [] m_pwch;
+ }
+#if !defined( WIN32 ) && !defined(_WIN32)
+ if ( !m_bCreatedUCS2 && m_pucs2 )
+ delete [] m_pucs2;
+#endif
+ }
+
+private:
+ // ensure we have done any conversion work required to farm out a
+ // UTF-8 encoded string.
+ //
+ // We perform two heap allocs here; the first one is the worst-case
+ // (four bytes per Unicode code point). This is usually quite pessimistic,
+ // so we perform a second allocation that's just the size we need.
+ void PopulateUTF8()
+ {
+ if ( !m_bCreatedUTF16 )
+ return; // no work to do
+ if ( m_pwch == NULL )
+ return; // don't have a UTF-16 string to convert
+ if ( m_pch != NULL )
+ return; // already been converted to UTF-8; no work to do
+
+ // each Unicode code point can expand to as many as four bytes in UTF-8; we
+ // also need to leave room for the terminating NUL.
+ uint32 cbMax = 4 * static_cast<uint32>( V_wcslen( m_pwch ) ) + 1;
+ char *pchTemp = new char[ cbMax ];
+ if ( V_UnicodeToUTF8( m_pwch, pchTemp, cbMax ) )
+ {
+ uint32 cchAlloc = static_cast<uint32>( V_strlen( pchTemp ) ) + 1;
+ char *pchHeap = new char[ cchAlloc ];
+ V_strncpy( pchHeap, pchTemp, cchAlloc );
+ delete [] pchTemp;
+ m_pch = pchHeap;
+ }
+ else
+ {
+ // do nothing, and leave the UTF-8 string NULL
+ delete [] pchTemp;
+ }
+ }
+
+ // ensure we have done any conversion work required to farm out a
+ // UTF-16 encoded string.
+ //
+ // We perform two heap allocs here; the first one is the worst-case
+ // (one code point per UTF-8 byte). This is sometimes pessimistic,
+ // so we perform a second allocation that's just the size we need.
+ void PopulateUTF16()
+ {
+ if ( m_bCreatedUTF16 )
+ return; // no work to do
+ if ( m_pch == NULL )
+ return; // no UTF-8 string to convert
+ if ( m_pwch != NULL )
+ return; // already been converted to UTF-16; no work to do
+
+ uint32 cchMax = static_cast<uint32>( V_strlen( m_pch ) ) + 1;
+ wchar_t *pwchTemp = new wchar_t[ cchMax ];
+ if ( V_UTF8ToUnicode( m_pch, pwchTemp, cchMax * sizeof( wchar_t ) ) )
+ {
+ uint32 cchAlloc = static_cast<uint32>( V_wcslen( pwchTemp ) ) + 1;
+ wchar_t *pwchHeap = new wchar_t[ cchAlloc ];
+ V_wcsncpy( pwchHeap, pwchTemp, cchAlloc * sizeof( wchar_t ) );
+ delete [] pwchTemp;
+ m_pwch = pwchHeap;
+ }
+ else
+ {
+ // do nothing, and leave the UTF-16 string NULL
+ delete [] pwchTemp;
+ }
+ }
+
+#if !defined( WIN32 ) && !defined(_WIN32)
+ // ensure we have done any conversion work required to farm out a
+ // UTF-16 encoded string.
+ //
+ // We perform two heap allocs here; the first one is the worst-case
+ // (one code point per UTF-8 byte). This is sometimes pessimistic,
+ // so we perform a second allocation that's just the size we need.
+ void PopulateUCS2()
+ {
+ if ( m_bCreatedUCS2 )
+ return;
+ if ( m_pch == NULL )
+ return; // no UTF-8 string to convert
+ if ( m_pucs2 != NULL )
+ return; // already been converted to UTF-16; no work to do
+
+ uint32 cchMax = static_cast<uint32>( V_strlen( m_pch ) ) + 1;
+ ucs2 *pwchTemp = new ucs2[ cchMax ];
+ if ( V_UTF8ToUCS2( m_pch, cchMax, pwchTemp, cchMax * sizeof( ucs2 ) ) )
+ {
+ uint32 cchAlloc = cchMax;
+ ucs2 *pwchHeap = new ucs2[ cchAlloc ];
+ memcpy( pwchHeap, pwchTemp, cchAlloc * sizeof( ucs2 ) );
+ delete [] pwchTemp;
+ m_pucs2 = pwchHeap;
+ }
+ else
+ {
+ // do nothing, and leave the UTF-16 string NULL
+ delete [] pwchTemp;
+ }
+ }
+#endif
+
+ // one of these pointers is an owned pointer; whichever
+ // one is the encoding OTHER than the one we were initialized
+ // with is the pointer we've allocated and must free.
+ const char *m_pch;
+ const wchar_t *m_pwch;
+#if !defined( WIN32 ) && !defined(_WIN32)
+ const ucs2 *m_pucs2;
+ bool m_bCreatedUCS2;
+#endif
+ // "created as UTF-16", means our owned string is the UTF-8 string not the UTF-16 one.
+ bool m_bCreatedUTF16;
+
+};
+
+
+#define V_UTF8ToUnicode V_UTF8ToUnicode
+#define V_UnicodeToUTF8 V_UnicodeToUTF8
+
+
+#endif \ No newline at end of file
diff --git a/external/vpc/public/winlite.h b/external/vpc/public/winlite.h
new file mode 100644
index 0000000..dc2a0bd
--- /dev/null
+++ b/external/vpc/public/winlite.h
@@ -0,0 +1,31 @@
+//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef WINLITE_H
+#define WINLITE_H
+#pragma once
+
+#ifdef _WIN32
+//
+// Prevent tons of unused windows definitions
+//
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOSERVICE
+#define NOMCX
+#define NOIME
+#if !defined( _X360 )
+#pragma warning(push, 1)
+#pragma warning(disable: 4005)
+#include <windows.h>
+#pragma warning(pop)
+#endif
+#undef PostMessage
+
+#endif // WIN32
+#endif // WINLITE_H