diff --git a/MaxNifTools.ini b/MaxNifTools.ini
index 7c11d9c63b1957db1878be0c338ec29cc18b32a7..0b8959445e6dd52a09bc1a39526ac47aa7ab413c 100644
--- a/MaxNifTools.ini
+++ b/MaxNifTools.ini
@@ -15,6 +15,9 @@ Reparse=0
 Website=http://www.niftools.org
 ; Wiki - Documentation website
 Wiki=http://www.niftools.org/wiki/index.php/3ds_Max
+; Force Plugcfg directory (Default=1) dont use the "recommended directory by max"
+ForcePlugcfg=1
+
 
 [MaxNifExport]
 ; Enable/Disable Exporter Class in max. Default: 1
diff --git a/NifCommon/AnimKey.cpp b/NifCommon/AnimKey.cpp
index 30fdbb0cf629e0cb32b08cebd679390b3e4ecf95..04342e95ed2618b11acf04d81f199eeec2c40e4c 100644
--- a/NifCommon/AnimKey.cpp
+++ b/NifCommon/AnimKey.cpp
@@ -50,8 +50,10 @@ T& InitBezKey(T& rKey, U& key, float time)
 {
    rKey.time = TimeToFrame(time + key.time);
    rKey.flags = 0;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
    SetInTanType(rKey.flags,BEZKEY_FLAT);
    SetOutTanType(rKey.flags,BEZKEY_FLAT);
+#endif
    return rKey;
 }
 
diff --git a/NifCommon/AppSettings.cpp b/NifCommon/AppSettings.cpp
index d4697021169436ed1ebfeb1c287f2678d7068a40..2e632817d20ba69952e87c9734bff113cf411fbd 100644
--- a/NifCommon/AppSettings.cpp
+++ b/NifCommon/AppSettings.cpp
@@ -9,8 +9,7 @@ AppSettingsMap TheAppSettings;
 void AppSettings::Initialize(Interface *gi) 
 {
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
    if (-1 != _taccess(iniName, 0)) {
       bool reparse = GetIniValue<bool>("System", "Reparse", false, iniName);
       if (reparse || TheAppSettings.empty()){
@@ -72,8 +71,7 @@ void AppSettings::ReadSettings(string iniFile)
 void AppSettings::WriteSettings(Interface *gi)
 {
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
    if (-1 != _taccess(iniName, 0)) 
    {
       SetIniValue(Name.c_str(), "NiVersion", NiVersion.c_str(), iniName);
diff --git a/NifCommon/IniSection.h b/NifCommon/IniSection.h
index e42f6a8ded61cb5cb33612f45f897cde6298b362..624bd020deebb43b750829701ef2ea817c62f5d8 100644
--- a/NifCommon/IniSection.h
+++ b/NifCommon/IniSection.h
@@ -2,22 +2,28 @@
 
 #include <string>
 #include <list>
-enum INIDEFTYPE
+
+enum VARIABLETYPE
 {
-   IDT_STRING,
-   IDT_INT,
-   IDT_FLOAT,
-   IDT_BOOL,
-   IDT_FILENAME,
-   IDT_UNKNOWN,
+   vtUnknown,
+   vtInteger,
+   vtFloat,
+   vtDouble,
+   vtBoolean,
+   vtText,
+   vtPointer,
+   vtHandle,
+   vtVector = 0x1000,
+   vtFixedVector = vtVector | 0x2000,
+   vtMatrix = 0x4000,
 };
 
-struct INIDEF
+struct VARIABLE
 {
-   INIDEF() : ShortName(NULL), IniName(NULL), MemberAddr(0), Description(NULL), DefaultValue(NULL), ValueSize(0) {
+   VARIABLE() : ShortName(NULL), IniName(NULL), MemberAddr(0), Description(NULL), DefaultValue(NULL), ValueSize(0) {
    }
 
-   ~INIDEF() {
+   ~VARIABLE() {
       if (ValueSize && DefaultValue) {
          delete DefaultValue;
          DefaultValue = NULL;
@@ -26,36 +32,43 @@ struct INIDEF
    }
 
    template<typename U>
-   INIDEF(LPCTSTR sName, LPCTSTR iName, const U& member, U default, LPCTSTR desc, INIDEFTYPE type) 
+   VARIABLE(LPCTSTR sName, LPCTSTR iName, const U& member, U default, LPCTSTR desc, VARIABLETYPE type) 
       : ShortName(sName), IniName(iName), MemberAddr(NULL), Description(NULL), MemberType(type) {
       SetDefault(default);
    }
 
    template<>
-   INIDEF(LPCTSTR sName, LPCTSTR iName, const std::string& member, std::string default, LPCTSTR desc, INIDEFTYPE type) 
+   VARIABLE(LPCTSTR sName, LPCTSTR iName, const std::string& member, std::string default, LPCTSTR desc, VARIABLETYPE type) 
       : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
-      MemberType = type==IDT_UNKNOWN?IDT_STRING:type; 
+      MemberType = type==vtUnknown?vtText:type; 
       SetDefault(default);
    }
 
    template<>
-   INIDEF(LPCTSTR sName, LPCTSTR iName, const int& member, int default, LPCTSTR desc, INIDEFTYPE type) 
+   VARIABLE(LPCTSTR sName, LPCTSTR iName, const int& member, int default, LPCTSTR desc, VARIABLETYPE type) 
       : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
-      MemberType = type==IDT_UNKNOWN?IDT_INT:type; 
+      MemberType = type==vtUnknown?vtInteger:type; 
       SetDefault(default);
    }
 
    template<>
-   INIDEF(LPCTSTR sName, LPCTSTR iName, const float& member, float default, LPCTSTR desc, INIDEFTYPE type) 
+   VARIABLE(LPCTSTR sName, LPCTSTR iName, const float& member, float default, LPCTSTR desc, VARIABLETYPE type) 
       : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
-      MemberType = type==IDT_UNKNOWN?IDT_FLOAT:type; 
+      MemberType = type==vtUnknown?vtFloat:type; 
       SetDefault(default);
    }
 
    template<>
-   INIDEF(LPCTSTR sName, LPCTSTR iName, const bool& member, bool default, LPCTSTR desc, INIDEFTYPE type) 
+   VARIABLE(LPCTSTR sName, LPCTSTR iName, const double& member, double default, LPCTSTR desc, VARIABLETYPE type) 
+      : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
+         MemberType = type==vtUnknown?vtDouble:type; 
+         SetDefault(default);
+   }
+
+   template<>
+   VARIABLE(LPCTSTR sName, LPCTSTR iName, const bool& member, bool default, LPCTSTR desc, VARIABLETYPE type) 
       : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { 
-      MemberType = type==IDT_UNKNOWN?IDT_BOOL:type; 
+      MemberType = type==vtUnknown?vtBoolean:type; 
       SetDefault(default);
    }
 
@@ -73,42 +86,42 @@ struct INIDEF
    LPCTSTR ShortName;
    LPCTSTR IniName;
    DWORD MemberAddr;
-   INIDEFTYPE MemberType;
+   VARIABLETYPE MemberType;
    LPCTSTR Description;
    LPVOID DefaultValue;
    DWORD ValueSize;
 };
 
 #define BEGIN_INI_MAP(name) \
-   virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \
-   virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \
-   static INIDEF* InternalGetInfDefmap() { \
+   virtual void *GetMember(const VARIABLE* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \
+   virtual const VARIABLE* GetInfDefmap() const { return InternalGetInfDefmap(); } \
+   static VARIABLE* InternalGetInfDefmap() { \
    const name* pThis = 0; \
-   static INIDEF map[] = { \
+   static VARIABLE map[] = { \
 
 #define BEGIN_INI_MAP_WITH_BASE(name, base) \
-   virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \
-   virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \
-   static INIDEF* InternalGetInfDefmap() { \
+   virtual void *GetMember(const VARIABLE* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \
+   virtual const VARIABLE* GetInfDefmap() const { return InternalGetInfDefmap(); } \
+   static VARIABLE* InternalGetInfDefmap() { \
    const name* pThis = 0; \
-   static INIDEF map[] = { \
+   static VARIABLE map[] = { \
 
 #define END_INI_MAP() \
-   INIDEF() };\
+   VARIABLE() };\
    return map;\
 }
 
 #define ADDITEM(sName, iName, member, desc) \
-   INIDEF(sName, iName, pThis->member, desc, IDT_UNKNOWN), \
+   VARIABLE(sName, iName, pThis->member, desc, vtUnknown), \
 
 #define ADDITEMEX(sName, iName, member, type, desc) \
-   INIDEF(sName, iName, pThis->member, desc, type), \
+   VARIABLE(sName, iName, pThis->member, desc, type), \
 
 struct IniFileSection
 {
    virtual LPCTSTR GetName() const = 0;
-   virtual const INIDEF* GetInfDefmap() const = 0;
-   virtual void *GetMember(const INIDEF* memptr) const = 0;
+   virtual const VARIABLE* GetInfDefmap() const = 0;
+   virtual void *GetMember(const VARIABLE* memptr) const = 0;
 };
 
 typedef std::list<IniFileSection*>  IniFileSectionList;
@@ -116,7 +129,7 @@ typedef std::list<IniFileSection*>  IniFileSectionList;
 inline int GetIniDefSectionSize(IniFileSection *section) {
    int len = 0;
 
-   for (const INIDEF *inidef = section->GetInfDefmap()
+   for (const VARIABLE *inidef = section->GetInfDefmap()
       ; inidef != NULL && inidef->ShortName
       ; ++inidef)
       ++len;
diff --git a/NifCommon/MAX_MemDirect.h b/NifCommon/MAX_MemDirect.h
index 47340a57511e49f02b8d7176acaa2fd7c518ab3b..57af5ac2c399af1ac66bdb15f99e169072252249 100644
--- a/NifCommon/MAX_MemDirect.h
+++ b/NifCommon/MAX_MemDirect.h
@@ -16,6 +16,8 @@
 #ifndef __MAX_MEM_H
 #define __MAX_MEM_H
 
+#if VERSION_3DSMAX < ((9000<<16)+(15<<8)+0) // Version 9
+
 #include <crtdbg.h>
 #include <malloc.h>
 #include <new.h>
@@ -191,5 +193,5 @@ CoreExport int	(__cdecl *MAX_CrtDumpMemoryLeaks)(void);
 #endif //IS_HYBRID
 #endif //_DEBUG
 
-
+#endif
 #endif //__MAX_MEM_H
diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp
index d50499b73df7821d157a426c002237497de30fb6..9de013614f49638420093b12d9b835bd44338e19 100644
--- a/NifCommon/niutils.cpp
+++ b/NifCommon/niutils.cpp
@@ -947,7 +947,6 @@ void CalcCenteredSphere(const vector<Vector3>& vertices, Vector3& center, float&
 
 static void TransformVector3(Matrix44& tm, vector<Vector3>& pts)
 {
-   Matrix44::IDENTITY;
    for (vector<Vector3>::iterator itr = pts.begin(); itr != pts.end(); ++itr)
    {    
       Matrix44 m4(*itr, Matrix33::IDENTITY, 1.0f);
@@ -1095,3 +1094,45 @@ Modifier *GetbhkCollisionModifier(INode *node)
    }
    return NULL;
 }
+
+void GetIniFileName(char *iniName)
+{
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
+	Interface *gi = GetCOREInterface();
+#else
+	Interface *gi = NULL;
+#endif
+	if (gi) {
+		LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
+		PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+
+		int forcePlugcfg = GetIniValue("System", "ForcePlugcfg", 0, iniName);
+
+		if (forcePlugcfg == 1 || _access(iniName, 06) != 0) {
+			TCHAR iniPath[MAX_PATH];
+			GetModuleFileName(NULL, iniPath, MAX_PATH);
+			if (LPTSTR fname = PathFindFileName(iniPath))
+				*fname = 0;
+			PathAddBackslash(iniPath);
+			PathAppend(iniPath, "plugcfg");
+			PathAppend(iniPath, "MaxNifTools.ini");
+
+			// Use plugcfg directory ini 
+			if (_access(iniPath, 06) == 0) {
+				strcpy(iniName, iniPath);
+			}
+		}
+	} else {
+		GetModuleFileName(NULL, iniName, MAX_PATH);
+		if (LPTSTR fname = PathFindFileName(iniName))
+			*fname = 0;
+		PathAddBackslash(iniName);
+		PathAppend(iniName, "plugcfg");
+		PathAppend(iniName, "MaxNifTools.ini");
+	}
+
+	if (_access(iniName, 06) != 0) {
+		MessageBox(NULL, "MaxNifTools could not find a valid INI.  The plugin may not work correctly.\nPlease check for proper installation.", 
+			"MaxNifTools", MB_OK|MB_ICONWARNING);
+	}
+}
\ No newline at end of file
diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h
index 81c2153eec99b9864f30bdfb47f19974ad40a49f..59b541a2ced55e53ec92edc0b6fa48c7c6b5a250 100644
--- a/NifCommon/niutils.h
+++ b/NifCommon/niutils.h
@@ -387,13 +387,9 @@ extern TriObject* GetTriObject(Object *o);
 
 extern TSTR GetFileVersion(const char *fileName);
 
-inline Niflib::NiObjectRef CreateBlock(const char *name) {
-   return Niflib::CreateObject(name);
-}
-
 template<typename T>
 inline Niflib::Ref<T> CreateNiObject() {
-   return Niflib::StaticCast<T>(Niflib::CreateObject(T::TypeConst().GetTypeName()));
+   return Niflib::StaticCast<T>(T::Create());
 }
 
 void CollapseGeomTransform(Niflib::NiTriBasedGeomRef shape);
@@ -402,4 +398,6 @@ void FixNormals(std::vector<Niflib::Triangle>& tris, std::vector<Niflib::Vector3
 
 Modifier *GetbhkCollisionModifier(INode *node);
 
+void GetIniFileName(char *iniName);
+
 #endif // _NIUTILS_H_
\ No newline at end of file
diff --git a/NifExport/Animation.cpp b/NifExport/Animation.cpp
index 07d943d9f9c1dd46879410a24ad04561e717766a..815422846aabce60daf5afed0154739264a3132c 100644
--- a/NifExport/Animation.cpp
+++ b/NifExport/Animation.cpp
@@ -11,7 +11,7 @@ HISTORY:
 *>	Copyright (c) 2006, All Rights Reserved.
 **********************************************************************/
 #include "pch.h"
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7+
 #include <IFrameTagManager.h>
 #endif
 #include <notetrck.h>
@@ -74,7 +74,7 @@ bool GetTextKeys(INode *node, vector<StringKey>& textKeys, Interval range)
 {
    // Populate Text keys and Sequence information from note tracks
    if (Exporter::mUseTimeTags) {
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7+
       if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
          int n = tagMgr->GetTagCount();
          for (int i = 0; i<n; i++) {
@@ -138,7 +138,7 @@ void Exporter::InitializeTimeController(NiTimeControllerRef ctrl, NiNodeRef pare
    ctrl->SetStopTime(FloatNegINF);
    ctrl->SetPhase(0.0f);
    ctrl->SetFlags(0x0C);
-   ctrl->SetTarget( parent );
+   //ctrl->SetTarget( parent );
    parent->AddController(DynamicCast<NiTimeController>(ctrl));
 }
 
@@ -328,7 +328,7 @@ bool AnimationExport::doExport(NiControllerSequenceRef seq)
 
    // Populate Text keys and Sequence information from note tracks
    if (Exporter::mUseTimeTags) {
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7
       if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
          int n = tagMgr->GetTagCount();
          for (int i = 0; i<n; i++) {
@@ -409,7 +409,7 @@ bool AnimationExport::doExport(NiControllerManagerRef mgr, INode *node)
 
    // Populate Text keys and Sequence information from note tracks
    if (Exporter::mUseTimeTags) {
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7
       if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
 
          curSeq = new NiControllerSequence();
@@ -721,13 +721,14 @@ NiTimeControllerRef AnimationExport::exportController(INode *node, Interval rang
             Exporter::InitializeTimeController(control, ninode);
 
             NiTransformInterpolatorRef interp = new NiTransformInterpolator();
-            data = new NiTransformData();
+            NiTransformDataRef tdata = new NiTransformData();
+            data = StaticCast<NiKeyframeData>(tdata);
             control->SetInterpolator(StaticCast<NiInterpolator>(interp));
 
             interp->SetTranslation(trans);
             interp->SetScale(scale);
             interp->SetRotation(rot);
-            interp->SetData(data);
+            interp->SetData(tdata);
 
             timeControl = StaticCast<NiTimeController>(control);
          }
@@ -740,7 +741,7 @@ NiTimeControllerRef AnimationExport::exportController(INode *node, Interval rang
          //   interp->SetTranslation( TOVECTOR3(tm.GetTrans()) );
          //   interp->SetScale( Average(GetScale(tm)) );
          //   interp->SetRotation( TOQUAT( Quat(tm) ) );
-         //   seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control));
+         //   seq->AddInterpolator(StaticCast<NiSingleInterpController>(control));
          //}
          //else
          {
@@ -954,13 +955,13 @@ bool AnimationExport::exportController(INode *node, bool hasAccum)
    NiTimeControllerRef control = exportController( node, range, keepTM );
    if (control != NULL)
    {
-      NiSingleInterpolatorControllerRef interpControl = DynamicCast<NiSingleInterpolatorController>(control);
+      NiSingleInterpControllerRef interpControl = DynamicCast<NiSingleInterpController>(control);
       if (interpControl) 
       {
          // Get Priority from node
          float priority;
          npGetProp(node, NP_ANM_PRI, priority, Exporter::mDefaultPriority);
-         seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(control), priority);
+         seq->AddInterpolator(StaticCast<NiSingleInterpController>(control), priority);
 
          // Handle NonAccum 
          if (Exporter::mAllowAccum && hasAccum)
@@ -985,7 +986,7 @@ bool AnimationExport::exportController(INode *node, bool hasAccum)
                   accinterp->SetData( interp->GetData() );
                   interp->SetData( NiTransformDataRef() );
                }
-               seq->AddInterpolator(StaticCast<NiSingleInterpolatorController>(acccontrol), Exporter::mDefaultPriority);
+               seq->AddInterpolator(StaticCast<NiSingleInterpController>(acccontrol), Exporter::mDefaultPriority);
 
                accnode->RemoveController(acccontrol);
             }
diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp
index 8281c68fc2d36af29313d46cc3c2c64ff5596a24..0ccf0986f12df8b9ec2b565d599368fcb659472f 100755
--- a/NifExport/Coll.cpp
+++ b/NifExport/Coll.cpp
@@ -281,7 +281,7 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node)
 		bhkCollisionObjectRef co = new bhkCollisionObject();
 		co->SetBody(DynamicCast<NiObject>(body));
       
-		co->SetParent(newParent);
+		//co->SetTarget(newParent);
 
 		// link
 		newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co));
@@ -332,7 +332,7 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node)
 	npGetProp(node, NP_HVK_CENTER, center);
 
 	// setup body
-	bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBodyT"));
+	bhkRigidBodyRef body = CreateNiObject<bhkRigidBodyT>();
 
 	body->SetLayer(OblivionLayer(lyr));
 	body->SetLayerCopy(OblivionLayer(lyr));
@@ -424,7 +424,7 @@ bhkSphereRepShapeRef Exporter::makeCapsuleShape(Object *obj, const Matrix3& tm)
 	params->GetValue(obj->GetParamBlockIndex(CAPSULE_RADIUS), 0, radius, FOREVER);
 	params->GetValue(obj->GetParamBlockIndex(CAPSULE_HEIGHT), 0, height, FOREVER);
 
-	bhkCapsuleShapeRef capsule = DynamicCast<bhkCapsuleShape>(CreateBlock("bhkCapsuleShape"));
+	bhkCapsuleShapeRef capsule = CreateNiObject<bhkCapsuleShape>();
 
 	return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(capsule));
 }
@@ -476,14 +476,16 @@ bhkSphereRepShapeRef Exporter::makeTriStripsShape(INode *node, const Matrix3& tm
 	data->SetNormals(vnorms);
 
 	// setup shape
-	bhkNiTriStripsShapeRef shape = DynamicCast<bhkNiTriStripsShape>(CreateBlock("bhkNiTriStripsShape"));
-	shape->SetNumStripsData(1);
-	shape->SetStripsData(0, data);
+	bhkNiTriStripsShapeRef shape = StaticCast<bhkNiTriStripsShape>(bhkNiTriStripsShape::Create());
 
-	if (tri != os.obj)
-		tri->DeleteMe();
+	//bhkNiTriStripsShapeRef shape = DynamicCast<bhkNiTriStripsShape>(CreateBlock("bhkNiTriStripsShape"));
+	//shape->SetNumStripsData(1);
+	//shape->SetStripsData(0, data);
+
+	//if (tri != os.obj)
+	//	tri->DeleteMe();
 
-	return bhkSphereRepShapeRef(DynamicCast<bhkSphereRepShape>(shape));
+	return bhkSphereRepShapeRef();
 }
 
 
diff --git a/NifExport/Config.cpp b/NifExport/Config.cpp
index 39ab0efcbaf817a43e6c64f0e34dc51e241611b2..5f40d78933f1adc998917d4a491eb05f5fc5224a 100755
--- a/NifExport/Config.cpp
+++ b/NifExport/Config.cpp
@@ -46,8 +46,7 @@ void Exporter::writeConfig(Interface *i)
    else
    {
       TCHAR iniName[MAX_PATH];
-      LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+      GetIniFileName(iniName);
 
       SetIniValue(NifExportSection, "GenerateStrips", mTriStrips, iniName);
       SetIniValue(NifExportSection, "IncludeHidden", mExportHidden, iniName);
@@ -118,8 +117,7 @@ void Exporter::readConfig(Interface *i)
    else
    {
       TCHAR iniName[MAX_PATH];
-      LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+      GetIniFileName(iniName);
 
       //mVersion = GetIniValue<int>(NifExportSection, "Version", 013, iniName);
       mTriStrips = GetIniValue<bool>(NifExportSection, "GenerateStrips", true, iniName);
@@ -165,8 +163,7 @@ void Exporter::readConfig(Interface *i)
 void Exporter::readKfConfig(Interface *i)
 {
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
 
    mExportHidden = GetIniValue(KfExportSection, "IncludeHidden", false, iniName);
    mExportLights = GetIniValue(KfExportSection, "Lights", false, iniName);
@@ -192,8 +189,7 @@ void Exporter::writeKfConfig(Interface *i)
 AppSettings * Exporter::exportAppSettings()
 {
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = GetCOREInterface()->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
 
    // Update the current app version
    AppSettings * appSettings = FindAppSetting(Exporter::mGameName);
@@ -218,8 +214,7 @@ AppSettings *Exporter::importAppSettings(string fname)
 {
    AppSettings *appSettings = NULL;
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = GetCOREInterface()->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
 
    // Locate which application to use. If Auto, find first app where this file appears in the root path list
    string curapp = GetIniValue<string>(NifExportSection, "CurrentApp", "AUTO", iniName);
diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp
index e7fe0de59b4d3141d97e816c5a2873247f5d5cb7..6e848f1fcef07db81673d8e7404d1f251afb6c37 100755
--- a/NifExport/Exporter.cpp
+++ b/NifExport/Exporter.cpp
@@ -90,21 +90,21 @@ Exporter::Result Exporter::doExport(NiNodeRef &root, INode *node)
 
             BSXFlagsRef bsx = CreateNiObject<BSXFlags>();
             bsx->SetName("BSX");
-            bsx->SetFlags( 0x00000007 );
+			bsx->SetData( 0x00000007 );
             root->AddExtraData(DynamicCast<NiExtraData>(bsx));
          }
          else if (mExportType != NIF_WO_ANIM)
          {
             BSXFlagsRef bsx = CreateNiObject<BSXFlags>();
             bsx->SetName("BSX");
-            bsx->SetFlags( 0x00000003 );
+            bsx->SetData( 0x00000003 );
             root->AddExtraData(DynamicCast<NiExtraData>(bsx));
          }
          else if (mExportCollision)
          {
             BSXFlagsRef bsx = CreateNiObject<BSXFlags>();
             bsx->SetName("BSX");
-            bsx->SetFlags( 0x00000002 );
+            bsx->SetData( 0x00000002 );
             root->AddExtraData(DynamicCast<NiExtraData>(bsx));
          }
       }
diff --git a/NifExport/KfExport.cpp b/NifExport/KfExport.cpp
index 0d85c97b45a488494901a02fd618b3f0a19ae56f..0bfcd7041bcd4a37863d38bc29cebd379b28e1b2 100644
--- a/NifExport/KfExport.cpp
+++ b/NifExport/KfExport.cpp
@@ -188,17 +188,7 @@ KfExport::KfExport()
 {
    Interface *gi = GetCOREInterface();
    TCHAR iniName[MAX_PATH];
-   if (gi) {
-      LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
-   } else {
-      GetModuleFileName(NULL, iniName, _countof(iniName));
-      if (LPTSTR fname = PathFindFileName(iniName))
-         fname = NULL;
-      PathAddBackslash(iniName);
-      PathAppend(iniName, "plugcfg");
-      PathAppend(iniName, "MaxNifTools.ini");
-   }
+   GetIniFileName(iniName);
    iniFileName = iniName;
    shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName);
    fileVersion = GetFileVersion(NULL);
@@ -275,8 +265,7 @@ int	KfExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL s
       AppSettings::Initialize(i);
 
       TCHAR iniName[MAX_PATH];
-      LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+      GetIniFileName(iniName);
       bool iniNameIsValid = (-1 != _taccess(iniName, 0));
 
       // read config from registry
diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp
index 9fcc315bf596a7af40d1f9173a869768056e3de9..ddeac52119fda00a1fa536840c8c5f6c78d6e5ff 100755
--- a/NifExport/Mesh.cpp
+++ b/NifExport/Mesh.cpp
@@ -38,7 +38,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue
          mtx.NoTrans();    
          mesh = copymesh = new Mesh(*mesh);     
          int n = mesh->getNumVerts();
-         for ( uint i = 0; i < n; ++i ) {
+         for ( unsigned int i = 0; i < n; ++i ) {
             Point3& vert = mesh->getVert(i);
             vert = mtx * vert;
          }
@@ -47,7 +47,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue
          MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals ();
          if (NULL != specNorms) {
             specNorms->CheckNormals();
-            for ( uint i = 0; i < specNorms->GetNumNormals(); ++i ) {
+            for ( unsigned int i = 0; i < specNorms->GetNumNormals(); ++i ) {
                Point3& norm = specNorms->Normal(i);
                norm = (mtx * norm).Normalize();
             }
@@ -141,7 +141,7 @@ Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue
 			}
 
          if (node->IsHidden())
-            shape->SetHidden(true);
+            shape->SetVisibility(false);
 
          shape->SetName(name);
          shape->SetLocalTransform(tm);
@@ -423,7 +423,7 @@ bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, Ti
 Exporter::Result SkinInstance::execute()
 {
    shape->BindSkin(boneList);
-   uint bone = 0;
+   unsigned int bone = 0;
    for (BoneWeightList::iterator bitr = boneWeights.begin(); bitr != boneWeights.end(); ++bitr, ++bone) {
       shape->SetBoneWeights(bone, (*bitr));
    }
diff --git a/NifExport/MtlTex.cpp b/NifExport/MtlTex.cpp
index 8624b178a0f0e6ba7700b9f4325353cc20716160..587ab656ee6ec70849e4302753d674cdb331480f 100755
--- a/NifExport/MtlTex.cpp
+++ b/NifExport/MtlTex.cpp
@@ -79,9 +79,7 @@ bool Exporter::makeTextureDesc(BitmapTex *bmTex, TexDesc& td)
    if (mAppSettings)
    {
       string newPath = mAppSettings->GetRelativeTexPath(string(mapPath), mTexPrefix);
-
-      NiObjectRef unk_link(NULL);
-      td.source->SetExternalTexture(newPath, unk_link);
+      td.source->SetExternalTexture(newPath);
    }
    else
    {
@@ -93,8 +91,7 @@ bool Exporter::makeTextureDesc(BitmapTex *bmTex, TexDesc& td)
       else
          newPath = f;
 
-      NiObjectRef unk_link(NULL);
-      td.source->SetExternalTexture(newPath.data(), unk_link);
+      td.source->SetExternalTexture(newPath.data());
    }
    return true;
 }
@@ -107,7 +104,7 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl)
       return;
 
 	string name;
-	NiMaterialPropertyRef mtlProp(DynamicCast<NiMaterialProperty>(CreateBlock("NiMaterialProperty")));
+	NiMaterialPropertyRef mtlProp(CreateNiObject<NiMaterialProperty>());
 	if (mtl)
 	{
 		Color c;
@@ -143,9 +140,9 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl)
                if (smtl->GetTwoSided()){
                   NiStencilPropertyRef stencil = new NiStencilProperty();
                   stencil->SetStencilFunction(TEST_GREATER);
-                  stencil->SetStencilEnabled(false);
+                  stencil->SetStencilState(false);
                   stencil->SetPassAction(ACTION_INCREMENT);
-                  stencil->SetDrawMode(DRAW_BOTH);
+                  stencil->SetFaceDrawMode(DRAW_BOTH);
                   parent->AddProperty(stencil);
                }
                if (smtl->IsFaceted()) {
@@ -344,9 +341,9 @@ bool Exporter::exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl)
                if (smtl->GetTwoSided()){
                   NiStencilPropertyRef stencil = CreateNiObject<NiStencilProperty>();
                   stencil->SetStencilFunction(TEST_GREATER);
-                  stencil->SetStencilEnabled(false);
+                  stencil->SetStencilState(false);
                   stencil->SetPassAction(ACTION_INCREMENT);
-                  stencil->SetDrawMode(DRAW_BOTH);
+                  stencil->SetFaceDrawMode(DRAW_BOTH);
                   parent->AddProperty(stencil);
                }
                if (smtl->IsFaceted()) {
@@ -378,31 +375,31 @@ bool Exporter::exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl)
       if (alphaMode != 0 || AlphaTestEnable) {
          // always add alpha ???
          NiAlphaPropertyRef alphaProp = CreateNiObject<NiAlphaProperty>();
-         alphaProp->SetAlphaBlend(true);
+         alphaProp->SetBlendState(true);
          if (alphaMode == 0) { // automatic
-            alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend));
-            alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend));
+            alphaProp->SetSourceBlendFunc(NiAlphaProperty::BlendFunc(srcBlend));
+            alphaProp->SetDestBlendFunc(NiAlphaProperty::BlendFunc(destBlend));
          } else if (alphaMode == 1) { // None
-            alphaProp->SetAlphaBlend(false);
-            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA);
-            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA);
+            alphaProp->SetBlendState(false);
+            alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_SRC_ALPHA);
+            alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_ONE_MINUS_SRC_ALPHA);
          } else if (alphaMode == 2) { // Standard
-            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA);
-            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA);
+            alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_SRC_ALPHA);
+            alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_ONE_MINUS_SRC_ALPHA);
          } else if (alphaMode == 3) { // Additive
-            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ONE);
-            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE);
+            alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_ONE);
+            alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_ONE);
          } else if (alphaMode == 4) { // Multiplicative
-            alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ZERO);
-            alphaProp->SetDestBlendMode(NiAlphaProperty::BM_SRC_COLOR);
+            alphaProp->SetSourceBlendFunc(NiAlphaProperty::BF_ZERO);
+            alphaProp->SetDestBlendFunc(NiAlphaProperty::BF_SRC_COLOR);
          } else { // Advanced
-            alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend));
-            alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend));
+            alphaProp->SetSourceBlendFunc(NiAlphaProperty::BlendFunc(srcBlend));
+            alphaProp->SetDestBlendFunc(NiAlphaProperty::BlendFunc(destBlend));
          }
-         alphaProp->SetTestMode(NiAlphaProperty::TestMode(TestMode));
-         alphaProp->SetAlphaSort(!NoSorter);
-         alphaProp->SetAlphaTestThreshold(TestRef);
-         alphaProp->SetAlphaTest(AlphaTestEnable);
+         alphaProp->SetTestFunc(NiAlphaProperty::TestFunc(TestMode));
+         alphaProp->SetTriangleSortMode(!NoSorter);
+         alphaProp->SetTestThreshold(TestRef);
+         alphaProp->SetBlendState(AlphaTestEnable);
          parent->AddProperty(alphaProp);
       }
 
diff --git a/NifExport/NifExport.cpp b/NifExport/NifExport.cpp
index 22a8ad5ae72112d5996a999190e880ee8b3a0b9e..dfbaf9b6b2268ab41349ef6097806efd916dfec7 100755
--- a/NifExport/NifExport.cpp
+++ b/NifExport/NifExport.cpp
@@ -39,6 +39,13 @@ public:
    int				DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts=FALSE, DWORD options=0);
    int				DoExportInternal(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options);
 
+   SDK_RESERVED_METHOD(1); // russom 02/26/01
+   SDK_RESERVED_METHOD(2); // russom 02/26/01
+   SDK_RESERVED_METHOD(3); // russom 02/26/01
+   SDK_RESERVED_METHOD(4); // russom 02/26/01
+   SDK_RESERVED_METHOD(5); // russom 02/26/01
+   SDK_RESERVED_METHOD(6); // russom 02/26/01
+
 	NifExport();
 	~NifExport();		
 };
@@ -167,12 +174,12 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA
             GetDlgItemText(hWnd, IDC_CB_VERSION, tmp, MAX_PATH);
             if (tmp[0] != 0)
             {
-               int nifVersion = ParseVersionString(tmp);
-               if (!IsSupportedVersion(nifVersion))
-               {
-                  MessageBox(hWnd, FormatString("Version '%s' is not a supported version.", tmp).c_str(), "NifExport", MB_OK|MB_ICONSTOP);
-                  return FALSE;
-               }
+               int nifVersion = ParseVersionString(tmp);
+               if (!IsSupportedVersion(nifVersion))
+               {
+                  MessageBox(hWnd, FormatString("Version '%s' is not a supported version.", tmp).c_str(), "NifExport", MB_OK|MB_ICONSTOP);
+                  return FALSE;
+               }
             }
 
             Exporter::mTriStrips = IsDlgButtonChecked(hWnd, IDC_CHK_STRIPS);
@@ -275,17 +282,7 @@ NifExport::NifExport()
 {
    Interface *gi = GetCOREInterface();
    TCHAR iniName[MAX_PATH];
-   if (gi) {
-      LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
-   } else {
-      GetModuleFileName(NULL, iniName, _countof(iniName));
-      if (LPTSTR fname = PathFindFileName(iniName))
-         fname = NULL;
-      PathAddBackslash(iniName);
-      PathAppend(iniName, "plugcfg");
-      PathAppend(iniName, "MaxNifTools.ini");
-   }
+   GetIniFileName(iniName);
    iniFileName = iniName;
    shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName);
    fileVersion = GetFileVersion(NULL);
@@ -369,44 +366,43 @@ int	NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL
    i->PushPrompt(title);
    if (!suppressPrompts)
       i->ProgressStart(title, TRUE, dummyProgress, NULL);
-	try
-	{
-      DoExportInternal(name, ei, i, suppressPrompts, options);
-   }
-   catch (Exporter::CancelExporterException&)
-   {
-      // Special user cancellation exception
-   }
-   catch (exception &e)
-   {
-      if (!suppressPrompts)
-         MessageBox(NULL, e.what(), "Export Error", MB_OK);
+	try
+	{
+      DoExportInternal(name, ei, i, suppressPrompts, options);
+   }
+   catch (Exporter::CancelExporterException&)
+   {
+      // Special user cancellation exception
+   }
+   catch (exception &e)
+   {
+      if (!suppressPrompts)
+         MessageBox(NULL, e.what(), "Export Error", MB_OK);
    }
    catch (...)
    {
       if (!suppressPrompts)
-         MessageBox(NULL, "Unknown error.", "Export Error", MB_OK);
+         MessageBox(NULL, "Unknown error.", "Export Error", MB_OK);
    }
    i->PopPrompt();
    if (!suppressPrompts)
       i->ProgressEnd();
    return true;
-}
-
+}
+
 int NifExport::DoExportInternal(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options)
 {
-   TCHAR path[MAX_PATH];
-   GetFullPathName(name, MAX_PATH, path, NULL);
-   PathRenameExtension(path, ".nif");
-
-   Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0;
-
+   TCHAR path[MAX_PATH];
+   GetFullPathName(name, MAX_PATH, path, NULL);
+   PathRenameExtension(path, ".nif");
+
+   Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0;
+
    // read application settings
    AppSettings::Initialize(i);
 
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = i->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
    bool iniNameIsValid = (-1 != _taccess(iniName, 0));
 
    // Set whether Config should use registry or not
@@ -433,66 +429,66 @@ int NifExport::DoExportInternal(const TCHAR *name, ExpInterface *ei, Interface *
 
       appSettings = Exporter::exportAppSettings();
       appSettings->WriteSettings(i);
-   }
-
-   int nifVersion = VER_20_0_0_5;
-   int nifUserVer = Exporter::mNifUserVersion;
-   if (!Exporter::mNifVersion.empty())
-   {
-      nifVersion = ParseVersionString(Exporter::mNifVersion);
-      if (!IsSupportedVersion(nifVersion))
-         throw exception(FormatString("Version '%s' is not a supported version.").c_str());
-   }
-   Exporter::mNifVersionInt = nifVersion;
-
-   Exporter::ExportType exportType = Exporter::mExportType;
-
-   // Hack so MW exports cleaner. Basically write tree without NiControllerManager
-   if (  nifVersion <= VER_10_0_1_0 
-      && (Exporter::mExportType != Exporter::NIF_WO_ANIM && Exporter::mExportType != Exporter::NIF_WITH_MGR)
-      )
-   {
-      Exporter::mExportType = Exporter::NIF_WO_KF;
-   }
-   Niflib::NifInfo info(nifVersion, nifUserVer, nifUserVer);
-   info.endian = Niflib::NifInfo::INFO_LITTLE_ENDIAN;
-   info.creator = Exporter::mCreatorName;
-   info.exportInfo1 = FormatText("Niftools 3ds Max Plugins %s", fileVersion.data());
-
-	Exporter exp(i, appSettings);
-	
-	Ref<NiNode> root = new NiNode();
+   }
+
+   int nifVersion = VER_20_0_0_5;
+   int nifUserVer = Exporter::mNifUserVersion;
+   if (!Exporter::mNifVersion.empty())
+   {
+      nifVersion = ParseVersionString(Exporter::mNifVersion);
+      if (!IsSupportedVersion(nifVersion))
+         throw exception(FormatString("Version '%s' is not a supported version.").c_str());
+   }
+   Exporter::mNifVersionInt = nifVersion;
+
+   Exporter::ExportType exportType = Exporter::mExportType;
+
+   // Hack so MW exports cleaner. Basically write tree without NiControllerManager
+   if (  nifVersion <= VER_10_0_1_0 
+      && (Exporter::mExportType != Exporter::NIF_WO_ANIM && Exporter::mExportType != Exporter::NIF_WITH_MGR)
+      )
+   {
+      Exporter::mExportType = Exporter::NIF_WO_KF;
+   }
+   Niflib::NifInfo info(nifVersion, nifUserVer, nifUserVer);
+   info.endian = ENDIAN_LITTLE;
+   info.creator = Exporter::mCreatorName;
+   info.exportInfo1 = FormatText("Niftools 3ds Max Plugins %s", fileVersion.data());
+
+	Exporter exp(i, appSettings);
+	
+	Ref<NiNode> root = new NiNode();
 	Exporter::Result result = exp.doExport(root, i->GetRootNode());
 
 	if (result!=Exporter::Ok)
 		throw exception("Unknown error.");
-
-   if (exportType == Exporter::NIF_WO_ANIM || exportType == Exporter::NIF_WITH_MGR)
-   {
-      WriteNifTree(path, NiObjectRef(root), info);
-   }
-   else 
-   {
-      Niflib::ExportOptions export_type = EXPORT_NIF;
-      switch (exportType) {
+
+   if (exportType == Exporter::NIF_WO_ANIM || exportType == Exporter::NIF_WITH_MGR)
+   {
+      WriteNifTree(path, NiObjectRef(root), info);
+   }
+   else 
+   {
+      Niflib::ExportOptions export_type = EXPORT_NIF;
+      switch (exportType) {
          case Exporter::SINGLE_KF_WITH_NIF: export_type = EXPORT_NIF_KF;       break;
          case Exporter::SINGLE_KF_WO_NIF:   export_type = EXPORT_KF;           break;
          case Exporter::MULTI_KF_WITH_NIF:  export_type = EXPORT_NIF_KF_MULTI; break;
          case Exporter::MULTI_KF_WO_NIF:    export_type = EXPORT_KF_MULTI;     break;
-      }
-
-      Niflib::NifGame game = KF_MW;
-      if (nifVersion <= VER_4_0_0_2) {
-         game = KF_MW;
-      } else if (nifVersion <= VER_20_0_0_4) {
-         game = KF_DAOC;
-      } else {
-         game = KF_CIV4;
-      }
-
-      WriteFileGroup(path, StaticCast<NiObject>(root), info, export_type, game);
-   }
-   return true;
+      }
+
+      Niflib::NifGame game = KF_MW;
+      if (nifVersion <= VER_4_0_0_2) {
+         game = KF_MW;
+      } else if (nifVersion <= VER_20_0_0_4) {
+         game = KF_DAOC;
+      } else {
+         game = KF_CIV4;
+      }
+
+      WriteFileGroup(path, StaticCast<NiObject>(root), info, export_type, game);
+   }
+   return true;
 }
 
 
diff --git a/NifExport/NvTriStrip/NvTriStrip.cpp b/NifExport/NvTriStrip/NvTriStrip.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..88e4c1e5fb7ac13eb91846fdfb25fbc5d7171d01
--- /dev/null
+++ b/NifExport/NvTriStrip/NvTriStrip.cpp
@@ -0,0 +1,504 @@
+
+#include "NvTriStripObjects.h"
+#include "NvTriStrip.h"
+
+using namespace NvTriStrip;
+
+namespace NvTriStrip {
+
+////////////////////////////////////////////////////////////////////////////////////////
+//private data
+static unsigned int cacheSize    = CACHESIZE_GEFORCE1_2;
+static bool bStitchStrips         = true;
+static unsigned int minStripSize = 0;
+static bool bListsOnly            = false;
+static unsigned int restartVal   = 0;
+static bool bRestart              = false;
+
+void EnableRestart(const unsigned int _restartVal)
+{
+	bRestart = true;
+	restartVal = _restartVal;
+}
+
+void DisableRestart()
+{
+	bRestart = false;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetListsOnly()
+//
+// If set to true, will return an optimized list, with no strips at all.
+//
+// Default value: false
+//
+void SetListsOnly(const bool _bListsOnly)
+{
+	bListsOnly = _bListsOnly;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetCacheSize()
+//
+// Sets the cache size which the stripfier uses to optimize the data.
+// Controls the length of the generated individual strips.
+// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
+// You may want to play around with this number to tweak performance.
+//
+// Default value: 16
+//
+void SetCacheSize(const unsigned int _cacheSize)
+{
+	cacheSize = _cacheSize;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetStitchStrips()
+//
+// bool to indicate whether to stitch together strips into one huge strip or not.
+// If set to true, you'll get back one huge strip stitched together using degenerate
+//  triangles.
+// If set to false, you'll get back a large number of separate strips.
+//
+// Default value: true
+//
+void SetStitchStrips(const bool _bStitchStrips)
+{
+	bStitchStrips = _bStitchStrips;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetMinStripSize()
+//
+// Sets the minimum acceptable size for a strip, in triangles.
+// All strips generated which are shorter than this will be thrown into one big, separate list.
+//
+// Default value: 0
+//
+void SetMinStripSize(const unsigned int _minStripSize)
+{
+	minStripSize = _minStripSize;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//Cleanup strips / faces, used by generatestrips
+void Cleanup(NvStripInfoVec& tempStrips, NvFaceInfoVec& tempFaces)
+{
+	//delete strips
+	for(size_t i = 0; i < tempStrips.size(); i++)
+	{
+		for(size_t j = 0; j < tempStrips[i]->m_faces.size(); j++)
+		{
+			delete tempStrips[i]->m_faces[j];
+			tempStrips[i]->m_faces[j] = NULL;
+		}
+		tempStrips[i]->m_faces.resize(0);
+		delete tempStrips[i];
+		tempStrips[i] = NULL;
+	}
+
+	//delete faces
+	for(size_t i = 0; i < tempFaces.size(); i++)
+	{
+		delete tempFaces[i];
+		tempFaces[i] = NULL;
+	}
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+//SameTriangle()
+//
+//Returns true if the two triangles defined by firstTri and secondTri are the same
+// The "same" is defined in this case as having the same indices with the same winding order
+//
+bool SameTriangle(unsigned short firstTri0, unsigned short firstTri1, unsigned short firstTri2, 
+				  unsigned short secondTri0, unsigned short secondTri1, unsigned short secondTri2)
+{
+	bool isSame = false;
+
+	if (firstTri0 == secondTri0)
+	{
+		if (firstTri1 == secondTri1)
+		{
+			if (firstTri2 == secondTri2)
+				isSame = true;
+		}
+	}
+	else if (firstTri0 == secondTri1)
+	{
+		if (firstTri1 == secondTri2)
+		{
+			if (firstTri2 == secondTri0)
+				isSame = true;
+		}
+	}
+	else if (firstTri0 == secondTri2)
+	{
+		if (firstTri1 == secondTri0)
+		{
+			if (firstTri2 == secondTri1)
+				isSame = true;
+		}
+	}
+
+	return isSame;
+}
+
+
+bool TestTriangle(const unsigned short v0, const unsigned short v1, const unsigned short v2, const std::vector<NvFaceInfo>* in_bins, const int NUMBINS)
+{
+	//hash this triangle
+	bool isLegit = false;
+	int ctr = v0 % NUMBINS;
+	for (size_t k = 0; k < in_bins[ctr].size(); ++k)
+	{
+		//check triangles in this bin
+		if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, 
+			v0, v1, v2))
+		{
+			isLegit = true;
+			break;
+		}
+	}
+	if (!isLegit)
+	{
+		ctr = v1 % NUMBINS;
+		for (size_t k = 0; k < in_bins[ctr].size(); ++k)
+		{
+			//check triangles in this bin
+			if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, 
+				v0, v1, v2))
+			{
+				isLegit = true;
+				break;
+			}
+		}
+		
+		if (!isLegit)
+		{
+			ctr = v2 % NUMBINS;
+			for (size_t k = 0; k < in_bins[ctr].size(); ++k)
+			{
+				//check triangles in this bin
+				if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2, 
+					v0, v1, v2))
+				{
+					isLegit = true;
+					break;
+				}
+			}
+			
+		}
+	}
+
+	return isLegit;
+}
+	
+
+////////////////////////////////////////////////////////////////////////////////////////
+// GenerateStrips()
+//
+// in_indices: input index list, the indices you would use to render
+// in_numIndices: number of entries in in_indices
+// primGroups: array of optimized/stripified PrimitiveGroups
+// numGroups: number of groups returned
+//
+// Be sure to call delete[] on the returned primGroups to avoid leaking mem
+//
+bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
+					PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled)
+{
+	//put data in format that the stripifier likes
+	WordVec tempIndices;
+	tempIndices.resize(in_numIndices);
+	unsigned short maxIndex = 0;
+	unsigned short minIndex = 0xFFFF;
+	for(size_t i = 0; i < in_numIndices; i++)
+	{
+		tempIndices[i] = in_indices[i];
+		if (in_indices[i] > maxIndex)
+			maxIndex = in_indices[i];
+		if (in_indices[i] < minIndex)
+			minIndex = in_indices[i];
+	}
+	NvStripInfoVec tempStrips;
+	NvFaceInfoVec tempFaces;
+
+	NvStripifier stripifier;
+	
+	//do actual stripification
+	stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces);
+
+	//stitch strips together
+	IntVec stripIndices;
+	unsigned int numSeparateStrips = 0;
+
+	if(bListsOnly)
+	{
+		//if we're outputting only lists, we're done
+		*numGroups = 1;
+		(*primGroups) = new PrimitiveGroup[*numGroups];
+		PrimitiveGroup* primGroupArray = *primGroups;
+
+		//count the total number of indices
+		unsigned int numIndices = 0;
+		for(size_t i = 0; i < tempStrips.size(); i++)
+		{
+			numIndices += tempStrips[i]->m_faces.size() * 3;
+		}
+
+		//add in the list
+		numIndices += tempFaces.size() * 3;
+
+		primGroupArray[0].type       = PT_LIST;
+		primGroupArray[0].numIndices = numIndices;
+		primGroupArray[0].indices    = new unsigned short[numIndices];
+
+		//do strips
+		unsigned int indexCtr = 0;
+		for(size_t i = 0; i < tempStrips.size(); i++)
+		{
+			for(size_t j = 0; j < tempStrips[i]->m_faces.size(); j++)
+			{
+				//degenerates are of no use with lists
+				if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j]))
+				{
+					primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v0;
+					primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v1;
+					primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v2;
+				}
+				else
+				{
+					//we've removed a tri, reduce the number of indices
+					primGroupArray[0].numIndices -= 3;
+				}
+			}
+		}
+
+		//do lists
+		for(size_t i = 0; i < tempFaces.size(); i++)
+		{			
+			primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0;
+			primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1;
+			primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2;
+		}
+	}
+	else
+	{
+		stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips, bRestart, restartVal);
+
+		//if we're stitching strips together, we better get back only one strip from CreateStrips()
+		assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips);
+		
+		//convert to output format
+		*numGroups = numSeparateStrips; //for the strips
+		if(tempFaces.size() != 0)
+			(*numGroups)++;  //we've got a list as well, increment
+		(*primGroups) = new PrimitiveGroup[*numGroups];
+		
+		PrimitiveGroup* primGroupArray = *primGroups;
+		
+		//first, the strips
+		int startingLoc = 0;
+   		for(size_t stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++)
+		{
+			int stripLength = 0;
+
+			if(!bStitchStrips)
+			{
+				//if we've got multiple strips, we need to figure out the correct length
+				size_t i;
+				for(i = startingLoc; i < stripIndices.size(); i++)
+				{
+					if(stripIndices[i] == -1)
+						break;
+				}
+				
+				stripLength = i - startingLoc;
+			}
+			else
+				stripLength = stripIndices.size();
+			
+			primGroupArray[stripCtr].type       = PT_STRIP;
+			primGroupArray[stripCtr].indices    = new unsigned short[stripLength];
+			primGroupArray[stripCtr].numIndices = stripLength;
+			
+			int indexCtr = 0;
+			for(int i = startingLoc; i < stripLength + startingLoc; i++)
+				primGroupArray[stripCtr].indices[indexCtr++] = stripIndices[i];
+
+			//we add 1 to account for the -1 separating strips
+			//this doesn't break the stitched case since we'll exit the loop
+			startingLoc += stripLength + 1; 
+		}
+		
+		//next, the list
+		if(tempFaces.size() != 0)
+		{
+			int faceGroupLoc = (*numGroups) - 1;    //the face group is the last one
+			primGroupArray[faceGroupLoc].type       = PT_LIST;
+			primGroupArray[faceGroupLoc].indices    = new unsigned short[tempFaces.size() * 3];
+			primGroupArray[faceGroupLoc].numIndices = tempFaces.size() * 3;
+			int indexCtr = 0;
+			for(size_t i = 0; i < tempFaces.size(); i++)
+			{
+				primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v0;
+				primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v1;
+				primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v2;
+			}
+		}
+	}
+
+	//validate generated data against input
+	if (validateEnabled)
+	{
+		const int NUMBINS = 100;
+
+		std::vector<NvFaceInfo> in_bins[NUMBINS];
+		
+		//hash input indices on first index
+		for (size_t i = 0; i < in_numIndices; i += 3)
+		{
+			NvFaceInfo faceInfo(in_indices[i], in_indices[i + 1], in_indices[i + 2]);
+			in_bins[in_indices[i] % NUMBINS].push_back(faceInfo);
+		}
+		
+		for (int i = 0; i < *numGroups; ++i)
+		{
+			switch ((*primGroups)[i].type)
+			{
+				case PT_LIST:
+				{
+					for (size_t j = 0; j < (*primGroups)[i].numIndices; j += 3)
+					{
+						unsigned short v0 = (*primGroups)[i].indices[j];
+						unsigned short v1 = (*primGroups)[i].indices[j + 1];
+						unsigned short v2 = (*primGroups)[i].indices[j + 2];
+						
+						//ignore degenerates
+						if (NvStripifier::IsDegenerate(v0, v1, v2))
+							continue;
+
+						if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS))
+						{
+							Cleanup(tempStrips, tempFaces);
+							return false;
+						}
+					}
+					break;
+				}
+
+				case PT_STRIP:
+				{
+					//int brokenCtr = 0;
+					bool flip = false;
+					for (size_t j = 2; j < (*primGroups)[i].numIndices; ++j)
+					{
+						unsigned short v0 = (*primGroups)[i].indices[j - 2];
+						unsigned short v1 = (*primGroups)[i].indices[j - 1];
+						unsigned short v2 = (*primGroups)[i].indices[j];
+						
+						if (flip)
+						{
+							//swap v1 and v2
+							unsigned short swap = v1;
+							v1 = v2;
+							v2 = swap;
+						}
+
+						//ignore degenerates
+						if (NvStripifier::IsDegenerate(v0, v1, v2))
+						{
+							flip = !flip;
+							continue;
+						}
+
+						if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS))
+						{
+							Cleanup(tempStrips, tempFaces);
+							return false;
+						}
+
+						flip = !flip;
+					}
+					break;
+				}
+
+				case PT_FAN:
+				default:
+					break;
+			}
+		}
+
+	}
+
+	//clean up everything
+	Cleanup(tempStrips, tempFaces);
+
+	return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RemapIndices()
+//
+// Function to remap your indices to improve spatial locality in your vertex buffer.
+//
+// in_primGroups: array of PrimitiveGroups you want remapped
+// numGroups: number of entries in in_primGroups
+// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
+//  of acceptable values for indices in your primitive groups.
+// remappedGroups: array of remapped PrimitiveGroups
+//
+// Note that, according to the remapping handed back to you, you must reorder your 
+//  vertex buffer.
+//
+void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
+				  const unsigned short numVerts, PrimitiveGroup** remappedGroups)
+{
+	(*remappedGroups) = new PrimitiveGroup[numGroups];
+
+	//caches oldIndex --> newIndex conversion
+	int *indexCache;
+	indexCache = new int[numVerts];
+	memset(indexCache, -1, sizeof(int)*numVerts);
+	
+	//loop over primitive groups
+	unsigned int indexCtr = 0;
+	for(int i = 0; i < numGroups; i++)
+	{
+		unsigned int numIndices = in_primGroups[i].numIndices;
+
+		//init remapped group
+		(*remappedGroups)[i].type       = in_primGroups[i].type;
+		(*remappedGroups)[i].numIndices = numIndices;
+		(*remappedGroups)[i].indices    = new unsigned short[numIndices];
+
+		for(size_t j = 0; j < numIndices; j++)
+		{
+			int cachedIndex = indexCache[in_primGroups[i].indices[j]];
+			if(cachedIndex == -1) //we haven't seen this index before
+			{
+				//point to "last" vertex in VB
+				(*remappedGroups)[i].indices[j] = indexCtr;
+
+				//add to index cache, increment
+				indexCache[in_primGroups[i].indices[j]] = indexCtr++;
+			}
+			else
+			{
+				//we've seen this index before
+				(*remappedGroups)[i].indices[j] = cachedIndex;
+			}
+		}
+	}
+
+	delete[] indexCache;
+}
+
+} //end namespace
diff --git a/NifExport/NvTriStrip/NvTriStrip.h b/NifExport/NvTriStrip/NvTriStrip.h
new file mode 100644
index 0000000000000000000000000000000000000000..0e6c695da8a043e61355324213b8d53deace304b
--- /dev/null
+++ b/NifExport/NvTriStrip/NvTriStrip.h
@@ -0,0 +1,147 @@
+#ifndef NVTRISTRIP_H
+#define NVTRISTRIP_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+namespace NvTriStrip {
+
+////////////////////////////////////////////////////////////////////////////////////////
+// Public interface for stripifier
+////////////////////////////////////////////////////////////////////////////////////////
+
+//GeForce1 and 2 cache size
+#define CACHESIZE_GEFORCE1_2 16
+
+//GeForce3 cache size
+#define CACHESIZE_GEFORCE3   24
+
+enum PrimType
+{
+	PT_LIST,
+	PT_STRIP,
+	PT_FAN
+};
+
+struct PrimitiveGroup
+{
+	PrimType type;
+	unsigned int numIndices;
+	unsigned short* indices;
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+	PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {}
+	~PrimitiveGroup()
+	{
+		if(indices)
+			delete[] indices;
+		indices = NULL;
+	}
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// EnableRestart()
+//
+// For GPUs that support primitive restart, this sets a value as the restart index
+//
+// Restart is meaningless if strips are not being stitched together, so enabling restart
+//  makes NvTriStrip forcing stitching.  So, you'll get back one strip.
+//
+// Default value: disabled
+//
+void EnableRestart(const unsigned int restartVal);
+
+////////////////////////////////////////////////////////////////////////////////////////
+// DisableRestart()
+//
+// For GPUs that support primitive restart, this disables using primitive restart
+//
+void DisableRestart();
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetCacheSize()
+//
+// Sets the cache size which the stripfier uses to optimize the data.
+// Controls the length of the generated individual strips.
+// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
+// You may want to play around with this number to tweak performance.
+//
+// Default value: 16
+//
+void SetCacheSize(const unsigned int cacheSize);
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetStitchStrips()
+//
+// bool to indicate whether to stitch together strips into one huge strip or not.
+// If set to true, you'll get back one huge strip stitched together using degenerate
+//  triangles.
+// If set to false, you'll get back a large number of separate strips.
+//
+// Default value: true
+//
+void SetStitchStrips(const bool bStitchStrips);
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetMinStripSize()
+//
+// Sets the minimum acceptable size for a strip, in triangles.
+// All strips generated which are shorter than this will be thrown into one big, separate list.
+//
+// Default value: 0
+//
+void SetMinStripSize(const unsigned int minSize);
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// SetListsOnly()
+//
+// If set to true, will return an optimized list, with no strips at all.
+//
+// Default value: false
+//
+void SetListsOnly(const bool bListsOnly);
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// GenerateStrips()
+//
+// in_indices: input index list, the indices you would use to render
+// in_numIndices: number of entries in in_indices
+// primGroups: array of optimized/stripified PrimitiveGroups
+// numGroups: number of groups returned
+//
+// Be sure to call delete[] on the returned primGroups to avoid leaking mem
+//
+bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
+					PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled = false);
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RemapIndices()
+//
+// Function to remap your indices to improve spatial locality in your vertex buffer.
+//
+// in_primGroups: array of PrimitiveGroups you want remapped
+// numGroups: number of entries in in_primGroups
+// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
+//  of acceptable values for indices in your primitive groups.
+// remappedGroups: array of remapped PrimitiveGroups
+//
+// Note that, according to the remapping handed back to you, you must reorder your 
+//  vertex buffer.
+//
+// Credit goes to the MS Xbox crew for the idea for this interface.
+//
+void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups, 
+				  const unsigned short numVerts, PrimitiveGroup** remappedGroups);
+
+} //End namespace
+
+#endif
\ No newline at end of file
diff --git a/NifExport/NvTriStrip/NvTriStripObjects.cpp b/NifExport/NvTriStrip/NvTriStripObjects.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4cf11d34d006ef3a63edc13811d29b0af8f38681
--- /dev/null
+++ b/NifExport/NvTriStrip/NvTriStripObjects.cpp
@@ -0,0 +1,1771 @@
+
+//#pragma warning( disable : 4786 )  
+
+#include <assert.h>
+#include <set>
+#include "NvTriStripObjects.h"
+#include "VertexCache.h"
+
+using namespace NvTriStrip;
+
+#define CACHE_INEFFICIENCY 6
+
+NvStripifier::NvStripifier()
+{
+	
+}
+
+NvStripifier::~NvStripifier()
+{
+	
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// FindEdgeInfo()
+//
+// find the edge info for these two indices
+//
+NvEdgeInfo * NvStripifier::FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1){
+	
+	// we can get to it through either array
+	// because the edge infos have a v0 and v1
+	// and there is no order except how it was
+	// first created.
+	NvEdgeInfo *infoIter = edgeInfos[v0];
+	while (infoIter != NULL){
+		if (infoIter->m_v0 == v0){
+			if (infoIter->m_v1 == v1)
+				return infoIter;
+			else
+				infoIter = infoIter->m_nextV0;
+		}
+		else {
+			assert(infoIter->m_v1 == v0);
+			if (infoIter->m_v0 == v1)
+				return infoIter;
+			else
+				infoIter = infoIter->m_nextV1;
+		}
+	}
+	return NULL;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// FindOtherFace
+//
+// find the other face sharing these vertices
+// exactly like the edge info above
+//
+NvFaceInfo * NvStripifier::FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo){
+	NvEdgeInfo *edgeInfo = FindEdgeInfo(edgeInfos, v0, v1);
+
+	if( (edgeInfo == NULL) && (v0 == v1))
+	{
+		//we've hit a degenerate
+		return NULL;
+	}
+
+	assert(edgeInfo != NULL);
+	return (edgeInfo->m_face0 == faceInfo ? edgeInfo->m_face1 : edgeInfo->m_face0);
+}
+
+
+bool NvStripifier::AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos)
+{
+	for(size_t i = 0; i < faceInfos.size(); ++i)
+	{
+		if( (faceInfos[i]->m_v0 == faceInfo->m_v0) &&
+			(faceInfos[i]->m_v1 == faceInfo->m_v1) &&
+			(faceInfos[i]->m_v2 == faceInfo->m_v2) )
+			return true;
+	}
+
+	return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// BuildStripifyInfo()
+//
+// Builds the list of all face and edge infos
+//
+void NvStripifier::BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos,
+									 const unsigned short maxIndex)
+{
+	// reserve space for the face infos, but do not resize them.
+	int numIndices = indices.size();
+	faceInfos.reserve(numIndices / 3);
+	
+	// we actually resize the edge infos, so we must initialize to NULL
+	edgeInfos.resize(maxIndex + 1);
+	for (int i = 0; i < maxIndex + 1; i++)
+		edgeInfos[i] = NULL;
+	
+	// iterate through the triangles of the triangle list
+	int numTriangles = numIndices / 3;
+	int index        = 0;
+	bool bFaceUpdated[3];
+
+	for (int i = 0; i < numTriangles; i++)
+	{	
+		bool bMightAlreadyExist = true;
+		bFaceUpdated[0] = false;
+		bFaceUpdated[1] = false;
+		bFaceUpdated[2] = false;
+
+		// grab the indices
+		int v0 = indices[index++];
+		int v1 = indices[index++];
+		int v2 = indices[index++];
+
+		//we disregard degenerates
+		if(IsDegenerate(v0, v1, v2))
+			continue;
+		
+		// create the face info and add it to the list of faces, but only if this exact face doesn't already 
+		//  exist in the list
+		NvFaceInfo *faceInfo = new NvFaceInfo(v0, v1, v2);
+		
+		// grab the edge infos, creating them if they do not already exist
+		NvEdgeInfo *edgeInfo01 = FindEdgeInfo(edgeInfos, v0, v1);
+		if (edgeInfo01 == NULL)
+		{
+			//since one of it's edges isn't in the edge data structure, it can't already exist in the face structure
+			bMightAlreadyExist = false;
+
+			// create the info
+			edgeInfo01 = new NvEdgeInfo(v0, v1);
+			
+			// update the linked list on both 
+			edgeInfo01->m_nextV0 = edgeInfos[v0];
+			edgeInfo01->m_nextV1 = edgeInfos[v1];
+			edgeInfos[v0] = edgeInfo01;
+			edgeInfos[v1] = edgeInfo01;
+			
+			// set face 0
+			edgeInfo01->m_face0 = faceInfo;
+		}
+		else 
+		{
+			if (edgeInfo01->m_face1 != NULL)
+			{
+				//printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
+			}
+			else
+			{
+				edgeInfo01->m_face1 = faceInfo;
+				bFaceUpdated[0] = true;
+			}
+		}
+		
+		// grab the edge infos, creating them if they do not already exist
+		NvEdgeInfo *edgeInfo12 = FindEdgeInfo(edgeInfos, v1, v2);
+		if (edgeInfo12 == NULL)
+		{
+			bMightAlreadyExist = false;
+			
+			// create the info
+			edgeInfo12 = new NvEdgeInfo(v1, v2);
+			
+			// update the linked list on both 
+			edgeInfo12->m_nextV0 = edgeInfos[v1];
+			edgeInfo12->m_nextV1 = edgeInfos[v2];
+			edgeInfos[v1] = edgeInfo12;
+			edgeInfos[v2] = edgeInfo12;
+			
+			// set face 0
+			edgeInfo12->m_face0 = faceInfo;
+		}
+		else 
+		{
+			if (edgeInfo12->m_face1 != NULL)
+			{
+				//printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
+			}
+			else
+			{
+				edgeInfo12->m_face1 = faceInfo;
+				bFaceUpdated[1] = true;
+			}
+		}
+		
+		// grab the edge infos, creating them if they do not already exist
+		NvEdgeInfo *edgeInfo20 = FindEdgeInfo(edgeInfos, v2, v0);
+		if (edgeInfo20 == NULL)
+		{
+			bMightAlreadyExist = false;
+
+			// create the info
+			edgeInfo20 = new NvEdgeInfo(v2, v0);
+			
+			// update the linked list on both 
+			edgeInfo20->m_nextV0 = edgeInfos[v2];
+			edgeInfo20->m_nextV1 = edgeInfos[v0];
+			edgeInfos[v2] = edgeInfo20;
+			edgeInfos[v0] = edgeInfo20;
+			
+			// set face 0
+			edgeInfo20->m_face0 = faceInfo;
+		}
+		else 
+		{
+			if (edgeInfo20->m_face1 != NULL)
+			{
+				//printf("BuildStripifyInfo: > 2 triangles on an edge... uncertain consequences\n");
+			}
+			else
+			{
+				edgeInfo20->m_face1 = faceInfo;
+				bFaceUpdated[2] = true;
+			}
+		}
+
+		if(bMightAlreadyExist)
+		{
+			if(!AlreadyExists(faceInfo, faceInfos))
+				faceInfos.push_back(faceInfo);
+			else
+			{
+				delete faceInfo;
+
+				//cleanup pointers that point to this deleted face
+				if(bFaceUpdated[0])
+					edgeInfo01->m_face1 = NULL;
+				if(bFaceUpdated[1])
+					edgeInfo12->m_face1 = NULL;
+				if(bFaceUpdated[2])
+					edgeInfo20->m_face1 = NULL;
+			}
+		}
+		else
+		{
+			faceInfos.push_back(faceInfo);
+		}
+
+	}
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// FindStartPoint()
+//
+// Finds a good starting point, namely one which has only one neighbor
+//
+int NvStripifier::FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos)
+{
+	int bestCtr = -1;
+	int bestIndex = -1;
+
+	for(size_t i = 0; i < faceInfos.size(); i++)
+	{
+		int ctr = 0;
+		
+		if(FindOtherFace(edgeInfos, faceInfos[i]->m_v0, faceInfos[i]->m_v1, faceInfos[i]) == NULL)
+			ctr++;
+		if(FindOtherFace(edgeInfos, faceInfos[i]->m_v1, faceInfos[i]->m_v2, faceInfos[i]) == NULL)
+			ctr++;
+		if(FindOtherFace(edgeInfos, faceInfos[i]->m_v2, faceInfos[i]->m_v0, faceInfos[i]) == NULL)
+			ctr++;
+		if(ctr > bestCtr)
+		{
+			bestCtr = ctr;
+			bestIndex = i;
+			//return i;
+		}
+	}
+	//return -1;
+	
+	if(bestCtr == 0)
+		return -1;
+	else
+		return bestIndex;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// FindGoodResetPoint()
+//  
+// A good reset point is one near other commited areas so that
+// we know that when we've made the longest strips its because
+// we're stripifying in the same general orientation.
+//
+NvFaceInfo* NvStripifier::FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos){
+	// we hop into different areas of the mesh to try to get
+	// other large open spans done.  Areas of small strips can
+	// just be left to triangle lists added at the end.
+	NvFaceInfo *result = NULL;
+	
+	if(result == NULL)
+	{
+		int numFaces   = faceInfos.size();
+      if (numFaces == 0)
+         return NULL;
+
+		int startPoint;
+		if(bFirstTimeResetPoint)
+		{
+			//first time, find a face with few neighbors (look for an edge of the mesh)
+			startPoint = FindStartPoint(faceInfos, edgeInfos);
+			bFirstTimeResetPoint = false;
+		}
+		else
+			startPoint = (int)(((float) numFaces - 1) * meshJump);
+		
+		if(startPoint == -1)
+		{
+			startPoint = (int)(((float) numFaces - 1) * meshJump);
+			
+			//meshJump += 0.1f;
+			//if (meshJump > 1.0f)
+			//	meshJump = .05f;
+		}
+
+		int i = startPoint;
+		do {
+			
+			// if this guy isn't visited, try him
+			if (faceInfos[i]->m_stripId < 0){
+				result = faceInfos[i];
+				break;
+			}
+			
+			// update the index and clamp to 0-(numFaces-1)
+			if (++i >= numFaces)
+				i = 0;
+			
+		} while (i != startPoint);
+		
+		// update the meshJump
+		meshJump += 0.1f;
+		if (meshJump > 1.0f)
+			meshJump = .05f;
+	}
+	
+	// return the best face we found
+	return result;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// GetUniqueVertexInB()
+//
+// Returns the vertex unique to faceB
+//
+int NvStripifier::GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB){
+	
+	int facev0 = faceB->m_v0;
+	if (facev0 != faceA->m_v0 &&
+		facev0 != faceA->m_v1 &&
+		facev0 != faceA->m_v2)
+		return facev0;
+	
+	int facev1 = faceB->m_v1;
+	if (facev1 != faceA->m_v0 &&
+		facev1 != faceA->m_v1 &&
+		facev1 != faceA->m_v2)
+		return facev1;
+	
+	int facev2 = faceB->m_v2;
+	if (facev2 != faceA->m_v0 &&
+		facev2 != faceA->m_v1 &&
+		facev2 != faceA->m_v2)
+		return facev2;
+	
+	// nothing is different
+	return -1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// GetSharedVertices()
+//
+// Returns the (at most) two vertices shared between the two faces
+//
+void NvStripifier::GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1)
+{
+	*vertex0 = -1;
+	*vertex1 = -1;
+
+	int facev0 = faceB->m_v0;
+	if (facev0 == faceA->m_v0 ||
+		facev0 == faceA->m_v1 ||
+		facev0 == faceA->m_v2)
+	{
+		if(*vertex0 == -1)
+			*vertex0 = facev0;
+		else
+		{
+			*vertex1 = facev0;
+			return;
+		}
+	}
+	
+	int facev1 = faceB->m_v1;
+	if (facev1 == faceA->m_v0 ||
+		facev1 == faceA->m_v1 ||
+		facev1 == faceA->m_v2)
+	{
+		if(*vertex0 == -1)
+			*vertex0 = facev1;
+		else
+		{
+			*vertex1 = facev1;
+			return;
+		}
+	}	
+
+	int facev2 = faceB->m_v2;
+	if (facev2 == faceA->m_v0 ||
+		facev2 == faceA->m_v1 ||
+		facev2 == faceA->m_v2)
+	{
+		if(*vertex0 == -1)
+			*vertex0 = facev2;
+		else
+		{
+			*vertex1 = facev2;
+			return;
+		}
+	}
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// GetNextIndex()
+//
+// Returns vertex of the input face which is "next" in the input index list
+//
+inline int NvStripifier::GetNextIndex(const WordVec &indices, NvFaceInfo *face){
+	
+	int numIndices = indices.size();
+	assert(numIndices >= 2);
+	
+	int v0  = indices[numIndices-2];
+	int v1  = indices[numIndices-1];
+	
+	int fv0 = face->m_v0;
+	int fv1 = face->m_v1;
+	int fv2 = face->m_v2;
+	
+	if (fv0 != v0 && fv0 != v1){
+		if ((fv1 != v0 && fv1 != v1) || (fv2 != v0 && fv2 != v1)){
+			//printf("GetNextIndex: Triangle doesn't have all of its vertices\n");
+			//printf("GetNextIndex: Duplicate triangle probably got us derailed\n");
+		}
+		return fv0;
+	}
+	if (fv1 != v0 && fv1 != v1){
+		if ((fv0 != v0 && fv0 != v1) || (fv2 != v0 && fv2 != v1)){
+			//printf("GetNextIndex: Triangle doesn't have all of its vertices\n");
+			//printf("GetNextIndex: Duplicate triangle probably got us derailed\n");
+		}
+		return fv1;
+	}
+	if (fv2 != v0 && fv2 != v1){
+		if ((fv0 != v0 && fv0 != v1) || (fv1 != v0 && fv1 != v1)){
+			//printf("GetNextIndex: Triangle doesn't have all of its vertices\n");
+			//printf("GetNextIndex: Duplicate triangle probably got us derailed\n");
+		}
+		return fv2;
+	}
+	
+	// shouldn't get here, but let's try and fail gracefully
+	if( (fv0 == fv1) || (fv0 == fv2) )
+		return fv0;
+	else if( (fv1 == fv0) || (fv1 == fv2) )
+		return fv1;
+	else if( (fv2 == fv0) || (fv2 == fv1) )
+		return fv2;
+	else
+		return -1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// IsMarked()
+//
+// If either the faceInfo has a real strip index because it is
+// already assign to a committed strip OR it is assigned in an
+// experiment and the experiment index is the one we are building
+// for, then it is marked and unavailable
+inline bool NvStripInfo::IsMarked(NvFaceInfo *faceInfo){
+	return (faceInfo->m_stripId >= 0) || (IsExperiment() && faceInfo->m_experimentId == m_experimentId);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// MarkTriangle()
+//
+// Marks the face with the current strip ID
+//
+inline void NvStripInfo::MarkTriangle(NvFaceInfo *faceInfo){
+	assert(!IsMarked(faceInfo));
+	if (IsExperiment()){
+		faceInfo->m_experimentId = m_experimentId;
+		faceInfo->m_testStripId  = m_stripId;
+    }
+	else{
+		assert(faceInfo->m_stripId == -1);
+		faceInfo->m_experimentId = -1;
+		faceInfo->m_stripId      = m_stripId;
+	}
+}
+
+
+bool NvStripInfo::Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face)
+{
+	bool bv0, bv1, bv2; //bools to indicate whether a vertex is in the faceVec or not
+	bv0 = bv1 = bv2 = false;
+
+	for(size_t i = 0; i < faceVec.size(); i++)
+	{
+		if(!bv0)
+		{
+			if( (faceVec[i]->m_v0 == face->m_v0) || 
+				(faceVec[i]->m_v1 == face->m_v0) ||
+				(faceVec[i]->m_v2 == face->m_v0) )
+				bv0 = true;
+		}
+
+		if(!bv1)
+		{
+			if( (faceVec[i]->m_v0 == face->m_v1) || 
+				(faceVec[i]->m_v1 == face->m_v1) ||
+				(faceVec[i]->m_v2 == face->m_v1) )
+				bv1 = true;
+		}
+
+		if(!bv2)
+		{
+			if( (faceVec[i]->m_v0 == face->m_v2) || 
+				(faceVec[i]->m_v1 == face->m_v2) ||
+				(faceVec[i]->m_v2 == face->m_v2) )
+				bv2 = true;
+		}
+
+		//the face is not unique, all it's vertices exist in the face vector
+		if(bv0 && bv1 && bv2)
+			return false;
+	}
+	
+	//if we get out here, it's unique
+	return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// Build()
+//
+// Builds a strip forward as far as we can go, then builds backwards, and joins the two lists
+//
+void NvStripInfo::Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos)
+{
+	// used in building the strips forward and backward
+	WordVec scratchIndices;
+	
+	// build forward... start with the initial face
+	NvFaceInfoVec forwardFaces, backwardFaces;
+	forwardFaces.push_back(m_startInfo.m_startFace);
+
+	MarkTriangle(m_startInfo.m_startFace);
+	
+	int v0 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v0 : m_startInfo.m_startEdge->m_v1);
+	int v1 = (m_startInfo.m_toV1 ? m_startInfo.m_startEdge->m_v1 : m_startInfo.m_startEdge->m_v0);
+	
+	// easiest way to get v2 is to use this function which requires the
+	// other indices to already be in the list.
+	scratchIndices.push_back(v0);
+	scratchIndices.push_back(v1);
+	int v2 = NvStripifier::GetNextIndex(scratchIndices, m_startInfo.m_startFace);
+	scratchIndices.push_back(v2);
+
+	//
+	// build the forward list
+	//
+	int nv0 = v1;
+	int nv1 = v2;
+
+	NvFaceInfo *nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace);
+	while (nextFace != NULL && !IsMarked(nextFace))
+	{
+		//check to see if this next face is going to cause us to die soon
+		int testnv0 = nv1;
+		int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
+		
+		NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace);
+
+		if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) )
+		{
+			//uh, oh, we're following a dead end, try swapping
+			NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace);
+
+			if( ((testNextFace != NULL) && !IsMarked(testNextFace)) )
+			{
+				//we only swap if it buys us something
+				
+				//add a "fake" degenerate face
+				NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0, true);
+				
+				forwardFaces.push_back(tempFace);
+				MarkTriangle(tempFace);
+
+				scratchIndices.push_back(nv0);
+				testnv0 = nv0;
+
+				++m_numDegenerates;
+			}
+
+		}
+
+		// add this to the strip
+		forwardFaces.push_back(nextFace);
+
+		MarkTriangle(nextFace);
+		
+		// add the index
+		//nv0 = nv1;
+		//nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
+		scratchIndices.push_back(testnv1);
+		
+		// and get the next face
+		nv0 = testnv0;
+		nv1 = testnv1;
+
+		nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace);
+	
+	}
+	
+	// tempAllFaces is going to be forwardFaces + backwardFaces
+	// it's used for Unique()
+	NvFaceInfoVec tempAllFaces;
+	for(size_t i = 0; i < forwardFaces.size(); i++)
+		tempAllFaces.push_back(forwardFaces[i]);
+
+	//
+	// reset the indices for building the strip backwards and do so
+	//
+	scratchIndices.resize(0);
+	scratchIndices.push_back(v2);
+	scratchIndices.push_back(v1);
+	scratchIndices.push_back(v0);
+	nv0 = v1;
+	nv1 = v0;
+	nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, m_startInfo.m_startFace);
+	while (nextFace != NULL && !IsMarked(nextFace))
+	{
+		//this tests to see if a face is "unique", meaning that its vertices aren't already in the list
+		// so, strips which "wrap-around" are not allowed
+		if(!Unique(tempAllFaces, nextFace))
+			break;
+
+		//check to see if this next face is going to cause us to die soon
+		int testnv0 = nv1;
+		int testnv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
+		
+		NvFaceInfo* nextNextFace = NvStripifier::FindOtherFace(edgeInfos, testnv0, testnv1, nextFace);
+
+		if( (nextNextFace == NULL) || (IsMarked(nextNextFace)) )
+		{
+			//uh, oh, we're following a dead end, try swapping
+			NvFaceInfo* testNextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, testnv1, nextFace);
+			if( ((testNextFace != NULL) && !IsMarked(testNextFace)) )
+			{
+				//we only swap if it buys us something
+				
+				//add a "fake" degenerate face
+				NvFaceInfo* tempFace = new NvFaceInfo(nv0, nv1, nv0, true);
+
+				backwardFaces.push_back(tempFace);
+				MarkTriangle(tempFace);
+				scratchIndices.push_back(nv0);
+				testnv0 = nv0;
+
+				++m_numDegenerates;
+			}
+				
+		}
+
+		// add this to the strip
+		backwardFaces.push_back(nextFace);
+		
+		//this is just so Unique() will work
+		tempAllFaces.push_back(nextFace);
+
+		MarkTriangle(nextFace);
+		
+		// add the index
+		//nv0 = nv1;
+		//nv1 = NvStripifier::GetNextIndex(scratchIndices, nextFace);
+		scratchIndices.push_back(testnv1);
+		
+		// and get the next face
+		nv0 = testnv0;
+		nv1 = testnv1;
+		nextFace = NvStripifier::FindOtherFace(edgeInfos, nv0, nv1, nextFace);
+	}
+	
+	// Combine the forward and backwards stripification lists and put into our own face vector
+	Combine(forwardFaces, backwardFaces);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// Combine()
+//
+// Combines the two input face vectors and puts the result into m_faces
+//
+void NvStripInfo::Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward){
+	
+	// add backward faces
+	int numFaces = backward.size();
+	for (int i = numFaces - 1; i >= 0; i--)
+		m_faces.push_back(backward[i]);
+	
+	// add forward faces
+	numFaces = forward.size();
+	for (int i = 0; i < numFaces; i++)
+		m_faces.push_back(forward[i]);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// SharesEdge()
+//
+// Returns true if the input face and the current strip share an edge
+//
+bool NvStripInfo::SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos)
+{
+	//check v0->v1 edge
+	NvEdgeInfo* currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v0, faceInfo->m_v1);
+	
+	if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1))
+		return true;
+	
+	//check v1->v2 edge
+	currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v1, faceInfo->m_v2);
+	
+	if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1))
+		return true;
+	
+	//check v2->v0 edge
+	currEdge = NvStripifier::FindEdgeInfo(edgeInfos, faceInfo->m_v2, faceInfo->m_v0);
+	
+	if(IsInStrip(currEdge->m_face0) || IsInStrip(currEdge->m_face1))
+		return true;
+	
+	return false;
+	
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// CommitStrips()
+//
+// "Commits" the input strips by setting their m_experimentId to -1 and adding to the allStrips
+//  vector
+//
+void NvStripifier::CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips)
+{	
+	// Iterate through strips
+	int numStrips = strips.size();
+	for (int i = 0; i < numStrips; i++){
+
+		// Tell the strip that it is now real
+		NvStripInfo *strip = strips[i];
+		strip->m_experimentId = -1;
+		
+		// add to the list of real strips
+		allStrips.push_back(strip);
+		
+		// Iterate through the faces of the strip
+		// Tell the faces of the strip that they belong to a real strip now
+		const NvFaceInfoVec &faces = strips[i]->m_faces;
+		int numFaces = faces.size();
+
+		for (int j = 0; j < numFaces; j++)
+		{
+			strip->MarkTriangle(faces[j]);
+		}
+	}
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// FindTraversal()
+//
+// Finds the next face to start the next strip on.
+//
+bool NvStripifier::FindTraversal(NvFaceInfoVec &faceInfos,
+								 NvEdgeInfoVec    &edgeInfos,
+								 NvStripInfo      *strip,
+								 NvStripStartInfo &startInfo){
+	
+	// if the strip was v0->v1 on the edge, then v1 will be a vertex in the next edge.
+	int v = (strip->m_startInfo.m_toV1 ? strip->m_startInfo.m_startEdge->m_v1 : strip->m_startInfo.m_startEdge->m_v0);
+	
+	NvFaceInfo *untouchedFace = NULL;
+	NvEdgeInfo *edgeIter      = edgeInfos[v];
+	while (edgeIter != NULL){
+		NvFaceInfo *face0 = edgeIter->m_face0;
+		NvFaceInfo *face1 = edgeIter->m_face1;
+		if ((face0 != NULL && !strip->IsInStrip(face0)) && face1 != NULL && !strip->IsMarked(face1))
+		{
+			untouchedFace = face1;
+			break;
+		}
+		if ((face1 != NULL && !strip->IsInStrip(face1)) && face0 != NULL && !strip->IsMarked(face0)){
+			untouchedFace = face0;
+			break;
+		}
+		
+		// find the next edgeIter
+		edgeIter = (edgeIter->m_v0 == v ? edgeIter->m_nextV0 : edgeIter->m_nextV1);
+	}
+	
+	startInfo.m_startFace = untouchedFace;
+	startInfo.m_startEdge = edgeIter;
+	if (edgeIter != NULL)
+	{
+		if(strip->SharesEdge(startInfo.m_startFace, edgeInfos))
+			startInfo.m_toV1 = (edgeIter->m_v0 == v);  //note! used to be m_v1
+		else
+			startInfo.m_toV1 = (edgeIter->m_v1 == v);
+	}
+	return (startInfo.m_startFace != NULL);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+// RemoveSmallStrips()
+//
+// allStrips is the whole strip vector...all small strips will be deleted from this list, to avoid leaking mem
+// allBigStrips is an out parameter which will contain all strips above minStripLength
+// faceList is an out parameter which will contain all faces which were removed from the striplist
+//
+void NvStripifier::RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList)
+{
+	faceList.clear();
+	allBigStrips.clear();  //make sure these are empty
+	NvFaceInfoVec tempFaceList;
+	
+	for(size_t i = 0; i < allStrips.size(); i++)
+	{
+		if(allStrips[i]->m_faces.size() < size_t(minStripLength))
+		{
+			//strip is too small, add faces to faceList
+			for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++)
+				tempFaceList.push_back(allStrips[i]->m_faces[j]);
+			
+			//and free memory
+			delete allStrips[i];
+		}
+		else
+		{
+			allBigStrips.push_back(allStrips[i]);
+		}
+	}
+	
+	if(tempFaceList.size())
+	{
+		bool *bVisitedList = new bool[tempFaceList.size()];
+		memset(bVisitedList, 0, tempFaceList.size()*sizeof(bool));
+		
+		VertexCache* vcache = new VertexCache(cacheSize);
+		
+		int bestNumHits = -1;
+		int numHits;
+		int bestIndex = -1;
+		
+		while(1)
+		{
+			bestNumHits = -1;
+			
+			//find best face to add next, given the current cache
+			for(size_t i = 0; i < tempFaceList.size(); i++)
+			{
+				if(bVisitedList[i])
+					continue;
+				
+				numHits = CalcNumHitsFace(vcache, tempFaceList[i]);
+				if(numHits > bestNumHits)
+				{
+					bestNumHits = numHits;
+					bestIndex = i;
+				}
+			}
+			
+			if(bestNumHits == -1.0f)
+				break;
+			bVisitedList[bestIndex] = true;
+			UpdateCacheFace(vcache, tempFaceList[bestIndex]);
+			faceList.push_back(tempFaceList[bestIndex]);
+		}
+		
+		delete vcache;
+		delete[] bVisitedList;
+	}
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// NextIsCW()
+//
+// Returns true if the next face should be ordered in CW fashion
+//
+bool NvStripifier::NextIsCW(const int numIndices)
+{
+	return ((numIndices % 2) == 0);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// IsCW()
+//
+// Returns true if the face is ordered in CW fashion
+//
+bool NvStripifier::IsCW(NvFaceInfo *faceInfo, int v0, int v1)
+{
+	if (faceInfo->m_v0 == v0)
+		return (faceInfo->m_v1 == v1);
+	
+	else if (faceInfo->m_v1 == v0)
+		return (faceInfo->m_v2 == v1);
+	
+	else 
+		return (faceInfo->m_v0 == v1);
+	
+	// shouldn't get here
+	assert(0);
+	return false;
+}
+
+bool NvStripifier::FaceContainsIndex(const NvFaceInfo& face, const unsigned int index)
+{
+	return ( (size_t(face.m_v0) == index) || (size_t(face.m_v1) == index) || (size_t(face.m_v2) == index) );
+}
+
+bool NvStripifier::IsMoneyFace(const NvFaceInfo& face)
+{
+	if(FaceContainsIndex(face, 800) &&
+	   FaceContainsIndex(face, 812) &&
+	   FaceContainsIndex(face, 731))
+	   return true;
+
+	return false;
+}
+				
+////////////////////////////////////////////////////////////////////////////////////////
+// CreateStrips()
+//
+// Generates actual strips from the list-in-strip-order.
+//
+void NvStripifier::CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, 
+								const bool bStitchStrips, unsigned int& numSeparateStrips, 
+								const bool bRestart, const unsigned int restartVal)
+{
+	assert(numSeparateStrips == 0);
+
+	NvFaceInfo tLastFace(0, 0, 0);
+	NvFaceInfo tPrevStripLastFace(0, 0, 0);
+	int nStripCount = allStrips.size();
+	assert(nStripCount > 0);
+
+	//we infer the cw/ccw ordering depending on the number of indices
+	//this is screwed up by the fact that we insert -1s to denote changing strips
+	//this is to account for that
+	int accountForNegatives = 0;
+
+	for (int i = 0; i < nStripCount; i++)
+	{
+		NvStripInfo *strip = allStrips[i];
+		int nStripFaceCount = strip->m_faces.size();
+		assert(nStripFaceCount > 0);
+
+		// Handle the first face in the strip
+		{
+			NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
+
+			// If there is a second face, reorder vertices such that the
+			// unique vertex is first
+			if (nStripFaceCount > 1)
+			{
+				int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
+				if (nUnique == tFirstFace.m_v1)
+				{
+					SWAP(tFirstFace.m_v0, tFirstFace.m_v1);
+				}
+				else if (nUnique == tFirstFace.m_v2)
+				{
+					SWAP(tFirstFace.m_v0, tFirstFace.m_v2);
+				}
+
+				// If there is a third face, reorder vertices such that the
+				// shared vertex is last
+				if (nStripFaceCount > 2)
+				{
+					if(IsDegenerate(strip->m_faces[1]))
+					{
+						int pivot = strip->m_faces[1]->m_v1;
+						if(tFirstFace.m_v1 == pivot)
+						{
+							SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
+						}
+					}
+					else
+					{
+						int nShared0, nShared1;
+						GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1);
+						if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) )
+						{
+							SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
+						}
+					}
+				}
+			}
+
+			if( (i == 0) || !bStitchStrips || bRestart)
+			{
+				if(!IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
+					stripIndices.push_back(tFirstFace.m_v0);
+			}
+			else
+			{
+				// Double tap the first in the new strip
+				stripIndices.push_back(tFirstFace.m_v0);
+	
+				// Check CW/CCW ordering
+				if (NextIsCW(stripIndices.size() - accountForNegatives) != IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
+				{
+					stripIndices.push_back(tFirstFace.m_v0);
+				}
+			}
+
+			stripIndices.push_back(tFirstFace.m_v0);
+			stripIndices.push_back(tFirstFace.m_v1);
+			stripIndices.push_back(tFirstFace.m_v2);
+
+			// Update last face info
+			tLastFace = tFirstFace;
+		}
+
+		for (int j = 1; j < nStripFaceCount; j++)
+		{
+			int nUnique = GetUniqueVertexInB(&tLastFace, strip->m_faces[j]);
+			if (nUnique != -1)
+			{
+				stripIndices.push_back(nUnique);
+
+				// Update last face info
+				tLastFace.m_v0 = tLastFace.m_v1;
+				tLastFace.m_v1 = tLastFace.m_v2;
+				tLastFace.m_v2 = nUnique;
+			}
+			else
+			{
+				//we've hit a degenerate
+				stripIndices.push_back(strip->m_faces[j]->m_v2);
+				tLastFace.m_v0 = strip->m_faces[j]->m_v0;//tLastFace.m_v1;
+				tLastFace.m_v1 = strip->m_faces[j]->m_v1;//tLastFace.m_v2;
+				tLastFace.m_v2 = strip->m_faces[j]->m_v2;//tLastFace.m_v1;
+
+			}
+		}
+
+		// Double tap between strips.
+		if (bStitchStrips && !bRestart) 
+		{
+			if (i != nStripCount - 1)
+				stripIndices.push_back(tLastFace.m_v2);
+		} 
+		else if (bRestart) 
+		{
+			stripIndices.push_back(restartVal);
+		} 
+		else 
+		{
+			//-1 index indicates next strip
+			stripIndices.push_back(-1);
+			accountForNegatives++;
+			numSeparateStrips++;
+		}
+
+		// Update last face info
+		tLastFace.m_v0 = tLastFace.m_v1;
+		tLastFace.m_v1 = tLastFace.m_v2;
+		tLastFace.m_v2 = tLastFace.m_v2;
+	}
+	
+	if(bStitchStrips || bRestart)
+		numSeparateStrips = 1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// Stripify()
+//
+//
+// in_indices are the input indices of the mesh to stripify
+// in_cacheSize is the target cache size 
+//
+void NvStripifier::Stripify(const WordVec &in_indices, const int in_cacheSize, 
+							const int in_minStripLength, const unsigned short maxIndex, 
+							NvStripInfoVec &outStrips, NvFaceInfoVec& outFaceList)
+{
+	meshJump = 0.0f;
+	bFirstTimeResetPoint = true; //used in FindGoodResetPoint()
+
+	//the number of times to run the experiments
+	int numSamples = 10;
+	
+	//the cache size, clamped to one
+	if ( in_cacheSize - CACHE_INEFFICIENCY < 1 ) cacheSize = 1;
+	else cacheSize = in_cacheSize - CACHE_INEFFICIENCY;
+	
+	minStripLength = in_minStripLength;  //this is the strip size threshold below which we dump the strip into a list
+	
+	indices = in_indices;
+	
+	// build the stripification info
+	NvFaceInfoVec allFaceInfos;
+	NvEdgeInfoVec allEdgeInfos;
+	
+	BuildStripifyInfo(allFaceInfos, allEdgeInfos, maxIndex);
+	
+	NvStripInfoVec allStrips;
+
+	// stripify
+	FindAllStrips(allStrips, allFaceInfos, allEdgeInfos, numSamples);
+
+	//split up the strips into cache friendly pieces, optimize them, then dump these into outStrips
+	SplitUpStripsAndOptimize(allStrips, outStrips, allEdgeInfos, outFaceList);
+
+	//clean up
+	for(size_t i = 0; i < allStrips.size(); i++)
+	{
+		delete allStrips[i];
+	}
+	
+	for (size_t i = 0; i < allEdgeInfos.size(); i++)
+	{
+		NvEdgeInfo *info = allEdgeInfos[i];
+		while (info != NULL)
+		{
+			NvEdgeInfo *next = (size_t(info->m_v0) == i ? info->m_nextV0 : info->m_nextV1);
+			info->Unref();
+			info = next;
+		}
+	}
+	
+}
+
+
+bool NvStripifier::IsDegenerate(const NvFaceInfo* face)
+{
+	if(face->m_v0 == face->m_v1)
+		return true;
+	else if(face->m_v0 == face->m_v2)
+		return true;
+	else if(face->m_v1 == face->m_v2)
+		return true;
+	else
+		return false;
+}
+
+bool NvStripifier::IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2)
+{
+	if(v0 == v1)
+		return true;
+	else if(v0 == v2)
+		return true;
+	else if(v1 == v2)
+		return true;
+	else
+		return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// SplitUpStripsAndOptimize()
+//
+// Splits the input vector of strips (allBigStrips) into smaller, cache friendly pieces, then
+//  reorders these pieces to maximize cache hits
+// The final strips are output through outStrips
+//
+void NvStripifier::SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips,
+                                            NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList)
+{
+	int threshold = cacheSize;
+	NvStripInfoVec tempStrips;
+	
+	//split up strips into threshold-sized pieces
+	for(size_t i = 0; i < allStrips.size(); i++)
+	{
+		NvStripInfo* currentStrip;
+		NvStripStartInfo startInfo(NULL, NULL, false);
+	
+		int actualStripSize = 0;
+		for(size_t j = 0; j < allStrips[i]->m_faces.size(); ++j)
+		{
+			if( !IsDegenerate(allStrips[i]->m_faces[j]) )
+				actualStripSize++;
+		}
+		
+		if(actualStripSize /*allStrips[i]->m_faces.size()*/ > threshold)
+		{
+			
+			int numTimes    = actualStripSize /*allStrips[i]->m_faces.size()*/ / threshold;
+			int numLeftover = actualStripSize /*allStrips[i]->m_faces.size()*/ % threshold;
+
+			int degenerateCount = 0;
+			int j;
+			for(j = 0; j < numTimes; j++)
+			{
+				currentStrip = new NvStripInfo(startInfo, 0, -1);
+				
+				int faceCtr = j*threshold + degenerateCount;
+				bool bFirstTime = true;
+				while(faceCtr < threshold+(j*threshold)+degenerateCount)
+				{
+					if(IsDegenerate(allStrips[i]->m_faces[faceCtr]))
+					{
+						degenerateCount++;
+						
+						//last time or first time through, no need for a degenerate
+						if( (((faceCtr + 1) != threshold+(j*threshold)+degenerateCount) ||
+							 ((j == numTimes - 1) && (numLeftover < 4) && (numLeftover > 0))) && 
+							 !bFirstTime)
+						{
+							currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
+						}
+						else
+						{
+							//but, we do need to delete the degenerate, if it's marked fake, to avoid leaking
+							if(allStrips[i]->m_faces[faceCtr]->m_bIsFake)
+							{
+								delete allStrips[i]->m_faces[faceCtr], allStrips[i]->m_faces[faceCtr] = NULL;
+							}
+							++faceCtr;
+						}
+					}
+					else
+					{
+						currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
+						bFirstTime = false;
+					}
+				}
+				/*
+				for(int faceCtr = j*threshold; faceCtr < threshold+(j*threshold); faceCtr++)
+				{
+					currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr]);
+				}
+				*/
+				if(j == numTimes - 1) //last time through
+				{
+					if( (numLeftover < 4) && (numLeftover > 0) ) //way too small
+					{
+						//just add to last strip
+						int ctr = 0;
+						while(ctr < numLeftover)
+						{
+							IsDegenerate( allStrips[i]->m_faces[faceCtr] ) ? ++degenerateCount : ++ctr;
+							currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
+						}
+						numLeftover = 0;
+					}
+				}
+				tempStrips.push_back(currentStrip);
+			}
+			
+			int leftOff = j * threshold + degenerateCount;
+			
+			if(numLeftover != 0)
+			{
+				currentStrip = new NvStripInfo(startInfo, 0, -1);   
+				
+				int ctr = 0;
+				bool bFirstTime = true;
+				while(ctr < numLeftover)
+				{
+					if( !IsDegenerate(allStrips[i]->m_faces[leftOff]) )
+					{
+						ctr++;
+						bFirstTime = false;
+						currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
+					}
+					else if(!bFirstTime)
+						currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
+					else
+					{
+						//don't leak
+						if(allStrips[i]->m_faces[leftOff]->m_bIsFake)
+						{
+							delete allStrips[i]->m_faces[leftOff], allStrips[i]->m_faces[leftOff] = NULL;
+						}
+
+						leftOff++;
+					}
+				}
+				/*
+				for(int k = 0; k < numLeftover; k++)
+				{
+					currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
+				}
+				*/
+				
+				tempStrips.push_back(currentStrip);
+			}
+		}
+		else
+		{
+			//we're not just doing a tempStrips.push_back(allBigStrips[i]) because
+			// this way we can delete allBigStrips later to free the memory
+			currentStrip = new NvStripInfo(startInfo, 0, -1);
+			
+			for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++)
+				currentStrip->m_faces.push_back(allStrips[i]->m_faces[j]);
+			
+			tempStrips.push_back(currentStrip);
+		}
+	}
+
+	//add small strips to face list
+	NvStripInfoVec tempStrips2;
+	RemoveSmallStrips(tempStrips, tempStrips2, outFaceList);
+	
+	outStrips.clear();
+	//screw optimization for now
+//	for(i = 0; i < tempStrips.size(); ++i)
+//    outStrips.push_back(tempStrips[i]);
+	
+	if(tempStrips2.size() != 0)
+	{
+		//Optimize for the vertex cache
+		VertexCache* vcache = new VertexCache(cacheSize);
+		
+		float bestNumHits = -1.0f;
+		float numHits;
+		int bestIndex = -1;
+		//bool done = false;
+		
+		int firstIndex = 0;
+		float minCost = 10000.0f;
+		
+		for(size_t i = 0; i < tempStrips2.size(); i++)
+		{
+			int numNeighbors = 0;
+			
+			//find strip with least number of neighbors per face
+			for(size_t j = 0; j < tempStrips2[i]->m_faces.size(); j++)
+			{
+				numNeighbors += NumNeighbors(tempStrips2[i]->m_faces[j], edgeInfos);
+			}
+			
+			float currCost = (float)numNeighbors / (float)tempStrips2[i]->m_faces.size();
+			if(currCost < minCost)
+			{
+				minCost = currCost;
+				firstIndex = i;
+			}
+		}
+		
+		UpdateCacheStrip(vcache, tempStrips2[firstIndex]);
+		outStrips.push_back(tempStrips2[firstIndex]);
+		
+		tempStrips2[firstIndex]->visited = true;
+		
+		bool bWantsCW = (tempStrips2[firstIndex]->m_faces.size() % 2) == 0;
+
+		//this n^2 algo is what slows down stripification so much....
+		// needs to be improved
+		while(1)
+		{
+			bestNumHits = -1.0f;
+			
+			//find best strip to add next, given the current cache
+			for(size_t i = 0; i < tempStrips2.size(); i++)
+			{
+				if(tempStrips2[i]->visited)
+					continue;
+
+				numHits = CalcNumHitsStrip(vcache, tempStrips2[i]);
+				if(numHits > bestNumHits)
+				{
+					bestNumHits = numHits;
+					bestIndex = i;
+				}
+				else if(numHits >= bestNumHits)
+				{
+					//check previous strip to see if this one requires it to switch polarity
+					NvStripInfo *strip = tempStrips2[i];
+					int nStripFaceCount = strip->m_faces.size();
+					
+					NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
+					
+					// If there is a second face, reorder vertices such that the
+					// unique vertex is first
+					if (nStripFaceCount > 1)
+					{
+						int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
+						if (nUnique == tFirstFace.m_v1)
+						{
+							SWAP(tFirstFace.m_v0, tFirstFace.m_v1);
+						}
+						else if (nUnique == tFirstFace.m_v2)
+						{
+							SWAP(tFirstFace.m_v0, tFirstFace.m_v2);
+						}
+						
+						// If there is a third face, reorder vertices such that the
+						// shared vertex is last
+						if (nStripFaceCount > 2)
+						{
+							int nShared0, nShared1;
+							GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1);
+							if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) )
+							{
+								SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
+							}
+						}
+					}
+						
+					// Check CW/CCW ordering
+					if (bWantsCW == IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
+					{
+						//I like this one!
+						bestIndex = i;
+					}
+				}
+			}
+			
+			if(bestNumHits == -1.0f)
+				break;
+			tempStrips2[bestIndex]->visited = true;
+			UpdateCacheStrip(vcache, tempStrips2[bestIndex]);
+			outStrips.push_back(tempStrips2[bestIndex]);
+			bWantsCW = (tempStrips2[bestIndex]->m_faces.size() % 2 == 0) ? bWantsCW : !bWantsCW;
+		}
+		
+		delete vcache;	
+	}
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// UpdateCacheStrip()
+//
+// Updates the input vertex cache with this strip's vertices
+//
+void NvStripifier::UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip)
+{
+	for(size_t i = 0; i < strip->m_faces.size(); ++i)
+	{
+		if(!vcache->InCache(strip->m_faces[i]->m_v0))
+			vcache->AddEntry(strip->m_faces[i]->m_v0);
+		
+		if(!vcache->InCache(strip->m_faces[i]->m_v1))
+			vcache->AddEntry(strip->m_faces[i]->m_v1);
+		
+		if(!vcache->InCache(strip->m_faces[i]->m_v2))
+			vcache->AddEntry(strip->m_faces[i]->m_v2);
+	}
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// UpdateCacheFace()
+//
+// Updates the input vertex cache with this face's vertices
+//
+void NvStripifier::UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face)
+{
+	if(!vcache->InCache(face->m_v0))
+		vcache->AddEntry(face->m_v0);
+		
+	if(!vcache->InCache(face->m_v1))
+		vcache->AddEntry(face->m_v1);
+		
+	if(!vcache->InCache(face->m_v2))
+		vcache->AddEntry(face->m_v2);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// CalcNumHitsStrip()
+//
+// returns the number of cache hits per face in the strip
+//
+float NvStripifier::CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip)
+{
+	int numHits = 0;
+	int numFaces = 0;
+	
+	for(size_t i = 0; i < strip->m_faces.size(); i++)
+	{
+		if(vcache->InCache(strip->m_faces[i]->m_v0))
+			++numHits;
+		
+		if(vcache->InCache(strip->m_faces[i]->m_v1))
+			++numHits;
+		
+		if(vcache->InCache(strip->m_faces[i]->m_v2))
+			++numHits;
+		
+		numFaces++;
+	}
+	
+	return ((float)numHits / (float)numFaces);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// CalcNumHitsFace()
+//
+// returns the number of cache hits in the face
+//
+int NvStripifier::CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face)
+{
+	int numHits = 0;
+
+	if(vcache->InCache(face->m_v0))
+		numHits++;
+		
+	if(vcache->InCache(face->m_v1))
+		numHits++;
+		
+	if(vcache->InCache(face->m_v2))
+		numHits++;
+		
+	return numHits;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// NumNeighbors()
+//
+// Returns the number of neighbors that this face has
+//
+int NvStripifier::NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec)
+{
+	int numNeighbors = 0;
+	
+	if(FindOtherFace(edgeInfoVec, face->m_v0, face->m_v1, face) != NULL)
+	{
+		numNeighbors++;
+	}
+	
+	if(FindOtherFace(edgeInfoVec, face->m_v1, face->m_v2, face) != NULL)
+	{
+		numNeighbors++;
+	}
+	
+	if(FindOtherFace(edgeInfoVec, face->m_v2, face->m_v0, face) != NULL)
+	{
+		numNeighbors++;
+	}
+	
+	return numNeighbors;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// AvgStripSize()
+//
+// Finds the average strip size of the input vector of strips
+//
+float NvStripifier::AvgStripSize(const NvStripInfoVec &strips){
+	int sizeAccum = 0;
+	int numStrips = strips.size();
+	for (int i = 0; i < numStrips; i++){
+		NvStripInfo *strip = strips[i];
+		sizeAccum += strip->m_faces.size();
+		sizeAccum -= strip->m_numDegenerates;
+	}
+	return ((float)sizeAccum) / ((float)numStrips);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// FindAllStrips()
+//
+// Does the stripification, puts output strips into vector allStrips
+//
+// Works by setting runnning a number of experiments in different areas of the mesh, and
+//  accepting the one which results in the longest strips.  It then accepts this, and moves
+//  on to a different area of the mesh.  We try to jump around the mesh some, to ensure that
+//  large open spans of strips get generated.
+//
+void NvStripifier::FindAllStrips(NvStripInfoVec &allStrips,
+								 NvFaceInfoVec &allFaceInfos,
+								 NvEdgeInfoVec &allEdgeInfos,
+								 int numSamples){
+	// the experiments
+	int experimentId = 0;
+	int stripId      = 0;
+	bool done        = false;
+
+	int loopCtr = 0;
+	
+	while (!done)
+	{
+		loopCtr++;
+		
+		//
+		// PHASE 1: Set up numSamples * numEdges experiments
+		//
+		NvStripInfoVec *experiments = new NvStripInfoVec [numSamples * 6];
+		int experimentIndex = 0;
+		std::set   <NvFaceInfo*>  resetPoints;
+		for (int i = 0; i < numSamples; i++)
+		{
+			
+			// Try to find another good reset point.
+			// If there are none to be found, we are done
+			NvFaceInfo *nextFace = FindGoodResetPoint(allFaceInfos, allEdgeInfos);
+			if (nextFace == NULL){
+				done = true;
+				break;
+			}
+			// If we have already evaluated starting at this face in this slew
+			// of experiments, then skip going any further
+			else if (resetPoints.find(nextFace) != resetPoints.end()){
+				continue;
+			}
+			
+			// trying it now...
+			resetPoints.insert(nextFace);
+			
+			// otherwise, we shall now try experiments for starting on the 01,12, and 20 edges
+			assert(nextFace->m_stripId < 0);
+			
+			// build the strip off of this face's 0-1 edge
+			NvEdgeInfo *edge01 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1);
+			NvStripInfo *strip01 = new NvStripInfo(NvStripStartInfo(nextFace, edge01, true), stripId++, experimentId++);
+			experiments[experimentIndex++].push_back(strip01);
+			
+			// build the strip off of this face's 1-0 edge
+			NvEdgeInfo *edge10 = FindEdgeInfo(allEdgeInfos, nextFace->m_v0, nextFace->m_v1);
+			NvStripInfo *strip10 = new NvStripInfo(NvStripStartInfo(nextFace, edge10, false), stripId++, experimentId++);
+			experiments[experimentIndex++].push_back(strip10);
+			
+			// build the strip off of this face's 1-2 edge
+			NvEdgeInfo *edge12 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2);
+			NvStripInfo *strip12 = new NvStripInfo(NvStripStartInfo(nextFace, edge12, true), stripId++, experimentId++);
+			experiments[experimentIndex++].push_back(strip12);
+			
+			// build the strip off of this face's 2-1 edge
+			NvEdgeInfo *edge21 = FindEdgeInfo(allEdgeInfos, nextFace->m_v1, nextFace->m_v2);
+			NvStripInfo *strip21 = new NvStripInfo(NvStripStartInfo(nextFace, edge21, false), stripId++, experimentId++);
+			experiments[experimentIndex++].push_back(strip21);
+			
+			// build the strip off of this face's 2-0 edge
+			NvEdgeInfo *edge20 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0);
+			NvStripInfo *strip20 = new NvStripInfo(NvStripStartInfo(nextFace, edge20, true), stripId++, experimentId++);
+			experiments[experimentIndex++].push_back(strip20);
+			
+			// build the strip off of this face's 0-2 edge
+			NvEdgeInfo *edge02 = FindEdgeInfo(allEdgeInfos, nextFace->m_v2, nextFace->m_v0);
+			NvStripInfo *strip02 = new NvStripInfo(NvStripStartInfo(nextFace, edge02, false), stripId++, experimentId++);
+			experiments[experimentIndex++].push_back(strip02);
+		}
+		
+		//
+		// PHASE 2: Iterate through that we setup in the last phase
+		// and really build each of the strips and strips that follow to see how
+		// far we get
+		//
+		int numExperiments = experimentIndex;
+		for (int i = 0; i < numExperiments; i++){
+			
+			// get the strip set
+			
+			// build the first strip of the list
+			experiments[i][0]->Build(allEdgeInfos, allFaceInfos);
+			int experimentId = experiments[i][0]->m_experimentId;
+			
+			NvStripInfo *stripIter = experiments[i][0];
+			NvStripStartInfo startInfo(NULL, NULL, false);
+			while (FindTraversal(allFaceInfos, allEdgeInfos, stripIter, startInfo)){
+				
+				// create the new strip info
+				stripIter = new NvStripInfo(startInfo, stripId++, experimentId);
+				
+				// build the next strip
+				stripIter->Build(allEdgeInfos, allFaceInfos);
+				
+				// add it to the list
+				experiments[i].push_back(stripIter);
+			}
+		}
+		
+		//
+		// Phase 3: Find the experiment that has the most promise
+		//
+		int bestIndex = 0;
+		double bestValue = 0;
+		for (int i = 0; i < numExperiments; i++)
+		{
+			const float avgStripSizeWeight = 1.0f;
+			//const float numTrisWeight      = 0.0f;
+			const float numStripsWeight    = 0.0f;
+			float avgStripSize = AvgStripSize(experiments[i]);
+			float numStrips    = (float) experiments[i].size();
+			float value        = avgStripSize * avgStripSizeWeight + (numStrips * numStripsWeight);
+			//float value = 1.f / numStrips;
+			//float value = numStrips * avgStripSize;
+				
+			if (value > bestValue)
+			{
+				bestValue = value;
+				bestIndex = i;
+			}
+		}
+
+		//
+		// Phase 4: commit the best experiment of the bunch
+		//
+		CommitStrips(allStrips, experiments[bestIndex]);
+		
+		// and destroy all of the others
+		for (int i = 0; i < numExperiments; i++)
+		{
+			if (i != bestIndex)
+			{
+				int numStrips = experiments[i].size();
+				for (int j = 0; j < numStrips; j++)
+				{
+					NvStripInfo* currStrip = experiments[i][j];
+					//delete all bogus faces in the experiments
+					for (size_t k = 0; k < currStrip->m_faces.size(); ++k)
+					{
+						if(currStrip->m_faces[k]->m_bIsFake)
+						{
+							delete currStrip->m_faces[k], currStrip->m_faces[k] = NULL;
+						}
+					}
+					delete currStrip, currStrip = NULL, experiments[i][j] = NULL;
+				}
+			}
+		}
+		
+		// delete the array that we used for all experiments
+		delete [] experiments;
+  }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// CountRemainingTris()
+//
+// This will count the number of triangles left in the
+// strip list starting at iter and finishing up at end
+//
+int NvStripifier::CountRemainingTris(std::list<NvStripInfo*>::iterator iter,
+											std::list<NvStripInfo*>::iterator  end){
+	int count = 0;
+	while (iter != end){
+		count += (*iter)->m_faces.size();
+		iter++;
+	}
+	return count;
+}
+
diff --git a/NifExport/NvTriStrip/NvTriStripObjects.h b/NifExport/NvTriStrip/NvTriStripObjects.h
new file mode 100644
index 0000000000000000000000000000000000000000..32d90f805e18ec6e0d0e843568137639cb71b86e
--- /dev/null
+++ b/NifExport/NvTriStrip/NvTriStripObjects.h
@@ -0,0 +1,248 @@
+
+#ifndef NV_TRISTRIP_OBJECTS_H
+#define NV_TRISTRIP_OBJECTS_H
+
+#include <assert.h>
+#include <vector>
+#include <list>
+#include "VertexCache.h"
+
+//Wrap these types in a namespace
+namespace NvTriStrip {
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Types defined for stripification
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+struct MyVertex {
+	float x, y, z;
+	float nx, ny, nz;
+};
+
+typedef MyVertex MyVector;
+
+struct MyFace {
+	int v1, v2, v3;
+	float nx, ny, nz;
+};
+
+
+class NvFaceInfo {
+public:
+	
+	// vertex indices
+	NvFaceInfo(int v0, int v1, int v2, bool bIsFake = false){
+		m_v0 = v0; m_v1 = v1; m_v2 = v2;
+		m_stripId      = -1;
+		m_testStripId  = -1;
+		m_experimentId = -1;
+		m_bIsFake = bIsFake;
+	}
+	
+	// data members are left public
+	int   m_v0, m_v1, m_v2;
+	int   m_stripId;      // real strip Id
+	int   m_testStripId;  // strip Id in an experiment
+	int   m_experimentId; // in what experiment was it given an experiment Id?
+	bool  m_bIsFake;      //if true, will be deleted when the strip it's in is deleted
+};
+
+// nice and dumb edge class that points knows its
+// indices, the two faces, and the next edge using
+// the lesser of the indices
+class NvEdgeInfo {
+public:
+	
+	// constructor puts 1 ref on us
+	NvEdgeInfo (int v0, int v1){
+		m_v0       = v0;
+		m_v1       = v1;
+		m_face0    = NULL;
+		m_face1    = NULL;
+		m_nextV0   = NULL;
+		m_nextV1   = NULL;
+		
+		// we will appear in 2 lists.  this is a good
+		// way to make sure we delete it the second time
+		// we hit it in the edge infos
+		m_refCount = 2;    
+		
+	}
+	
+	// ref and unref
+	void Unref () { if (--m_refCount == 0) delete this; }
+	
+	// data members are left public
+	unsigned int m_refCount;
+	NvFaceInfo  *m_face0, *m_face1;
+	int          m_v0, m_v1;
+	NvEdgeInfo  *m_nextV0, *m_nextV1;
+};
+
+
+// This class is a quick summary of parameters used
+// to begin a triangle strip.  Some operations may
+// want to create lists of such items, so they were
+// pulled out into a class
+class NvStripStartInfo {
+public:
+	NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){
+		m_startFace    = startFace;
+		m_startEdge    = startEdge;
+		m_toV1         = toV1;
+	}
+	NvFaceInfo    *m_startFace;
+	NvEdgeInfo    *m_startEdge;
+	bool           m_toV1;      
+};
+
+
+typedef std::vector<NvFaceInfo*>     NvFaceInfoVec;
+typedef std::list  <NvFaceInfo*>     NvFaceInfoList;
+typedef std::list  <NvFaceInfoVec*>  NvStripList;
+typedef std::vector<NvEdgeInfo*>     NvEdgeInfoVec;
+
+typedef std::vector<short> WordVec;
+typedef std::vector<int> IntVec;
+typedef std::vector<MyVertex> MyVertexVec;
+typedef std::vector<MyFace> MyFaceVec;
+
+template<class T> 
+inline void SWAP(T& first, T& second) 
+{
+	T temp = first;
+	first = second;
+	second = temp;
+}
+
+// This is a summary of a strip that has been built
+class NvStripInfo {
+public:
+	
+	// A little information about the creation of the triangle strips
+	NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) :
+	  m_startInfo(startInfo)
+	{
+		m_stripId      = stripId;
+		m_experimentId = experimentId;
+		visited = false;
+		m_numDegenerates = 0;
+	}
+
+	// This is an experiment if the experiment id is >= 0
+	inline bool IsExperiment () const { return m_experimentId >= 0; }
+	  
+	inline bool IsInStrip (const NvFaceInfo *faceInfo) const 
+	{
+		if(faceInfo == NULL)
+			return false;
+		  
+		return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId);
+	}
+	  
+	bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos);
+	  
+	// take the given forward and backward strips and combine them together
+	void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward);
+	  
+	//returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec
+	bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face);
+	  
+	// mark the triangle as taken by this strip
+	bool IsMarked    (NvFaceInfo *faceInfo);
+	void MarkTriangle(NvFaceInfo *faceInfo);
+	  
+	// build the strip
+	void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos);
+	  
+	// public data members
+	NvStripStartInfo m_startInfo;
+	NvFaceInfoVec    m_faces;
+	int              m_stripId;
+	int              m_experimentId;
+	  
+	bool visited;
+
+	int m_numDegenerates;
+};
+
+typedef std::vector<NvStripInfo*>    NvStripInfoVec;
+
+
+//The actual stripifier
+class NvStripifier {
+public:
+	
+	// Constructor
+	NvStripifier();
+	~NvStripifier();
+	
+	//the target vertex cache size, the structure to place the strips in, and the input indices
+	void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength, 
+				  const unsigned short maxIndex, NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces);
+	void CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, const bool bStitchStrips, unsigned int& numSeparateStrips, const bool bRestart, const unsigned int restartVal);
+	
+	static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB);
+	//static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB);
+	static void GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1);
+
+	static bool IsDegenerate(const NvFaceInfo* face);
+	static bool IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2);
+	
+protected:
+	
+	WordVec indices;
+	int cacheSize;
+	int minStripLength;
+	float meshJump;
+	bool bFirstTimeResetPoint;
+	
+	/////////////////////////////////////////////////////////////////////////////////
+	//
+	// Big mess of functions called during stripification
+	//
+	/////////////////////////////////////////////////////////////////////////////////
+
+	//********************
+	bool IsMoneyFace(const NvFaceInfo& face);
+	bool FaceContainsIndex(const NvFaceInfo& face, const unsigned int index);
+
+	bool IsCW(NvFaceInfo *faceInfo, int v0, int v1);
+	bool NextIsCW(const int numIndices);
+	
+	static int  GetNextIndex(const WordVec &indices, NvFaceInfo *face);
+	static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1);
+	static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo);
+	NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
+	
+	void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples);
+	void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList);
+	void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList);
+	
+	bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo);
+	int  CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator  end);
+	
+	void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips);
+	
+	float AvgStripSize(const NvStripInfoVec &strips);
+	int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
+	
+	void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip);
+	void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face);
+	float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip);
+	int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face);
+	int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec);
+	
+	void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const unsigned short maxIndex);
+	bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos);
+	
+	// let our strip info classes and the other classes get
+	// to these protected stripificaton methods if they want
+	friend class NvStripInfo;
+};
+
+} //End namespace
+
+#endif
\ No newline at end of file
diff --git a/NifExport/NvTriStrip/VertexCache.cpp b/NifExport/NvTriStrip/VertexCache.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a5f0badf87912a01768d94f737eba4e6b13b87fe
--- /dev/null
+++ b/NifExport/NvTriStrip/VertexCache.cpp
@@ -0,0 +1,87 @@
+
+
+#include "VertexCache.h"
+using namespace NvTriStrip;
+
+VertexCache::VertexCache()
+{
+  VertexCache(16);
+}
+
+
+VertexCache::VertexCache(int size)
+{
+  numEntries = size;
+
+  entries = new int[numEntries];
+
+  for(int i = 0; i < numEntries; i++)
+    entries[i] = -1;
+}
+
+
+VertexCache::~VertexCache()
+{
+  delete[] entries;
+}
+
+
+int VertexCache::At(int index)
+{
+  return entries[index];
+}
+
+
+void VertexCache::Set(int index, int value)
+{
+  entries[index] = value;
+}
+
+
+void VertexCache::Clear()
+{
+  for(int i = 0; i < numEntries; i++)
+    entries[i] = -1;
+}
+
+void VertexCache::Copy(VertexCache* inVcache)
+{
+  for(int i = 0; i < numEntries; i++)
+  {
+    inVcache->Set(i, entries[i]);
+  }
+}
+
+bool VertexCache::InCache(int entry)
+{
+  bool returnVal = false;
+
+  for(int i = 0; i < numEntries; i++)
+  {
+    if(entries[i] == entry)
+    {
+      returnVal = true;
+      break;
+    }
+  }
+
+  return returnVal;
+}
+
+
+int VertexCache::AddEntry(int entry)
+{
+  int removed;
+
+  removed = entries[numEntries - 1];
+
+  //push everything right one
+  for(int i = numEntries - 2; i >= 0; i--)
+  {
+    entries[i + 1] = entries[i];
+  }
+
+  entries[0] = entry;
+
+  return removed;
+}
diff --git a/NifExport/NvTriStrip/VertexCache.h b/NifExport/NvTriStrip/VertexCache.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcb075a92e225d435205ae98eacc663aba415121
--- /dev/null
+++ b/NifExport/NvTriStrip/VertexCache.h
@@ -0,0 +1,31 @@
+  
+#ifndef VERTEX_CACHE_H
+
+#define VERTEX_CACHE_H
+
+namespace NvTriStrip {
+
+class VertexCache
+{
+	
+public:
+	VertexCache(int size);
+	VertexCache();
+	~VertexCache();	
+	bool InCache(int entry);
+	int AddEntry(int entry);
+	void Clear();
+	void Copy(VertexCache* inVcache) ;
+	int At(int index);
+	void Set(int index, int value);
+
+private:
+
+  int *entries;
+  int numEntries;
+
+};
+
+} //End namespace
+
+#endif
diff --git a/NifExport/Strips.cpp b/NifExport/Strips.cpp
index 019af369d72126e0754998f1a18d510a0b4a4785..b418cdab7b5c9228f24c9a6da08e705a31a127ae 100755
--- a/NifExport/Strips.cpp
+++ b/NifExport/Strips.cpp
@@ -1,5 +1,7 @@
 #include "pch.h"
 
+#include "NvTriStrip/NvTriStrip.h"
+using namespace NvTriStrip;
 /*
 using namespace triangle_stripper;
 
@@ -85,7 +87,7 @@ void Exporter::strippify(FaceGroup &grp)
 		data[i * 3 + 2] = grp.faces[i][2];
 	}
 	
-	PrimitiveGroup * groups = 0;
+   PrimitiveGroup * groups = 0;
 	unsigned short numGroups = 0;
 	
 	// GF 3+
diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp
index 6f98c6f9df0c95059d6b83d2ae3d1c68fe66f150..2a356c03e3f3ee8bdbaf852b52293a02d170e308 100755
--- a/NifExport/Util.cpp
+++ b/NifExport/Util.cpp
@@ -228,7 +228,7 @@ bool Exporter::removeUnreferencedBones(NiNodeRef node)
    {
       NiAVObjectRef& child = (*itr);
       bool childRemove = false;
-      if (child->IsDerivedType(NiNode::TypeConst()))
+      if (child->IsDerivedType(NiNode::TYPE))
       {
          childRemove = removeUnreferencedBones(StaticCast<NiNode>(child));
       }
diff --git a/NifFurniture/NifFurniture.cpp b/NifFurniture/NifFurniture.cpp
index d80d111c3d61954d9b88d6b1a53d4f9edd9d3efd..d4f3d5ca06d0383dd412bb140c9d7f11967696ab 100755
--- a/NifFurniture/NifFurniture.cpp
+++ b/NifFurniture/NifFurniture.cpp
@@ -252,7 +252,12 @@ int NifFurnitureMarker::Display(TimeValue t, INode* inode, ViewExp *vpt, int fla
     Material *mtl = gw->getMaterial();
 
     DWORD rlim = gw->getRndLimits();
-    gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY|GW_BACKCULL);
+
+    DWORD newrlim = GW_WIREFRAME|GW_BACKCULL;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
+    newrlim |= GW_EDGES_ONLY;
+#endif
+    gw->setRndLimits(newrlim);
     
 	GetMat(t, inode, vpt, m);
 	m.Scale(mFlip);
diff --git a/NifImport/ImportAnimation.cpp b/NifImport/ImportAnimation.cpp
index adb3da66a79a47618ecf54e0310c57e79abbf4aa..6e0e27a4fd766e88bc0fdf5f677fa4dc4c8fc117 100644
--- a/NifImport/ImportAnimation.cpp
+++ b/NifImport/ImportAnimation.cpp
@@ -11,7 +11,7 @@ HISTORY:
 *>	Copyright (c) 2006, All Rights Reserved.
 **********************************************************************/
 #include "stdafx.h"
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7
 #  include <IFrameTagManager.h>
 #endif
 #include <notetrck.h>
@@ -181,7 +181,7 @@ void NifImporter::ClearAnimation()
 {
    if (clearAnimation)
    {
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7
       if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
 
          int n = tagMgr->GetTagCount();
@@ -430,7 +430,7 @@ bool NifImporter::AddNoteTracks(float time, string name, string target, NiTextKe
       }
 
       if (addTimeTags) {
-#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
+#if VERSION_3DSMAX >= ((7000<<16)+(15<<8)+0) // Version 7
          if (IFrameTagManager *tagMgr = (IFrameTagManager*)GetCOREInterface(FRAMETAGMANAGER_INTERFACE)) {
             for (vector<StringKey>::iterator itr=textKeys.begin(); itr != textKeys.end(); ++itr) {
                tagMgr->CreateNewTag(const_cast<TCHAR*>((*itr).data.c_str()), TimeToFrame(time + (*itr).time), 0, FALSE);
@@ -539,7 +539,7 @@ bool AnimationImport::GetTransformData(ControllerLink& lnk, string name, NiKeyfr
 
          if (npoints > 3)
          {
-            NiKeyframeDataRef data = CreateBlock("NiKeyframeData");
+            NiKeyframeDataRef data = CreateNiObject<NiKeyframeData>();
             data->SetRotateType(QUADRATIC_KEY);
             data->SetTranslateType(QUADRATIC_KEY);
             data->SetScaleType(QUADRATIC_KEY);
diff --git a/NifImport/ImportCollision.cpp b/NifImport/ImportCollision.cpp
index 53d6aed4e49f323fe33889b4fa812a6c00b86680..22f17b314ff46c0e4e04edbbd42cc951976e3e51 100644
--- a/NifImport/ImportCollision.cpp
+++ b/NifImport/ImportCollision.cpp
@@ -56,10 +56,10 @@ bool NifImporter::ImportCollision(NiNodeRef node)
    if (collObj)
    {
       CollisionImport ci(*this);
-      if (INode *inode = FindINode(gi, collObj->GetParent()))
+      if (INode *inode = FindINode(gi, collObj->GetTarget()))
       {
          NiObjectRef body = collObj->GetBody();
-         if (body->IsDerivedType(bhkRigidBody::TypeConst()))
+         if (body->IsDerivedType(bhkRigidBody::TYPE))
          {
             ci.ImportRigidBody(bhkRigidBodyRef(body), inode);
          }
@@ -113,15 +113,15 @@ bool CollisionImport::ImportRigidBody(bhkRigidBodyRef body, INode* node)
 bool CollisionImport::ImportShape(bhkRigidBodyRef body, bhkShapeRef shape, INode* parent)
 {
    INode *shapeNode = NULL;
-   if (shape->IsDerivedType(bhkCapsuleShape::TypeConst()))
+   if (shape->IsDerivedType(bhkCapsuleShape::TYPE))
    {
       shapeNode = ImportCapsule(body, bhkCapsuleShapeRef(shape), parent);
    }
-   else if (shape->IsDerivedType(bhkSphereShape::TypeConst()))
+   else if (shape->IsDerivedType(bhkSphereShape::TYPE))
    {
       shapeNode = ImportSphere(body, bhkSphereShapeRef(shape), parent);
    }
-   else if (shape->IsDerivedType(bhkConvexVerticesShape::TypeConst()))
+   else if (shape->IsDerivedType(bhkConvexVerticesShape::TYPE))
    {
       shapeNode = ImportConvexVertices(body, bhkConvexVerticesShapeRef(shape), parent);
    }
diff --git a/NifImport/ImportLights.cpp b/NifImport/ImportLights.cpp
index a48feb36f440ee9ee66f247d99c056ec2e1da35d..ed67650a86f94d7ef238d12ee1468c2b32782561 100644
--- a/NifImport/ImportLights.cpp
+++ b/NifImport/ImportLights.cpp
@@ -72,7 +72,7 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights)
       GenLight *ob = NULL;
       NiLightRef& light = (*itr);
 
-      if (light->IsSameType(NiPointLight::TypeConst())){
+      if (light->IsSameType(NiPointLight::TYPE)){
          ob = CreateLight(gi, light, OMNI_LIGHT);
          NiPointLightRef ptLight = light;
          float c = ptLight->GetConstantAttenuation();
@@ -88,12 +88,12 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights)
             ob->SetDecayType(2);
             ob->SetAtten(0, ATTEN_START, 4.0f/(l*l));
          }
-      } else if (light->IsSameType(NiDirectionalLight::TypeConst())){
+      } else if (light->IsSameType(NiDirectionalLight::TYPE)){
          ob = CreateLight(gi, light, DIR_LIGHT);
-      } else if (light->IsSameType(NiAmbientLight::TypeConst())){
+      } else if (light->IsSameType(NiAmbientLight::TYPE)){
          ob = CreateLight(gi, light, OMNI_LIGHT);
          ob->SetAmbientOnly(TRUE);
-      } else if (light->IsSameType(NiSpotLight::TypeConst())){
+      } else if (light->IsSameType(NiSpotLight::TYPE)){
          ob = CreateLight(gi, light, FSPOT_LIGHT);
       }
       if (INode *n = gi->CreateObjectNode(ob)) {
@@ -108,7 +108,7 @@ bool NifImporter::ImportLights(vector<NiLightRef> lights)
          Quat q = TOQUAT(rot.AsQuaternion());
 
          PosRotScaleNode(n, p, q, scale, prsDefault);
-         n->Hide(light->GetHidden() ? TRUE : FALSE);
+         n->Hide(light->GetVisibility() ? FALSE : TRUE );
       }
       ok = true;
    }
diff --git a/NifImport/ImportMeshAndSkin.cpp b/NifImport/ImportMeshAndSkin.cpp
index 5a9094512a4d2415b24926101d75febc99e7707a..552a76fd3f841da4f5c2053760ab7dfa08d971da 100644
--- a/NifImport/ImportMeshAndSkin.cpp
+++ b/NifImport/ImportMeshAndSkin.cpp
@@ -173,7 +173,7 @@ bool NifImporter::ImportMesh(ImpNode *node, TriObject *o, NiTriBasedGeomRef triG
    if (INode *parent = GetNode(triGeom->GetParent()))
       parent->AttachChild(inode, 1);
 
-   inode->Hide(triGeom->GetHidden() ? TRUE : FALSE);
+   inode->Hide(triGeom->GetVisibility() ? FALSE : TRUE);
 
    if (enableAutoSmooth){
       mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE);
@@ -278,7 +278,7 @@ bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeom
       Matrix44 transform = (*itr)->GetLocalTransform();
       //Apply the transformations
       if (transform != Matrix44::IDENTITY) {
-         for ( uint i = 0; i < subverts.size(); ++i )
+         for ( unsigned int i = 0; i < subverts.size(); ++i )
             subverts[i] = transform * subverts[i];
       }
       vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) );
@@ -334,7 +334,7 @@ bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeom
       vector<Vector3> subnorms = triGeomData->GetNormals();
       Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation();
       if (rotation != Matrix44::IDENTITY) {
-         for ( uint i = 0; i < subnorms.size(); ++i )
+         for ( unsigned int i = 0; i < subnorms.size(); ++i )
             subnorms[i] = rotation * subnorms[i];
       }
       if (!subnorms.empty())
@@ -410,7 +410,7 @@ bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeom
       // attach child
       if (INode *parent = GetNode((*itr)->GetParent()))
          parent->AttachChild(inode, 1);
-      inode->Hide((*itr)->GetHidden() ? TRUE : FALSE);
+      inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE);
    }
    if (removeDegenerateFaces)
       mesh.RemoveDegenerateFaces();
@@ -600,8 +600,10 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom, int v_sta
       //   and the value always seems to be 4 anyway.  I'd also this be more dynamic than hard coded numbers
       //   but I cant figure out the correct values to pass the scripting engine from here so I'm giving up.
       int numWeightsPerVertex = 4;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
       IParamBlock2 *params = skinMod->GetParamBlockByID(2/*advanced*/);
       params->SetValue(0x7/*bone_Limit*/, 0, numWeightsPerVertex);
+#endif
 
       // Can get some truly bizarre animations without this in MAX with Civ4 Leaderheads
 #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+
@@ -655,6 +657,13 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom, int v_sta
          }
       }
 
+      tnode->EvalWorldState(0);
+      skinMod->DisableModInViews();
+      skinMod->EnableModInViews();
+#if VERSION_3DSMAX < ((5000<<16)+(15<<8)+0) // Version 4
+      gi->SetCommandPanelTaskMode(TASK_MODE_MODIFY);
+      gi->SelectNode(tnode);
+#endif
       // Assign the weights 
       for (vector<VertexHolder>::iterator itr=vertexHolders.begin(), end=vertexHolders.end(); itr != end; ++itr){
          VertexHolder& h = (*itr);
diff --git a/NifImport/ImportMtlAndTex.cpp b/NifImport/ImportMtlAndTex.cpp
index 2a7e698181f7ca136aa10608c90e9084f61fed61..7664618449e377588d3b7d907336987e03d69fb6 100644
--- a/NifImport/ImportMtlAndTex.cpp
+++ b/NifImport/ImportMtlAndTex.cpp
@@ -27,7 +27,7 @@ Texmap* NifImporter::CreateTexture(TexDesc& desc)
 {
    BitmapManager *bmpMgr = TheManager;
    if (NiSourceTextureRef texSrc = desc.source){
-      string filename = texSrc->GetExternalFileName();
+      string filename = texSrc->GetTextureFileName();
       if (bmpMgr->CanImport(filename.c_str())){
          BitmapTex *bmpTex = NewDefaultBitmapTex();
          string name = texSrc->GetName();
@@ -83,13 +83,13 @@ Texmap* NifImporter::CreateTexture(TexDesc& desc)
 StdMat2 *NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObject)
 {
    // Texture
-   NiMaterialPropertyRef matRef = avObject->GetPropertyByType(NiMaterialProperty::TypeConst());
+   NiMaterialPropertyRef matRef = avObject->GetPropertyByType(NiMaterialProperty::TYPE);
    if (matRef != NULL){
-      NiTexturingPropertyRef texRef = avObject->GetPropertyByType(NiTexturingProperty::TypeConst());
-      NiWireframePropertyRef wireRef = avObject->GetPropertyByType(NiWireframeProperty::TypeConst());
-      NiAlphaPropertyRef alphaRef = avObject->GetPropertyByType(NiAlphaProperty::TypeConst());
-      NiStencilPropertyRef stencilRef = avObject->GetPropertyByType(NiStencilProperty::TypeConst());
-      NiShadePropertyRef shadeRef = avObject->GetPropertyByType(NiShadeProperty::TypeConst());
+      NiTexturingPropertyRef texRef = avObject->GetPropertyByType(NiTexturingProperty::TYPE);
+      NiWireframePropertyRef wireRef = avObject->GetPropertyByType(NiWireframeProperty::TYPE);
+      NiAlphaPropertyRef alphaRef = avObject->GetPropertyByType(NiAlphaProperty::TYPE);
+      NiStencilPropertyRef stencilRef = avObject->GetPropertyByType(NiStencilProperty::TYPE);
+      NiShadePropertyRef shadeRef = avObject->GetPropertyByType(NiShadeProperty::TYPE);
 
       StdMat2 *m = NewDefaultStdMat();
       m->SetName(matRef->GetName().c_str());
@@ -120,7 +120,7 @@ StdMat2 *NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avO
                m->SetWire(value);
             }
             if (stencilRef != NULL) {
-               if (stencilRef->GetDrawMode() == 3 /*DRAW_BOTH*/) {
+				if (stencilRef->GetFaceDrawMode() == DRAW_BOTH) {
                   BOOL value = TRUE;
                   m->SetTwoSided(value);
                }
@@ -267,22 +267,22 @@ bool NifImporter::ImportCiv4Shader(ImpNode *node, NiAVObjectRef avObject, StdMat
       setMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable);
    }
    if (NiAlphaPropertyRef alphaRef = SelectFirstObjectOfType<NiAlphaProperty>(props)) {
-      int TestRef = alphaRef->GetAlphaTestThreshold();
-      int srcBlend = alphaRef->GetSourceBlendMode(); 
-      int destBlend = alphaRef->GetDestBlendMode();
-      int TestMode = alphaRef->GetTestMode();
-      bool AlphaTestEnable = alphaRef->GetAlphaTest();     
-      bool NoSorter = !alphaRef->GetAlphaSort();
-      bool alphaBlend = alphaRef->GetAlphaBlend();
+      int TestRef = alphaRef->GetTestThreshold();
+      int srcBlend = alphaRef->GetSourceBlendFunc(); 
+      int destBlend = alphaRef->GetSourceBlendFunc ();
+      int TestMode = alphaRef->GetTestFunc();
+      bool AlphaTestEnable = alphaRef->GetTestState();     
+      bool NoSorter = !alphaRef->GetTriangleSortMode();
+      bool alphaBlend = alphaRef->GetBlendState();
       int alphaMode = 1;
 
       if (!alphaBlend) {
          alphaMode = 1; // none
-      } else if (srcBlend == NiAlphaProperty::BM_SRC_ALPHA && destBlend == NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA) {
+      } else if (srcBlend == NiAlphaProperty::BF_SRC_ALPHA && destBlend == NiAlphaProperty::BF_ONE_MINUS_SRC_ALPHA) {
          alphaMode = 0; // standard or automatic?
-      } else if (srcBlend == NiAlphaProperty::BM_ONE && destBlend == NiAlphaProperty::BM_ONE) {
+      } else if (srcBlend == NiAlphaProperty::BF_ONE && destBlend == NiAlphaProperty::BF_ONE) {
          alphaMode = 3;
-      } else if (srcBlend == NiAlphaProperty::BM_ZERO && destBlend == NiAlphaProperty::BM_SRC_COLOR) {
+      } else if (srcBlend == NiAlphaProperty::BF_ZERO && destBlend == NiAlphaProperty::BF_SRC_COLOR) {
          alphaMode = 4;
       } else {
          alphaMode = 5;
diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp
index e5f5b6013701b8d302197b154fe4a8018b03b23c..960529025b3eeafcc3d03fb239c5abf81221c7df 100644
--- a/NifImport/ImportSkeleton.cpp
+++ b/NifImport/ImportSkeleton.cpp
@@ -36,7 +36,7 @@ struct NiNodeNameEquivalence : public NumericStringEquivalence
 void GoToSkeletonBindPosition(vector<NiNodeRef>& blocks)
 {
    //Send all skeleton roots to bind position
-   for (uint i = 0; i < blocks.size(); ++i) {
+   for (unsigned int i = 0; i < blocks.size(); ++i) {
       NiNodeRef node = blocks[i];
       if ( node != NULL && node->IsSkeletonRoot() ) {
          node->GoToSkeletonBindPosition();
@@ -481,6 +481,7 @@ INode *NifImporter::CreateBone(const string& name, Point3 startPos, Point3 endPo
          if (INode *n = result.n)
          {
             n->SetName(const_cast<TCHAR*>(name.c_str()));
+
             float len = Length(endPos-startPos);
             float width = max(minBoneWidth, min(maxBoneWidth, len * boneWidthToLengthRatio));
             if (Object* o = n->GetObjectRef())
@@ -573,7 +574,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse)
       vector<NiAVObjectRef> children = node->GetChildren();
       vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children);
 
-      NiAVObject::CollisionType cType = node->GetCollision();
+      NiAVObject::CollisionType cType = node->GetCollisionMode();
       if (children.empty() && name=="Bounding Box")
          return;
 
@@ -654,13 +655,13 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse)
       {
          bool isDummy = ( (uncontrolledDummies && !HasControllerRef(ctrlCount, name))
                      || (!dummyNodeMatches.empty() && wildmatch(dummyNodeMatches, name))
-                     || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TypeConst()))
+                     || (convertBillboardsToDummyNodes && node->IsDerivedType(NiBillboardNode::TYPE))
                       );
          if (wildmatch("Camera*", name)) {
             if (enableCameras) {
                if (bone = CreateCamera(name)) {
                   PosRotScaleNode(bone, p, q, scale, prs);
-                  bone->Hide(node->GetHidden() ? TRUE : FALSE);
+                  bone->Hide(node->GetVisibility() ? FALSE : TRUE);
                }
             }
          }else if (isDummy && createNubsForBones)
@@ -668,7 +669,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse)
          else if (bone = CreateBone(name, p, pp, zAxis))
          {
             PosRotScaleNode(bone, p, q, scale, prs);
-            bone->Hide(node->GetHidden() ? TRUE : FALSE);
+            bone->Hide(node->GetVisibility() ? FALSE : TRUE);
          }
          if (bone)
          {
diff --git a/NifImport/MaxNifImport.cpp b/NifImport/MaxNifImport.cpp
index b1903c756fbd535f75290e4a368008dcae95275f..3202ae7290329f8287df814c488e3dcfede55dd5 100644
--- a/NifImport/MaxNifImport.cpp
+++ b/NifImport/MaxNifImport.cpp
@@ -38,6 +38,13 @@ class MaxNifImport : public SceneImport {
 		unsigned int	Version();					// Version number * 100 (i.e. v3.01 = 301)
 		void			   ShowAbout(HWND hWnd);		// Show DLL's "About..." box
 		int				DoImport(const TCHAR *name,ImpInterface *i,Interface *gi, BOOL suppressPrompts=FALSE);	// Import file
+
+      SDK_RESERVED_METHOD(1); // russom 02/26/01
+      SDK_RESERVED_METHOD(2); // russom 02/26/01
+      SDK_RESERVED_METHOD(3); // russom 02/26/01
+      SDK_RESERVED_METHOD(4); // russom 02/26/01
+      SDK_RESERVED_METHOD(5); // russom 02/26/01
+      SDK_RESERVED_METHOD(6); // russom 02/26/01
 		
 		//Constructor/Destructor
 		MaxNifImport();
@@ -72,17 +79,7 @@ MaxNifImport::MaxNifImport()
 {
    Interface *gi = GetCOREInterface();
    TCHAR iniName[MAX_PATH];
-   if (gi) {
-      LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
-   } else {
-      GetModuleFileName(NULL, iniName, _countof(iniName));
-      if (LPTSTR fname = PathFindFileName(iniName))
-         fname = NULL;
-      PathAddBackslash(iniName);
-      PathAppend(iniName, "plugcfg");
-      PathAppend(iniName, "MaxNifTools.ini");
-   }
+   GetIniFileName(iniName);
    iniFileName = iniName;
    shortDescription = GetIniValue<TSTR>("System", "ShortDescription", "Netimmerse/Gamebryo", iniFileName.c_str());
    webSite = GetIniValue<TSTR>("System", "Website", "http://www.niftools.org", iniFileName.c_str());
diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp
index a49134caec06d393830119f1854f86b8644b5189..628e43c941eb9f2edfcf66680cfff904241d49b5 100644
--- a/NifImport/NIFImport.cpp
+++ b/NifImport/NIFImport.cpp
@@ -108,8 +108,7 @@ string NifImporter::GetSkeleton(AppSettings *appSettings)
 void NifImporter::LoadIniSettings()
 {
    TCHAR iniName[MAX_PATH];
-   LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-   PathCombine(iniName, pluginDir, "MaxNifTools.ini");
+   GetIniFileName(iniName);
    this->iniFileName = iniName;
    iniFileValid = (-1 != _access(iniName, 0));
 
@@ -283,7 +282,7 @@ bool NifImporter::DoImport()
 
    if (isValid()) {
 
-      if (root->IsDerivedType(NiNode::TypeConst()))
+      if (root->IsDerivedType(NiNode::TYPE))
       {
          NiNodeRef rootNode = root;
 
@@ -317,11 +316,11 @@ bool NifImporter::DoImport()
             }
          }
       }
-      else if (root->IsDerivedType(NiTriShape::TypeConst()))
+      else if (root->IsDerivedType(NiTriShape::TYPE))
       {
          ok |= ImportMesh(NiTriShapeRef(root));
       }
-      else if (root->IsDerivedType(NiTriStrips::TypeConst()))
+      else if (root->IsDerivedType(NiTriStrips::TYPE))
       {
          ok |= ImportMesh(NiTriStripsRef(root));
       }
diff --git a/NifPlugins/DllEntry.cpp b/NifPlugins/DllEntry.cpp
index 3beef1029ce9b0960b4bef717f031f0dd46ffd16..90bc9d0b8afbe9e04cc36889646e0765c68683b6 100644
--- a/NifPlugins/DllEntry.cpp
+++ b/NifPlugins/DllEntry.cpp
@@ -20,6 +20,7 @@ extern ClassDesc2* GetbhkSphereDesc();
 extern ClassDesc2* GetbhkCapsuleDesc();
 extern ClassDesc2* GetbhkRigidBodyModifierDesc();
 extern ClassDesc2* GetbhkBoxDesc();
+extern ClassDesc* GetDDSLibClassDesc();
 
 enum ClassDescType
 {
@@ -66,19 +67,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
 
 void InitializeLibSettings()
 {
-   Interface *gi = GetCOREInterface();
    TCHAR iniName[MAX_PATH];
-   if (gi) {
-      LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR);
-      PathCombine(iniName, pluginDir, "MaxNifTools.ini");
-   } else {
-      GetModuleFileName(NULL, iniName, _countof(iniName));
-      if (LPTSTR fname = PathFindFileName(iniName))
-         *fname = 0;
-      PathAddBackslash(iniName);
-      PathAppend(iniName, "plugcfg");
-      PathAppend(iniName, "MaxNifTools.ini");
-   }
+   GetIniFileName(iniName);
    libVersion = GetIniValue("System", "MaxSDKVersion", libVersion, iniName);
    if (libVersion == 0)
       libVersion = VERSION_3DSMAX;
@@ -110,6 +100,9 @@ void InitializeLibSettings()
       classDescEnabled[CD_KFExport] = true;
       classDescriptions[nClasses++] = GetKfExportDesc();
    }
+#ifdef GAME_VER
+   classDescriptions[nClasses++] = (ClassDesc2 *)GetDDSLibClassDesc();
+#endif
 }
 
 // This function returns a string that describes the DLL and where the user
diff --git a/NifPlugins_VC80.sln b/NifPlugins_VC80.sln
index edd13349535598cd4864b47e04fce8c518c16618..edda3730668d56307b01ab76fadddfd962443d89 100644
--- a/NifPlugins_VC80.sln
+++ b/NifPlugins_VC80.sln
@@ -1,6 +1,6 @@
 Microsoft Visual Studio Solution File, Format Version 9.00
 # Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NIFlib", "..\niflib\niflib.vcproj", "{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Niflib", "..\niflib\niflib.vcproj", "{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{50B67748-0DFB-45B0-BF1F-E80135EE3823}"
 	ProjectSection(SolutionItems) = preProject
@@ -17,6 +17,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NifPlugins", "NifPlugins_VC
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug - gmax|Win32 = Debug - gmax|Win32
+		Debug - gmax|x64 = Debug - gmax|x64
+		Debug - Max 4.2|Win32 = Debug - Max 4.2|Win32
+		Debug - Max 4.2|x64 = Debug - Max 4.2|x64
+		Debug - Max 4|Win32 = Debug - Max 4|Win32
+		Debug - Max 4|x64 = Debug - Max 4|x64
 		Debug - Max 5|Win32 = Debug - Max 5|Win32
 		Debug - Max 5|x64 = Debug - Max 5|x64
 		Debug - Max 6|Win32 = Debug - Max 6|Win32
@@ -27,6 +33,12 @@ Global
 		Debug - Max 8|x64 = Debug - Max 8|x64
 		Debug - Max 9|Win32 = Debug - Max 9|Win32
 		Debug - Max 9|x64 = Debug - Max 9|x64
+		Release - gmax|Win32 = Release - gmax|Win32
+		Release - gmax|x64 = Release - gmax|x64
+		Release - Max 4.2|Win32 = Release - Max 4.2|Win32
+		Release - Max 4.2|x64 = Release - Max 4.2|x64
+		Release - Max 4|Win32 = Release - Max 4|Win32
+		Release - Max 4|x64 = Release - Max 4|x64
 		Release - Max 5|Win32 = Release - Max 5|Win32
 		Release - Max 5|x64 = Release - Max 5|x64
 		Release - Max 6|Win32 = Release - Max 6|Win32
@@ -39,36 +51,63 @@ Global
 		Release - Max 9|x64 = Release - Max 9|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.Build.0 = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|x64.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.Build.0 = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|x64.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.Build.0 = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|x64.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.Build.0 = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|x64.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.Build.0 = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|x64.ActiveCfg = Debug - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.Build.0 = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|x64.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.Build.0 = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|x64.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.Build.0 = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|x64.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.Build.0 = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|x64.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.ActiveCfg = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.Build.0 = Release - PCH|Win32
-		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|x64.ActiveCfg = Release - PCH|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - gmax|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - gmax|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - gmax|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4.2|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4.2|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4.2|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 4|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 5|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 6|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 7|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 8|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.ActiveCfg = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|Win32.Build.0 = Debug - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Debug - Max 9|x64.ActiveCfg = Debug - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - gmax|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - gmax|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - gmax|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4.2|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4.2|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4.2|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 4|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 5|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 6|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 7|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 8|x64.ActiveCfg = Release - DLL|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.ActiveCfg = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|Win32.Build.0 = Release - Static|Win32
+		{19FD8EE6-79CC-4BAC-9744-D9573BE47C7E}.Release - Max 9|x64.ActiveCfg = Release - DLL|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - gmax|Win32.ActiveCfg = Debug - gmax|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - gmax|Win32.Build.0 = Debug - gmax|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - gmax|x64.ActiveCfg = Debug - Max 5|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4.2|Win32.ActiveCfg = Debug - Max 4.2|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4.2|Win32.Build.0 = Debug - Max 4.2|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4.2|x64.ActiveCfg = Debug - Max 4.2|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4|Win32.ActiveCfg = Debug - Max 4|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4|Win32.Build.0 = Debug - Max 4|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 4|x64.ActiveCfg = Debug - Max 5|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 5|Win32.ActiveCfg = Debug - Max 5|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 5|Win32.Build.0 = Debug - Max 5|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 5|x64.ActiveCfg = Debug - Max 5|Win32
@@ -84,6 +123,15 @@ Global
 		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 9|Win32.ActiveCfg = Debug - Max 9|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 9|Win32.Build.0 = Debug - Max 9|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Debug - Max 9|x64.ActiveCfg = Debug - Max 9|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - gmax|Win32.ActiveCfg = Release - gmax|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - gmax|Win32.Build.0 = Release - gmax|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - gmax|x64.ActiveCfg = Release - Max 5|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4.2|Win32.ActiveCfg = Release - Max 4.2|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4.2|Win32.Build.0 = Release - Max 4.2|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4.2|x64.ActiveCfg = Release - Max 4.2|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4|Win32.ActiveCfg = Release - Max 4|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4|Win32.Build.0 = Release - Max 4|Win32
+		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 4|x64.ActiveCfg = Release - Max 5|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 5|Win32.ActiveCfg = Release - Max 5|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 5|Win32.Build.0 = Release - Max 5|Win32
 		{466F2D3E-2663-4583-A05C-128683677617}.Release - Max 5|x64.ActiveCfg = Release - Max 5|Win32
diff --git a/NifPlugins_VC80.vcproj b/NifPlugins_VC80.vcproj
index 0de9f6b8547c9877b76aeddce8612f31bfb9b0fc..97163782a2ea766a75941241020acd1a023710c1 100644
--- a/NifPlugins_VC80.vcproj
+++ b/NifPlugins_VC80.vcproj
@@ -50,7 +50,7 @@
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				InlineFunctionExpansion="2"
 				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK"
 				StringPooling="true"
 				ExceptionHandling="2"
 				RuntimeLibrary="0"
@@ -78,18 +78,638 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax6\plugins\NifPlugins.dlu"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
+				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				SetChecksum="true"
+				BaseAddress="0x16860000"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug - Max 6|Win32"
+			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
+			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)NifPlugins.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				Optimization="0"
+				InlineFunctionExpansion="2"
+				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK"
+				GeneratePreprocessedFile="0"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				ForceConformanceInForLoopScope="false"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
+				Culture="1033"
+				AdditionalIncludeDirectories=".\NifCommon"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
 				OutputFile="C:\3dsmax6\plugins\NifPlugins.dlu"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
+				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
+				SubSystem="2"
+				BaseAddress="0x16860000"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release - Max 7|Win32"
+			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
+			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+				CommandLine=""
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)NifPlugins.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				InlineFunctionExpansion="2"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED;NIFLIB_STATIC_LINK"
+				StringPooling="true"
+				ExceptionHandling="2"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				ForceConformanceInForLoopScope="false"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG;NIFPLUGINS"
+				Culture="1033"
+				AdditionalIncludeDirectories=".\NifCommon"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib"
+				AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
+				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				SetChecksum="true"
+				BaseAddress="0x16860000"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug - Max 7|Win32"
+			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
+			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)NifPlugins.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				Optimization="0"
+				InlineFunctionExpansion="2"
+				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED;NIFLIB_STATIC_LINK"
+				GeneratePreprocessedFile="0"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				ForceConformanceInForLoopScope="false"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
+				Culture="1033"
+				AdditionalIncludeDirectories=".\NifCommon"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
+				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
+				SubSystem="2"
+				BaseAddress="0x16860000"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release - Max 8|Win32"
+			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
+			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+				CommandLine=""
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)NifPlugins.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				InlineFunctionExpansion="2"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED;NIFLIB_STATIC_LINK"
+				StringPooling="true"
+				ExceptionHandling="2"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				ForceConformanceInForLoopScope="false"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG;NIFPLUGINS"
+				Culture="1033"
+				AdditionalIncludeDirectories=".\NifCommon"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
+				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				SetChecksum="true"
+				BaseAddress="0x16860000"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug - Max 8|Win32"
+			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
+			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)NifPlugins.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				Optimization="0"
+				InlineFunctionExpansion="2"
+				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED;NIFLIB_STATIC_LINK"
+				GeneratePreprocessedFile="0"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				ForceConformanceInForLoopScope="false"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
+				Culture="1033"
+				AdditionalIncludeDirectories=".\NifCommon"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
+				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
+				SubSystem="2"
+				BaseAddress="0x16860000"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug - Max 5|Win32"
+			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
+			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="1"
+				TypeLibraryName="$(OutDir)NifPlugins.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				Optimization="0"
+				InlineFunctionExpansion="2"
+				AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK"
+				GeneratePreprocessedFile="0"
+				MinimalRebuild="true"
+				ExceptionHandling="2"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				ForceConformanceInForLoopScope="false"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+				DisableSpecificWarnings="4244;4018"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
+				Culture="1033"
+				AdditionalIncludeDirectories=".\NifCommon"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalOptions="/MACHINE:I386"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
 				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				SetChecksum="true"
 				BaseAddress="0x16860000"
 			/>
 			<Tool
@@ -115,23 +735,25 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
-				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
+				CommandLine=""
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - Max 6|Win32"
+			Name="Release - Max 5|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			UseOfMFC="0"
 			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
+				CommandLine=""
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
@@ -141,7 +763,7 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				PreprocessorDefinitions="_DEBUG"
+				PreprocessorDefinitions="NDEBUG"
 				MkTypLibCompatible="true"
 				SuppressStartupBanner="true"
 				TargetEnvironment="1"
@@ -150,15 +772,13 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
-				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE"
-				GeneratePreprocessedFile="0"
-				MinimalRebuild="true"
+				AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK"
+				StringPooling="true"
 				ExceptionHandling="2"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
 				ForceConformanceInForLoopScope="false"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
@@ -172,7 +792,7 @@
 			/>
 			<Tool
 				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
+				PreprocessorDefinitions="NDEBUG;NIFPLUGINS"
 				Culture="1033"
 				AdditionalIncludeDirectories=".\NifCommon"
 			/>
@@ -182,16 +802,19 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflibd.lib"
-				OutputFile="C:\3dsmax6\plugins\NifPlugins.dlu"
-				LinkIncremental="2"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu"
+				LinkIncremental="1"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax6\maxsdk\lib;..\niflib\lib"
-				IgnoreDefaultLibraryNames="msvcrtd.lib"
+				AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
 				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				SetChecksum="true"
 				BaseAddress="0x16860000"
 			/>
 			<Tool
@@ -217,25 +840,24 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
-				CommandLine=""
+				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - Max 7|Win32"
+			Name="Debug - Max 9|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			UseOfMFC="0"
 			ATLMinimizesCRunTimeLibraryUsage="false"
-			WholeProgramOptimization="0"
+			CharacterSet="2"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
-				CommandLine=""
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
@@ -245,7 +867,7 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				PreprocessorDefinitions="NDEBUG"
+				PreprocessorDefinitions="_DEBUG"
 				MkTypLibCompatible="true"
 				SuppressStartupBanner="true"
 				TargetEnvironment="1"
@@ -254,13 +876,15 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
+				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
-				StringPooling="true"
-				ExceptionHandling="2"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
+				AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED;NIFLIB_STATIC_LINK"
+				GeneratePreprocessedFile="0"
+				MinimalRebuild="true"
+				ExceptionHandling="1"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
 				ForceConformanceInForLoopScope="false"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
@@ -274,7 +898,7 @@
 			/>
 			<Tool
 				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG;NIFPLUGINS"
+				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
 				Culture="1033"
 				AdditionalIncludeDirectories=".\NifCommon"
 			/>
@@ -284,18 +908,16 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
-				OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu"
-				LinkIncremental="1"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu"
+				LinkIncremental="2"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib"
+				AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
 				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				SetChecksum="true"
 				BaseAddress="0x16860000"
 			/>
 			<Tool
@@ -321,23 +943,25 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
-				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
+				CommandLine=""
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - Max 7|Win32"
+			Name="Release - Max 9|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			UseOfMFC="0"
 			ATLMinimizesCRunTimeLibraryUsage="false"
+			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
+				CommandLine=""
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
@@ -347,7 +971,7 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				PreprocessorDefinitions="_DEBUG"
+				PreprocessorDefinitions="NDEBUG"
 				MkTypLibCompatible="true"
 				SuppressStartupBanner="true"
 				TargetEnvironment="1"
@@ -356,15 +980,13 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
-				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED"
-				GeneratePreprocessedFile="0"
-				MinimalRebuild="true"
+				AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED;NIFLIB_STATIC_LINK"
+				StringPooling="true"
 				ExceptionHandling="2"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
 				ForceConformanceInForLoopScope="false"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
@@ -378,7 +1000,7 @@
 			/>
 			<Tool
 				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG;NIFPLUGINS"
+				PreprocessorDefinitions="NDEBUG;NIFPLUGINS"
 				Culture="1033"
 				AdditionalIncludeDirectories=".\NifCommon"
 			/>
@@ -389,15 +1011,18 @@
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
 				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
-				OutputFile="C:\3dsmax7\plugins\NifPlugins.dlu"
-				LinkIncremental="2"
+				OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu"
+				LinkIncremental="1"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax7\maxsdk\lib;..\niflib\lib"
-				IgnoreDefaultLibraryNames="msvcrtd.lib"
+				AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
 				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				SetChecksum="true"
 				BaseAddress="0x16860000"
 			/>
 			<Tool
@@ -423,11 +1048,11 @@
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
-				CommandLine=""
+				CommandLine="set MaxRootDir=$(TargetDir)\..&#x0D;&#x0A;if exist &quot;%MaxRootDir%\plugcfg&quot; (&#x0D;&#x0A;if not exist &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot; (&#x0D;&#x0A;copy &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;%MaxRootDir%\plugcfg\MaxNifTools.ini&quot;&#x0D;&#x0A;)&#x0D;&#x0A;)&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifPlugins_Readme.txt&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(ProjectDir)MaxNifTools.ini&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;xcopy /D /Y /I &quot;$(TargetPath)&quot; &quot;$(OutDir)&quot;&#x0D;&#x0A;"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - Max 8|Win32"
+			Name="Release - Max 4|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
@@ -461,8 +1086,8 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
+				AdditionalIncludeDirectories="C:\3dsmax4\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK"
 				StringPooling="true"
 				ExceptionHandling="2"
 				RuntimeLibrary="0"
@@ -490,11 +1115,12 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
-				OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax4\plugins\NifPlugins.dlu"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib"
+				AdditionalLibraryDirectories="C:\3dsmax4\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
@@ -531,7 +1157,7 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - Max 8|Win32"
+			Name="Debug - Max 4|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
@@ -564,8 +1190,8 @@
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED"
+				AdditionalIncludeDirectories="C:\3dsmax4\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -578,6 +1204,7 @@
 				SuppressStartupBanner="true"
 				DebugInformationFormat="3"
 				CompileAs="0"
+				DisableSpecificWarnings="4244;4018"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -595,11 +1222,11 @@
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
 				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
-				OutputFile="C:\3dsmax8\plugins\NifPlugins.dlu"
+				OutputFile="C:\3dsmax4\plugins\NifPlugins.dlu"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax8\maxsdk\lib;..\niflib\lib"
-				IgnoreDefaultLibraryNames="msvcrtd.lib"
+				AdditionalLibraryDirectories="C:\3dsmax4\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
@@ -633,7 +1260,7 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - Max 5|Win32"
+			Name="Debug - gmax|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
@@ -666,8 +1293,8 @@
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE"
+				AdditionalIncludeDirectories="C:\gmax12\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;GAME_VER;NIFLIB_STATIC_LINK"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -698,11 +1325,11 @@
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
 				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
-				OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu"
+				OutputFile="C:\gmax12\plugins\NifPlugins.dlu"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib"
-				IgnoreDefaultLibraryNames="msvcrtd.lib"
+				AdditionalLibraryDirectories="C:\gmax12\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
@@ -736,7 +1363,7 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - Max 5|Win32"
+			Name="Release - gmax|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
@@ -770,12 +1397,12 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax5\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES"
+				AdditionalIncludeDirectories="C:\gmax12\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;GAME_VER;NIFLIB_STATIC_LINK"
 				StringPooling="true"
-				ExceptionHandling="2"
+				ExceptionHandling="1"
 				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
+				EnableFunctionLevelLinking="false"
 				ForceConformanceInForLoopScope="false"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderThrough="$(ProjectDir)NifPlugins\pch.h"
@@ -799,11 +1426,12 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
-				OutputFile="C:\3dsmax5\plugins\NifPlugins.dlu"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\gmax12\plugins\NifPlugins.dlu"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax5\maxsdk\lib;..\niflib\lib"
+				AdditionalLibraryDirectories="C:\gmax12\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
@@ -840,7 +1468,7 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - Max 9|Win32"
+			Name="Debug - Max 4.2|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
@@ -873,8 +1501,8 @@
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				Optimization="0"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;USE_BIPED"
+				AdditionalIncludeDirectories="C:\3dsmax42\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_UNSUPPORTED_CODE;NIFLIB_STATIC_LINK"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="true"
 				ExceptionHandling="2"
@@ -887,6 +1515,7 @@
 				SuppressStartupBanner="true"
 				DebugInformationFormat="3"
 				CompileAs="0"
+				DisableSpecificWarnings="4244;4018"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -903,12 +1532,12 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib_debug.lib"
-				OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax42\plugins\NifPlugins.dlu"
 				LinkIncremental="2"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib"
-				IgnoreDefaultLibraryNames="msvcrtd.lib"
+				AdditionalLibraryDirectories="C:\3dsmax42\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
@@ -942,7 +1571,7 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - Max 9|Win32"
+			Name="Release - Max 4.2|Win32"
 			OutputDirectory="$(SolutionDir)Staging\$(ConfigurationName)\"
 			IntermediateDirectory="$(SolutionDir)Temp\$(ProjectName)\$(ConfigurationName)\"
 			ConfigurationType="2"
@@ -976,8 +1605,8 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/LD /Zm200 /FI&quot;$(ProjectDir)NifPlugins\pch.h&quot;"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="C:\3dsmax9\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;USE_BIPED"
+				AdditionalIncludeDirectories="C:\3dsmax42\maxsdk\include;..\niflib\include;..\niflib;.\NifCommon"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS;_USE_MATH_DEFINES;NIFLIB_STATIC_LINK"
 				StringPooling="true"
 				ExceptionHandling="2"
 				RuntimeLibrary="0"
@@ -1005,11 +1634,12 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/MACHINE:I386"
-				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib niflib.lib"
-				OutputFile="C:\3dsmax9\plugins\NifPlugins.dlu"
+				AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib shlwapi.lib core.lib geom.lib gfx.lib mesh.lib maxutil.lib maxscrpt.lib paramblk2.lib bmm.lib"
+				OutputFile="C:\3dsmax42\plugins\NifPlugins.dlu"
 				LinkIncremental="1"
 				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="C:\3dsmax9\maxsdk\lib;..\niflib\lib"
+				AdditionalLibraryDirectories="C:\3dsmax42\maxsdk\lib;..\niflib\lib"
+				IgnoreDefaultLibraryNames=""
 				ModuleDefinitionFile=".\NifPlugins\NifPlugins.def"
 				GenerateDebugInformation="true"
 				ProgramDatabaseFile="$(IntDir)\$(TargetName).pdb"
@@ -1104,6 +1734,762 @@
 					>
 				</File>
 			</Filter>
+			<Filter
+				Name="dds"
+				>
+				<File
+					RelativePath=".\NifProps\dds\dds.cpp"
+					>
+					<FileConfiguration
+						Name="Release - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCLCompilerTool"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath=".\NifProps\dds\dds.h"
+					>
+					<FileConfiguration
+						Name="Release - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath=".\NifProps\dds\dds.rc"
+					>
+					<FileConfiguration
+						Name="Release - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCResourceCompilerTool"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath=".\NifProps\dds\ddsres.h"
+					>
+					<FileConfiguration
+						Name="Release - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath=".\NifProps\dds\dxtlib.h"
+					>
+					<FileConfiguration
+						Name="Release - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+				</File>
+				<File
+					RelativePath=".\NifProps\dds\veroverrides.h"
+					>
+					<FileConfiguration
+						Name="Release - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 6|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 7|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 8|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 5|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 9|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - gmax|Win32"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Debug - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+					<FileConfiguration
+						Name="Release - Max 4.2|Win32"
+						ExcludedFromBuild="true"
+						>
+						<Tool
+							Name="VCCustomBuildTool"
+						/>
+					</FileConfiguration>
+				</File>
+			</Filter>
 		</Filter>
 		<Filter
 			Name="NifFurniture"
@@ -1216,6 +2602,34 @@
 					>
 				</File>
 			</Filter>
+			<Filter
+				Name="NvTriStrip"
+				>
+				<File
+					RelativePath=".\NifExport\NvTriStrip\NvTriStrip.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NifExport\NvTriStrip\NvTriStrip.h"
+					>
+				</File>
+				<File
+					RelativePath=".\NifExport\NvTriStrip\NvTriStripObjects.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NifExport\NvTriStrip\NvTriStripObjects.h"
+					>
+				</File>
+				<File
+					RelativePath=".\NifExport\NvTriStrip\VertexCache.cpp"
+					>
+				</File>
+				<File
+					RelativePath=".\NifExport\NvTriStrip\VertexCache.h"
+					>
+				</File>
+			</Filter>
 		</Filter>
 		<Filter
 			Name="NifCommon"
@@ -1401,6 +2815,60 @@
 						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
 					/>
 				</FileConfiguration>
+				<FileConfiguration
+					Name="Release - Max 4|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug - Max 4|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug - gmax|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release - gmax|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug - Max 4.2|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release - Max 4.2|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\$(InputName)1.obj"
+						XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+					/>
+				</FileConfiguration>
 			</File>
 			<File
 				RelativePath=".\NifPlugins\NifPlugins.rc"
@@ -1489,6 +2957,54 @@
 						UsePrecompiledHeader="1"
 					/>
 				</FileConfiguration>
+				<FileConfiguration
+					Name="Release - Max 4|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug - Max 4|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug - gmax|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release - gmax|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug - Max 4.2|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release - Max 4.2|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
 			</File>
 			<File
 				RelativePath=".\NifPlugins\pch.h"
diff --git a/NifProps/bhkBoxObj.cpp b/NifProps/bhkBoxObj.cpp
index 9079331290f518ed1cff0ff4ab4e70eb88a9bb38..0415051d85e0b0fcde6d9422bcf18239ae33022e 100644
--- a/NifProps/bhkBoxObj.cpp
+++ b/NifProps/bhkBoxObj.cpp
@@ -798,7 +798,13 @@ int bhkBoxObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags)
    m = inode->GetObjectTM(t);
    gw->setTransform(m);
    DWORD rlim = gw->getRndLimits();
-   gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY|GW_Z_BUFFER);
+
+   DWORD newrlim = GW_WIREFRAME|GW_Z_BUFFER;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
+   newrlim |= GW_EDGES_ONLY;
+#endif
+   gw->setRndLimits(newrlim);
+
    if (inode->Selected()) 
       gw->setColor( LINE_COLOR, GetSelColor());
    else if(!inode->IsFrozen() && !inode->Dependent())
diff --git a/NifProps/bhkCapsuleObj.cpp b/NifProps/bhkCapsuleObj.cpp
index 4e98bcdec76ecb0244e3f3bf0bf56d3ac60c7a44..6fa759a16a8186f1d0cc2f03fdef259dc95974d2 100644
--- a/NifProps/bhkCapsuleObj.cpp
+++ b/NifProps/bhkCapsuleObj.cpp
@@ -680,7 +680,13 @@ int bhkCapsuleObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags
    m = inode->GetObjectTM(t);
    gw->setTransform(m);
    DWORD rlim = gw->getRndLimits();
-   gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY/*|GW_Z_BUFFER*/);
+
+   DWORD newrlim = GW_WIREFRAME/*|GW_Z_BUFFER*/;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
+   newrlim |= GW_EDGES_ONLY;
+#endif
+   gw->setRndLimits(newrlim);
+
    if (inode->Selected()) 
       gw->setColor( LINE_COLOR, GetSelColor());
    else if(!inode->IsFrozen() && !inode->Dependent())
diff --git a/NifProps/bhkRigidBodyModifer.cpp b/NifProps/bhkRigidBodyModifer.cpp
index 48c50f3a99495ef3421fa00f8795cb6a96b6341e..9dd47f86bb74f288463f27f03a8a0c94d1a58f1e 100644
--- a/NifProps/bhkRigidBodyModifer.cpp
+++ b/NifProps/bhkRigidBodyModifer.cpp
@@ -748,7 +748,12 @@ int bhkRigidBodyModifier::Display(TimeValue t, INode* inode, ViewExp *vpt, int f
 	m = inode->GetObjectTM(t);
 	gw->setTransform(m);
 	DWORD rlim = gw->getRndLimits();
-	gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY/*|GW_Z_BUFFER*/);
+
+   DWORD newrlim = GW_WIREFRAME/*|GW_Z_BUFFER*/;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
+   newrlim |= GW_EDGES_ONLY;
+#endif
+   gw->setRndLimits(newrlim);
 
 	//UpdateMesh(t);
    gw->setMaterial(swMtl);
diff --git a/NifProps/bhkSphereObj.cpp b/NifProps/bhkSphereObj.cpp
index f0ac610f62a67db25959e9b78c58999caed858de..89ecd2532e75d72e9c51e6fa699a93cbdb7c9c15 100644
--- a/NifProps/bhkSphereObj.cpp
+++ b/NifProps/bhkSphereObj.cpp
@@ -591,7 +591,13 @@ int bhkSphereObject::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags)
    m = inode->GetObjectTM(t);
    gw->setTransform(m);
    DWORD rlim = gw->getRndLimits();
-   gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY/*|GW_Z_BUFFER*/);
+
+   DWORD newrlim = GW_WIREFRAME/*|GW_Z_BUFFER*/;
+#if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+
+   newrlim |= GW_EDGES_ONLY;
+#endif
+   gw->setRndLimits(newrlim);
+
    if (inode->Selected()) 
       gw->setColor( LINE_COLOR, GetSelColor());
    else if(!inode->IsFrozen() && !inode->Dependent())
diff --git a/NifProps/dds/ConvertColor.h b/NifProps/dds/ConvertColor.h
new file mode 100644
index 0000000000000000000000000000000000000000..c334b4cdc3d7851bf213abad2ca26b902c4d238e
--- /dev/null
+++ b/NifProps/dds/ConvertColor.h
@@ -0,0 +1,349 @@
+#pragma once
+#include "tPixel.h" 
+
+namespace nv
+{
+
+template < class T > inline T Min(const T &x, const T &y)
+{
+    if (x < y)
+        return x;
+    else
+        return y;
+}
+template < class T > inline T Max(const T &x, const T &y)
+{
+    if (x < y)
+        return y;
+    else
+        return x;
+}
+
+
+
+}
+
+
+typedef unsigned short nvhalf;
+
+union nv_half_data 
+{
+    unsigned short bits;
+    struct 
+    {
+        unsigned long m : 10;
+        unsigned long e : 5;
+        unsigned long s : 1;
+    } ieee;
+};
+
+union nv_ieee_single 
+{
+    float f;
+    struct {
+        unsigned long m : 23;
+        unsigned long e : 8;
+        unsigned long s : 1;
+    } ieee;
+};
+
+
+class nvColorConvert
+{
+public:
+
+    void RGBAToFloat(const RGBAImage & srcImage,  
+        fpImage & dstImage);
+
+    void RGBAToFloat(const RGBAMipMappedImage & srcMIPImage,  
+                    fpMipMappedImage & dstMIPImage);
+
+
+    void FloatToRGBA(const fpImage & srcImage,
+        RGBAImage & dstImage);
+
+    void FloatToRGBA(const fpMipMappedImage & srcMIPImage,
+        RGBAMipMappedImage & dstMIPImage);
+
+    fpPixel RGBEtoFloat(int r, int g, int b, int e); 
+
+
+    // photoshop import export
+    float PSSignedToFloat(int pixel, int depth, int plane);
+    float PSUnsignedToFloat(int pixel, int depth);
+
+    int FloatToUnsignedPS(float pixel, int depth);
+    int FloatToSignedPS(float pixel, int depth, int plane);
+
+    // format to float
+    static float UnsignedToFloat(int channel);    // unsigned, 8 bits
+    static float UnsignedToFloat(int channel, int nBits);    // unsigned
+    static float SignedToFloat(int channel);  // 8 bits
+    static float SignedToFloat(int channel, int nBits);
+
+
+    static void RGBAToFloat(int r, int g, int b, int a, fpPixel & fp)
+    {
+        fp.r = UnsignedToFloat(r);
+        fp.g = UnsignedToFloat(g);
+        fp.b = UnsignedToFloat(b);
+        fp.a = UnsignedToFloat(a);
+    }
+
+
+    static void RGBAToFloat( const rgba_t & inColor, fpPixel & fp)
+    {
+
+        fp.r = UnsignedToFloat(inColor.r);
+        fp.g = UnsignedToFloat(inColor.g);
+        fp.b = UnsignedToFloat(inColor.b);
+        fp.a = UnsignedToFloat(inColor.a);
+    }
+
+
+    static void RGBEToFloat(fpPixel & fp, const rgba_t & rgbe);
+    static void RGBEToFloat(float &r, float & g, float & b, const rgba_t & rgbe);
+
+
+
+
+    static float HalfToFloat(nvhalf val) 
+    {
+        nv_half_data h;
+        //h.bits = val.value_bits;
+        h.bits = val;
+        nv_ieee_single sng;
+        sng.ieee.s = h.ieee.s;
+
+        //  handle special cases
+        if ( (h.ieee.e==0) && (h.ieee.m==0) ) 
+        {  // zero
+            sng.ieee.m=0;
+            sng.ieee.e=0;
+        }
+        else if ( (h.ieee.e==0) && (h.ieee.m!=0) ) 
+        {  
+            // denorm -- denorm half will fit in non-denorm single
+            const float half_denorm = (1.0f/16384.0f); // 2^-14
+            float mantissa = ((float)(h.ieee.m)) / 1024.0f;
+            float sgn = (h.ieee.s)? -1.0f :1.0f;
+            sng.f = sgn*mantissa*half_denorm;
+        }
+        else if ( (h.ieee.e==31) && (h.ieee.m==0) )
+        { // infinity
+            sng.ieee.e = 0xff;
+            sng.ieee.m = 0;
+        }
+        else if ( (h.ieee.e==31) && (h.ieee.m!=0) ) 
+        { // NaN
+            sng.ieee.e = 0xff;
+            sng.ieee.m = 1;
+        }
+        else 
+        {
+            sng.ieee.e = h.ieee.e+112;
+            sng.ieee.m = (h.ieee.m << 13);
+        }
+
+        return sng.f;
+    }
+
+
+
+    /// float to format
+    static unsigned long FloatToUnsigned(float channel);  // 8 bits
+    static unsigned long FloatToUnsigned(float channel, int nBits);
+
+    static long FloatToSigned(float channel);  // 8 bits
+    static long FloatToSigned(float channel, int nBits);
+
+
+
+
+    static unsigned long NormalToUnsigned(float inColor )
+    {
+        return FloatToUnsigned(inColor * 0.5f + 0.5f);
+    }
+
+    static unsigned long NormalToUnsigned(float inColor, int nBits )
+    {
+        return FloatToUnsigned(inColor * 0.5f + 0.5f, nBits);
+    }
+
+    static void NormalToRGBA(const fpPixel & inColor, rgba_t & outColor )
+    {
+        outColor.r = (unsigned char)NormalToUnsigned(inColor.r);
+        outColor.g = (unsigned char)NormalToUnsigned(inColor.g);
+        outColor.b = (unsigned char)NormalToUnsigned(inColor.b);
+        outColor.a = (unsigned char)NormalToUnsigned(inColor.a);
+
+    }
+
+    static void FloatToRGBA(const fpPixel & inColor, rgba_t & p )
+    {
+        p.r = (unsigned char)FloatToUnsigned(inColor.r);
+        p.g = (unsigned char)FloatToUnsigned(inColor.g);
+        p.b = (unsigned char)FloatToUnsigned(inColor.b);
+        p.a = (unsigned char)FloatToUnsigned(inColor.a);
+
+    }
+
+    static void FloatToBGRA(const fpPixel & inColor, unsigned long & outColor )
+    {
+        unsigned int r = FloatToUnsigned(inColor.r);
+        unsigned int g = FloatToUnsigned(inColor.g);
+        unsigned int b = FloatToUnsigned(inColor.b);
+        unsigned int a = FloatToUnsigned(inColor.a);
+
+        outColor = (a << 24) | (r << 16) | (g << 8) | b;
+
+    }
+
+
+
+    static void FloatToBGRA(float r, float g, float b, float a, unsigned long & outColor )
+    {
+        unsigned int ri = FloatToUnsigned(r);
+        unsigned int gi = FloatToUnsigned(g);
+        unsigned int bi = FloatToUnsigned(b);
+        unsigned int ai = FloatToUnsigned(a);
+
+        outColor = (ai << 24) | (ri << 16) | (gi << 8) | bi;
+    }
+
+    static void FloatToQ8W8V8U8(const fpPixel & inColor, q8w8v8u8_t & outColor )
+    {
+        outColor.q = (char)FloatToSigned(inColor.r);
+        outColor.v = (char)FloatToSigned(inColor.g);
+        outColor.w = (char)FloatToSigned(inColor.b);
+        outColor.u = (char)FloatToSigned(inColor.a);
+
+    }
+
+
+    static void FloatToU16V16(float u, float v, v16u16_t & outColor )
+    {
+        outColor.u = (short)FloatToSigned(u, 16);
+        outColor.v = (short)FloatToSigned(v, 16);
+    }
+
+
+    static void FloatToR12G12B8(const fpPixel & inColor, r12g12b8_t & outColor )
+    {
+        outColor.r = FloatToUnsigned(inColor.r, 12);
+        outColor.g = FloatToUnsigned(inColor.g, 12);
+        outColor.b = FloatToUnsigned(inColor.b, 8);
+    }
+
+    static void NormalToR12G12B8(const fpPixel & inColor, r12g12b8_t & outColor )
+    {
+        outColor.r = FloatToUnsigned(inColor.r * 0.5f + 0.5f, 12);
+        outColor.g = FloatToUnsigned(inColor.g * 0.5f + 0.5f, 12);
+        outColor.b = FloatToUnsigned(inColor.b * 0.5f + 0.5f, 8);
+    }
+
+
+
+
+    static float FloatToRGBE_Alpha(const fpPixel & fp);
+
+    static void FloatToRGBE(rgba_t & rgbe, const float &r, const float & g, const float & b );
+    static void FloatToRGBE(rgba_t * rgbe, const float &r, const float & g, const float & b );
+
+    static void FloatToRGBE(fpPixel & rgbe, const fpPixel & fp);
+    static void FloatToRGBE(rgba_t & rgbe, const fpPixel & fp);
+
+    static unsigned char FloatToRGBE_DXT3Alpha(const fpPixel & fp);
+
+
+
+    static nvhalf FloatToHalf(float val) 
+    {
+        nv_ieee_single f;
+        f.f = val;
+        nv_half_data h;
+
+        h.ieee.s = f.ieee.s;
+
+        // handle special cases
+
+        //const float half_denorm = (1.0f/16384.0f);
+
+        if ( (f.ieee.e==0) && (f.ieee.m==0) ) 
+        { // zero
+            h.ieee.m = 0;
+            h.ieee.e = 0;
+        }
+        else if ( (f.ieee.e==0) && (f.ieee.m!=0) ) 
+        {  // denorm -- denorm float maps to 0 half
+            h.ieee.m = 0;
+            h.ieee.e = 0;
+        }
+        else if ( (f.ieee.e==0xff) && (f.ieee.m==0) ) 
+        { 
+            // infinity
+            h.ieee.m = 0;
+            h.ieee.e = 31;
+        }
+        else if ( (f.ieee.e==0xff) && (f.ieee.m!=0) ) 
+        { 
+            // NaN
+            h.ieee.m = 1;
+            h.ieee.e = 31;
+        }
+        else 
+        { 
+            // regular number
+            int new_exp = f.ieee.e-127;
+
+            if (new_exp<-24) 
+            { // this maps to 0
+                h.ieee.m = 0;
+                h.ieee.e = 0;
+            }
+
+            if (new_exp<-14) 
+            {
+                // this maps to a denorm
+                h.ieee.e = 0;
+                unsigned int exp_val = (unsigned int) (-14 - new_exp);  // 2^-exp_val
+                switch (exp_val) 
+                {
+                case 0: 
+                    //fprintf(stderr, "ftoh: logical error in denorm creation!\n"); 
+                    h.ieee.m = 0; 
+                    break;
+                case 1: h.ieee.m = 512 + (f.ieee.m>>14); break;
+                case 2: h.ieee.m = 256 + (f.ieee.m>>15); break;
+                case 3: h.ieee.m = 128 + (f.ieee.m>>16); break;
+                case 4: h.ieee.m = 64 + (f.ieee.m>>17); break;
+                case 5: h.ieee.m = 32 + (f.ieee.m>>18); break;
+                case 6: h.ieee.m = 16 + (f.ieee.m>>19); break;
+                case 7: h.ieee.m = 8 + (f.ieee.m>>20); break;
+                case 8: h.ieee.m = 4 + (f.ieee.m>>21); break;
+                case 9: h.ieee.m = 2 + (f.ieee.m>>22); break;
+                case 10: h.ieee.m = 1; break;
+                }
+            }
+            else if (new_exp>15) 
+            { // map this value to infinity
+                h.ieee.m = 0;
+                h.ieee.e = 31;
+            }
+            else 
+            {
+                h.ieee.e = new_exp+15;
+                h.ieee.m = (f.ieee.m >> 13);
+            }
+        }
+
+        return (*(nvhalf*)(&h.bits));
+    }
+
+
+
+};
+
+
+
+
diff --git a/NifProps/dds/dds.cpp b/NifProps/dds/dds.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..85fbc37533f1b41e9549085760678276da747a04
--- /dev/null
+++ b/NifProps/dds/dds.cpp
@@ -0,0 +1,774 @@
+// File ....: dds.cpp
+// ------------------
+// Author...: Sean Palmer
+// Date ....: April 2001
+// Descr....: DDS File I/O Module
+
+//-- Include files
+
+#include <max.h>
+#include <bmmlib.h>
+#include <pixelbuf.h>
+#include "dds.h"
+#include "ddsres.h"
+
+#include <stdio.h>
+
+#include "dxtlib.h"
+
+//extern "C" FILE _iob[3] = {NULL, NULL, NULL};
+
+extern HINSTANCE hInstance;
+
+static FILE* ghFile=NULL;
+
+void WriteDTXnFile(DWORD count, void *buffer)
+{
+  fwrite(buffer, count, 1, ghFile);
+}
+
+void ReadDTXnFile(DWORD count, void *buffer)
+{
+  fread(buffer, count, 1, ghFile);
+}
+
+//-----------------------------------------------------------------------------
+//-- File Class
+
+class File
+{
+public:
+  FILE  *stream;
+  File  (const TCHAR *name, const TCHAR *mode) { stream = _tfopen(name,mode); }
+  ~File () { Close(); } 
+  void Close() { if(stream) fclose(stream); stream = NULL; }
+};
+
+//-----------------------------------------------------------------------------
+// DDS Class Description
+
+class DDSClassDesc : public ClassDesc
+{
+public:
+  int             IsPublic     ()                   { return 1;                }
+  void           *Create       (BOOL loading=FALSE) { return new BitmapIO_DDS; }
+  const TCHAR    *ClassName    ()                   { return GetString(IDS_DDS); }
+  SClass_ID       SuperClassID ()                   { return BMM_IO_CLASS_ID;  }
+  Class_ID        ClassID      ()                   { return DDS_CLASS_ID;    }
+  const TCHAR    *Category     ()                   { return GetString(IDS_BITMAP_IO); }
+};
+
+static DDSClassDesc DDSDesc;
+
+//-----------------------------------------------------------------------------
+// *> AboutCtrlDlgProc()
+//
+
+BOOL CALLBACK AboutCtrlDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
+{
+  switch (message)
+  {
+    case WM_INITDIALOG:
+    {
+      CenterWindow(hWnd,GetParent(hWnd));
+      return 1;
+    }
+
+    case WM_COMMAND:
+      switch (LOWORD(wParam))
+      {
+        case IDOK:
+         EndDialog(hWnd,1);
+         break;
+
+        case IDCANCEL:
+         EndDialog(hWnd,0);
+         break;
+
+      }
+      return 1;
+  }
+  return 0;
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::BitmapIO_DDS()
+
+BitmapIO_DDS::BitmapIO_DDS()
+{
+  mParams.outFormat  = TF_DXT3 | TF_MIPMAPS;
+}
+
+BitmapIO_DDS::~BitmapIO_DDS () {}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::LongDesc()
+
+const TCHAR *BitmapIO_DDS::LongDesc()
+{
+  return GetString(IDS_DDS_FILE);
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::ShortDesc()
+
+const TCHAR *BitmapIO_DDS::ShortDesc()
+{
+  return GetString(IDS_DDS);
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::LoadConfigure()
+
+BOOL BitmapIO_DDS::LoadConfigure (void *ptr)
+{
+  DDSParams *buf = (DDSParams*) ptr;
+  memcpy(&mParams, ptr, sizeof(DDSParams));
+  return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::SaveConfigure()
+
+BOOL BitmapIO_DDS::SaveConfigure (void *ptr)
+{
+  if (ptr)
+  {
+    memcpy(ptr, &mParams, sizeof(DDSParams));
+    return TRUE;
+  }
+  return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::ShowAbout()
+
+void BitmapIO_DDS::ShowAbout(HWND hWnd)
+{
+  DialogBoxParam(
+    hInstance,
+    MAKEINTRESOURCE(IDD_DDS_ABOUT),
+    hWnd,
+    (DLGPROC)AboutCtrlDlgProc,
+    (LPARAM)0);
+}
+
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::ConfigCtrlDlgProc
+
+BOOL BitmapIO_DDS::ConfigCtrlDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
+{
+
+  switch (message)
+  {
+    case WM_INITDIALOG:
+      switch (mParams.outFormat & TF_FMTMASK)
+      {
+        case TF_DXT1:    CheckDlgButton(hWnd, IDC_DDS_DXT1,     TRUE); break;
+        case TF_DXT1_1BitAlpha: CheckDlgButton(hWnd, IDC_DDS_DXT1ALPHA, TRUE); break;
+        case TF_DXT3:    CheckDlgButton(hWnd, IDC_DDS_DXT3,     TRUE); break;
+        case TF_DXT5:    CheckDlgButton(hWnd, IDC_DDS_DXT5,     TRUE); break;
+        case TF_RGB4444: CheckDlgButton(hWnd, IDC_DDS_ARGB4444, TRUE); break;
+        case TF_RGB1555: CheckDlgButton(hWnd, IDC_DDS_ARGB1555, TRUE); break;
+        case TF_RGB565:  CheckDlgButton(hWnd, IDC_DDS_RGB565,   TRUE); break;
+        case TF_RGB8888: CheckDlgButton(hWnd, IDC_DDS_ARGB8888, TRUE); break;
+      }
+      CheckDlgButton(hWnd, IDC_DDS_DITHER, (mParams.outFormat & TF_DITHER)!=0);
+      CheckDlgButton(hWnd, IDC_DDS_MIPMAPS, (mParams.outFormat & TF_MIPMAPS)!=0);
+      break;
+
+    case WM_COMMAND:
+      switch (LOWORD(wParam))
+      {
+        case IDOK:
+          EndDialog(hWnd,1);
+          break;
+        case IDCANCEL:
+          EndDialog(hWnd,0);
+          break;
+
+        case IDC_DDS_DXT1:     mParams.outFormat = TF_DXT1    | (mParams.outFormat&~TF_FMTMASK); break;
+        case IDC_DDS_DXT1ALPHA: mParams.outFormat = TF_DXT1_1BitAlpha | (mParams.outFormat&~TF_FMTMASK); break;
+        case IDC_DDS_DXT3:     mParams.outFormat = TF_DXT3    | (mParams.outFormat&~TF_FMTMASK); break; 
+        case IDC_DDS_DXT5:     mParams.outFormat = TF_DXT5    | (mParams.outFormat&~TF_FMTMASK); break;
+        case IDC_DDS_ARGB4444: mParams.outFormat = TF_RGB4444 | (mParams.outFormat&~TF_FMTMASK); break;
+        case IDC_DDS_ARGB1555: mParams.outFormat = TF_RGB1555 | (mParams.outFormat&~TF_FMTMASK); break;
+        case IDC_DDS_RGB565:   mParams.outFormat = TF_RGB565  | (mParams.outFormat&~TF_FMTMASK); break;
+        case IDC_DDS_ARGB8888: mParams.outFormat = TF_RGB8888 | (mParams.outFormat&~TF_FMTMASK); break;
+
+        case IDC_DDS_DITHER:
+          if (IsDlgButtonChecked(hWnd, IDC_DDS_DITHER))
+            mParams.outFormat |= TF_DITHER;
+          else
+            mParams.outFormat &= ~TF_DITHER;
+          break;
+
+        case IDC_DDS_MIPMAPS:
+          if (IsDlgButtonChecked(hWnd, IDC_DDS_MIPMAPS))
+            mParams.outFormat |= TF_MIPMAPS;
+          else
+            mParams.outFormat &= ~TF_MIPMAPS;
+          break;
+      }
+      return TRUE;
+  }
+  return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// #> StaticDialogProc
+
+BOOL CALLBACK StaticDialogProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
+{
+  BitmapIO_DDS* p;
+
+  if (msg==WM_INITDIALOG)
+  {
+    p = (BitmapIO_DDS*)l;
+    SetWindowLong(hwnd, GWL_USERDATA,l);
+  }
+  else
+  {
+    if ((p = (BitmapIO_DDS*)GetWindowLong(hwnd, GWL_USERDATA)) == NULL)
+      return FALSE;
+  }
+  return p->ConfigCtrlDlgProc(hwnd,msg,w,l);
+}
+
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::ShowControl()
+
+BOOL BitmapIO_DDS::ShowControl(HWND hWnd, DWORD flag)
+{
+  return DialogBoxParam(
+    hInstance,
+    MAKEINTRESOURCE (IDD_DDS_CONFIG),
+    hWnd,
+    (DLGPROC) StaticDialogProc,
+    (LPARAM) this);
+}
+
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::GetImageInfo()
+
+BMMRES BitmapIO_DDS::GetImageInfo (BitmapInfo *fbi)
+{
+  //-- Open DDS File -----------------------------------
+
+  File file(fbi->Name(), _T("rb"));
+
+  if (!file.stream)
+    return (ProcessImageIOError(fbi));
+
+  //-- Read File Header --------------------------------
+
+  if (!ReadDDSHeader(file.stream))
+    return (ProcessImageIOError(fbi,BMMRES_BADFILEHEADER));
+
+  //-- Update Bitmap Info ------------------------------
+
+  fbi->SetWidth((WORD)hdr.dwWidth);
+  fbi->SetHeight((WORD)hdr.dwHeight);
+
+  switch (hdr.dwFourCC)
+  {
+    case 0:
+      switch (hdr.dwRGBBitCount)
+      {
+        //case  1: fbi->SetType(BMM_LINE_ART); break;
+        //case  4: fbi->SetType(BMM_BMP_4);    break;
+        //case  8: fbi->SetType(BMM_PALETTED); break;
+        case 16: 
+          if (hdr.dwRGBAlphaBitMask)
+            fbi->SetType(BMM_TRUE_32);  
+          else
+            fbi->SetType(BMM_TRUE_24);  
+          break;
+        case 24: fbi->SetType(BMM_TRUE_24);  break;
+        case 32: fbi->SetType(BMM_TRUE_32);   break;
+        default: fbi->SetType(BMM_NO_TYPE);  break;
+      }
+      break;
+    case 'D'|('X'<<8)|('T'<<16)|('1'<<24):
+    case 'D'|('X'<<8)|('T'<<16)|('2'<<24):
+    case 'D'|('X'<<8)|('T'<<16)|('3'<<24):
+    case 'D'|('X'<<8)|('T'<<16)|('4'<<24):
+    case 'D'|('X'<<8)|('T'<<16)|('5'<<24):
+      fbi->SetType(BMM_TRUE_32);   
+      break;
+  }
+
+//  fbi->SetGamma(1.0f);
+  fbi->SetAspect(1.0f);
+  fbi->SetFirstFrame(0);
+  fbi->SetLastFrame(0);
+
+  return BMMRES_SUCCESS;
+}
+
+inline WORD Conv4To16(int d) { return (d<<12) | (d<<8) | (d<<4) | d; }
+inline WORD Conv5To16(int d) { return (d<<11) | (d<<6) | (d<<1); }
+inline WORD Conv6To16(int d) { return (d<<10) | (d<<4) | (d>>2); }
+inline WORD Conv8To16(int d) { return (d<<8)  | d; }
+
+//-----------------------------------------------------------------------------
+//-- BitmapIO_DDS::Load()
+
+BitmapStorage *BitmapIO_DDS::Load(BitmapInfo *fbi, Bitmap *map, BMMRES *status)
+{
+  RGBQUAD      *rgb = NULL;
+  BMM_Color_48 *pal = NULL;
+  BitmapStorage  *s = NULL;
+  BMM_Color_64   *b = NULL;
+  BYTE           *p = NULL;
+
+
+  int pixels = 0;
+  int rows   = 0;
+  int w      = 0;
+  int wb     = 0;
+  int h      = 0;
+
+  //-- Initialize Status Optimistically
+
+  *status = BMMRES_SUCCESS;
+
+  //-- Make sure nothing weird is going on
+
+  if(openMode != BMM_NOT_OPEN)
+  {
+    *status = ProcessImageIOError(fbi,BMMRES_INTERNALERROR);
+    return NULL;
+  }
+
+  //-- Open DDS File -----------------------------------
+
+  File file(fbi->Name(), _T("rb"));
+
+  if (!file.stream)
+  {
+    *status = ProcessImageIOError(fbi);
+    return(NULL);
+  }
+
+  ghFile = file.stream;
+
+  int width;
+  int height;
+  int planes;
+  int lTotalWidth; 
+  int rowBytes;
+      
+  //-- Read File Header --------------------------------
+
+  unsigned char* data = nvDXTdecompress(width, height, planes, lTotalWidth, rowBytes);
+
+  if (!data)
+  {
+    *status = ProcessImageIOError(fbi,BMMRES_BADFILEHEADER);
+    return (NULL);
+  }
+
+  ghFile = NULL;
+ 
+
+  //-- Update Bitmap Info ------------------------------
+
+  fbi->SetWidth(width);
+  fbi->SetHeight(height);
+
+  //fbi->SetGamma(1.0f);
+  fbi->SetAspect(1.0f);
+
+  switch(planes)
+  {
+    case 3:
+      fbi->SetType(BMM_TRUE_24);
+      break;
+
+    case 4:
+      fbi->SetType(BMM_TRUE_32);
+      break;
+  }
+
+  fbi->SetFirstFrame(0);
+  fbi->SetLastFrame(0);
+
+  //-- Create Image Storage ----------------------------
+
+  switch(planes)
+  {
+    case 3:
+    case 4:
+      s = BMMCreateStorage(map->Manager(),BMM_TRUE_32);
+      break;
+  }
+
+  if(!s)
+  {
+    *status = ProcessImageIOError(fbi,BMMRES_CANTSTORAGE);
+    return NULL;
+  }
+
+  //-- Allocate Image Storage --------------------------
+
+  if (s->Allocate(fbi,map->Manager(),BMM_OPEN_R)==0)
+  {
+
+    memory_error_out:
+    *status = ProcessImageIOError(fbi,BMMRES_MEMORYERROR);
+    goto bail_out;
+
+    io_error_out:
+    *status = ProcessImageIOError(fbi);
+    bail_out:
+
+    if (s) delete s;
+    if (b) free(b);
+    if (p) free(p);
+    if (rgb) free(rgb);
+    if (pal) free(pal);
+
+    return NULL;
+
+  }
+
+  switch (planes)
+  {
+    case 3:
+    {
+      //-- Read Image (24 Bits) ----------------------------
+
+      w    = width;
+      wb   = lTotalWidth*planes; //rowBytes;
+      h    = height;
+
+      b = (BMM_Color_64  *)malloc(width*sizeof(BMM_Color_64));
+      p = (BYTE          *)data;
+
+      if(!b || !p)
+        goto memory_error_out;
+
+      BYTE *ptr;
+
+      do
+      {
+        ptr = p;
+        p += wb;
+        for (int x = 0; x < w; x++)
+        {
+          b[x].b = Conv8To16(*ptr++);
+          b[x].g = Conv8To16(*ptr++);
+          b[x].r = Conv8To16(*ptr++);
+        }
+        if (s->PutPixels(0,rows,w,b)!=1)
+          goto io_error_out;
+        rows++;
+        if (rows>=h) break;
+
+        //-- Progress Report
+
+        if (fbi->GetUpdateWindow())
+          SendMessage(fbi->GetUpdateWindow(),BMM_PROGRESS,rows,h);
+
+      } while (true);
+      break;
+    }
+    case 4:
+    {
+      //-- Read Image (32 Bits) ----------------------------
+
+      w    = width;
+      wb   = lTotalWidth*planes; //rowBytes;
+      h    = height;
+
+      b = (BMM_Color_64  *)malloc(width*sizeof(BMM_Color_64));
+      p = (BYTE          *)data;
+
+      if(!b || !p)
+        goto memory_error_out;
+
+      BYTE *ptr;
+
+      bool foundalpha = false;
+ 
+      do
+      {
+        ptr = p;
+        p += wb;
+        for (int x = 0; x < w; x++)
+        {
+          b[x].b = Conv8To16(*ptr++);
+          b[x].g = Conv8To16(*ptr++);
+          b[x].r = Conv8To16(*ptr++);
+          if (*ptr != 0xFF) foundalpha=true;
+          b[x].a = Conv8To16(*ptr++);
+        }
+        if (s->PutPixels(0,rows,w,b)!=1)
+          goto io_error_out;
+        rows++;
+        if (rows>=h) break;
+
+        //-- Progress Report
+
+        if (fbi->GetUpdateWindow())
+          SendMessage(fbi->GetUpdateWindow(),BMM_PROGRESS,rows,h);
+
+      } while (true);
+      if (foundalpha)
+  	    fbi->SetFlags(MAP_HAS_ALPHA);
+      else
+        fbi->SetType(BMM_TRUE_24);
+      break;
+    }
+  }
+
+  //-- Clean Up ----------------------------------------
+
+  free(data);
+
+  if (b) free(b);
+
+  //-- Set the storage's BitmapInfo
+
+  s->bi.CopyImageInfo(fbi);
+
+  return  s;
+
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::OpenOutput()
+//
+
+BMMRES BitmapIO_DDS::OpenOutput(BitmapInfo *fbi, Bitmap *map)
+{
+
+  if (openMode != BMM_NOT_OPEN)
+    return (ProcessImageIOError(&bi,BMMRES_INTERNALERROR));
+
+  if (!map)
+    return (ProcessImageIOError(&bi,BMMRES_INTERNALERROR));
+
+  //-- Save Image Info Data
+
+  bi.CopyImageInfo(fbi);
+  bi.SetUpdateWindow(fbi->GetUpdateWindow());
+
+  this->map = map;
+  openMode    = BMM_OPEN_W;
+
+  return (BMMRES_SUCCESS);
+
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::Write()
+//
+//
+
+BMMRES BitmapIO_DDS::Write(int frame)
+{
+
+  BMMRES result = BMMRES_SUCCESS;
+
+  //-- If we haven't gone through an OpenOutput(), leave
+
+  if (openMode != BMM_OPEN_W)
+    return ProcessImageIOError(&bi,BMMRES_INTERNALERROR);
+
+  //-- Resolve Filename --------------------------------
+
+  TCHAR filename[MAX_PATH];
+
+  if (frame == BMM_SINGLEFRAME)
+  {
+    _tcscpy(filename,bi.Name());
+  }
+  else
+  {
+    if (!BMMCreateNumberedFilename(bi.Name(),frame,filename))
+      return ProcessImageIOError(&bi,BMMRES_NUMBEREDFILENAMEERROR);
+  }
+
+  //-- Create Image File -------------------------------
+
+  PBITMAPINFO pbmi = GetDitheredOutputDib(32);
+  if (!pbmi)
+    return ProcessImageIOError(&bi,GetString(IDS_CONVERT_ERROR));
+  int w=map->Width();
+  int h=map->Height();
+  int wb=w*4;
+  unsigned char* data = new unsigned char[wb*h];
+  const unsigned char* psrc = (const unsigned char*)pbmi->bmiColors;
+  unsigned char* pdst = data + wb*h;
+  for (int j=h; --j>=0; )
+  {
+    pdst -= wb;
+    memcpy(pdst,psrc,wb);
+    psrc += wb;
+  }
+
+  //-- Write Image File --------------------------------
+
+  if (bi.GetUpdateWindow())
+    SendMessage(bi.GetUpdateWindow(),BMM_PROGRESS,50,100);
+
+  File file(filename, _T("wb"));
+
+  if (!file.stream)
+  {
+    LocalFree(pbmi);
+    return ProcessImageIOError(&bi);
+  }
+
+  ghFile = file.stream;
+  
+/*
+   Compresses an image with a user supplied callback with the data for each MIP level created
+   Only supports input of RGB 24 or ARGB 32 bpp
+   if callback is == 0 (or not specified), then WriteDTXnFile is called with all file info
+*/
+  HRESULT res = nvDXTcompress(data, // pointer to data (24 or 32 bit)
+                  w, // width in texels
+                  h, // height in texels
+                  mParams.outFormat&TF_FMTMASK, 
+                  (mParams.outFormat&TF_MIPMAPS)!=0,    // auto gen MIP maps
+                  (mParams.outFormat&TF_DITHER)!=0,    // dither
+                  4,  // 3 or 4 bytes per pixel
+                  0);   // callback for generated levels
+
+  delete[] data;
+
+  LocalFree(pbmi);
+  ghFile = NULL;
+
+  if (res != 0)
+  {
+    switch (res)
+    {
+      default:
+      case DXTERR_INPUT_POINTER_ZERO:
+        return ProcessImageIOError(&bi,GetString(IDS_CONVERT_ERROR));
+      case DXTERR_DEPTH_IS_NOT_3_OR_4:
+        return ProcessImageIOError(&bi,GetString(IDS_UNSUPPORTEDFORMAT_ERROR));
+      case DXTERR_NON_POWER_2:
+        return ProcessImageIOError(&bi,GetString(IDS_NONPOWEROF2_ERROR));
+    }
+  }
+
+  if (bi.GetUpdateWindow())
+    SendMessage(bi.GetUpdateWindow(),BMM_PROGRESS,100,100);
+
+  return result;
+}
+
+//-----------------------------------------------------------------------------
+// BitmapIO_DDS::Close()
+//
+
+int  BitmapIO_DDS::Close(int flag)
+{
+  return 1;
+}
+
+//-----------------------------------------------------------------------------
+// #> BitmapIO_DDS::ReadDDSHeader()
+//
+
+int  BitmapIO_DDS::ReadDDSHeader(FILE *stream)
+{
+  //-- Read File Header --------------------------------
+
+  int res = fread(&hdr,1,sizeof(DDSFILEHEADER),stream);
+
+  if (res != sizeof(DDSFILEHEADER))
+    return 0;
+
+  //-- Validate ----------------------------------------
+
+  if (hdr.dwMagic != 0x20534444)
+    return 0;
+
+  //-- Done
+  return 1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Interface
+
+extern ClassDesc *GetDDSLibClassDesc()
+{
+   return &DDSDesc;
+}
+
+#if 0
+//-- Globals ------------------------------------------------------------------
+
+TCHAR *GetString(int id)
+{
+   static TCHAR buf[256];
+   if (hInstance)
+      return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
+   return NULL;
+}
+
+
+DLLEXPORT const TCHAR * LibDescription ()
+{
+  return GetString(IDS_DDS_DESC);
+}
+
+DLLEXPORT int LibNumberClasses ()
+{
+  return 1;
+}
+
+DLLEXPORT ClassDesc *LibClassDesc(int i)
+{
+  switch(i)
+  {
+    case  0: return &DDSDesc; break;
+    default: return 0;        break;
+  }
+}
+
+DLLEXPORT ULONG LibVersion ()
+{
+  return (VERSION_3DSMAX);
+}
+
+// Let the plug-in register itself for deferred loading
+__declspec(dllexport) ULONG CanAutoDefer()
+{
+  return 1;
+}
+
+//-----------------------------------------------------------------------------
+//-- DLL Declaration
+
+BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
+{
+  switch (fdwReason)
+  {
+     case DLL_PROCESS_ATTACH:
+        if (hInstance)
+          return(FALSE);
+        hInstance = hDLLInst;
+        break;
+     case DLL_PROCESS_DETACH:
+        hInstance  = NULL;
+        break;
+     case DLL_THREAD_ATTACH:
+        break;
+     case DLL_THREAD_DETACH:
+        break;
+  }
+  return TRUE;
+}
+
+#endif
\ No newline at end of file
diff --git a/NifProps/dds/dds.dep b/NifProps/dds/dds.dep
new file mode 100644
index 0000000000000000000000000000000000000000..076baa32f4f9156910722920246a977b39099cf8
--- /dev/null
+++ b/NifProps/dds/dds.dep
@@ -0,0 +1,128 @@
+# Microsoft Developer Studio Generated Dependency File, included by dds.mak
+
+.\dds.cpp : \
+	"..\..\..\include\acolor.h"\
+	"..\..\..\include\ActionTable.h"\
+	"..\..\..\include\animtbl.h"\
+	"..\..\..\include\appio.h"\
+	"..\..\..\include\assert1.h"\
+	"..\..\..\include\baseinterface.h"\
+	"..\..\..\include\bitarray.h"\
+	"..\..\..\include\bitmap.h"\
+	"..\..\..\include\bmmlib.h"\
+	"..\..\..\include\box2.h"\
+	"..\..\..\include\box3.h"\
+	"..\..\..\include\buildver.h"\
+	"..\..\..\include\captypes.h"\
+	"..\..\..\include\channels.h"\
+	"..\..\..\include\cmdmode.h"\
+	"..\..\..\include\color.h"\
+	"..\..\..\include\coreexp.h"\
+	"..\..\..\include\custcont.h"\
+	"..\..\..\include\dbgprint.h"\
+	"..\..\..\include\dpoint3.h"\
+	"..\..\..\include\euler.h"\
+	"..\..\..\include\evuser.h"\
+	"..\..\..\include\excllist.h"\
+	"..\..\..\include\export.h"\
+	"..\..\..\include\gbuf.h"\
+	"..\..\..\include\gencam.h"\
+	"..\..\..\include\genhier.h"\
+	"..\..\..\include\genlight.h"\
+	"..\..\..\include\genshape.h"\
+	"..\..\..\include\geom.h"\
+	"..\..\..\include\geomlib.h"\
+	"..\..\..\include\gfloat.h"\
+	"..\..\..\include\gfx.h"\
+	"..\..\..\include\gfxlib.h"\
+	"..\..\..\include\gutil.h"\
+	"..\..\..\include\hitdata.h"\
+	"..\..\..\include\hold.h"\
+	"..\..\..\include\iColorMan.h"\
+	"..\..\..\include\iFnPub.h"\
+	"..\..\..\include\impapi.h"\
+	"..\..\..\include\impexp.h"\
+	"..\..\..\include\impexpintf.h"\
+	"..\..\..\include\imtl.h"\
+	"..\..\..\include\inode.h"\
+	"..\..\..\include\INodeGIProperties.h"\
+	"..\..\..\include\interval.h"\
+	"..\..\..\include\ioapi.h"\
+	"..\..\..\include\iparamb.h"\
+	"..\..\..\include\ipipelineclient.h"\
+	"..\..\..\include\ipoint2.h"\
+	"..\..\..\include\ipoint3.h"\
+	"..\..\..\include\istdplug.h"\
+	"..\..\..\include\iTreeVw.h"\
+	"..\..\..\include\linklist.h"\
+	"..\..\..\include\lockid.h"\
+	"..\..\..\include\log.h"\
+	"..\..\..\include\matrix2.h"\
+	"..\..\..\include\matrix3.h"\
+	"..\..\..\include\max.h"\
+	"..\..\..\include\maxapi.h"\
+	"..\..\..\include\maxcom.h"\
+	"..\..\..\include\maxtess.h"\
+	"..\..\..\include\maxtypes.h"\
+	"..\..\..\include\mesh.h"\
+	"..\..\..\include\meshlib.h"\
+	"..\..\..\include\MNBigMat.h"\
+	"..\..\..\include\MNCommon.h"\
+	"..\..\..\include\mnmath.h"\
+	"..\..\..\include\MNMesh.h"\
+	"..\..\..\include\MNNormalSpec.h"\
+	"..\..\..\include\mouseman.h"\
+	"..\..\..\include\mtl.h"\
+	"..\..\..\include\namesel.h"\
+	"..\..\..\include\nametab.h"\
+	"..\..\..\include\object.h"\
+	"..\..\..\include\objmode.h"\
+	"..\..\..\include\palutil.h"\
+	"..\..\..\include\paramtype.h"\
+	"..\..\..\include\patch.h"\
+	"..\..\..\include\patchlib.h"\
+	"..\..\..\include\patchobj.h"\
+	"..\..\..\include\pixelbuf.h"\
+	"..\..\..\include\plugapi.h"\
+	"..\..\..\include\plugin.h"\
+	"..\..\..\include\point2.h"\
+	"..\..\..\include\point3.h"\
+	"..\..\..\include\point4.h"\
+	"..\..\..\include\polyobj.h"\
+	"..\..\..\include\polyshp.h"\
+	"..\..\..\include\ptrvec.h"\
+	"..\..\..\include\quat.h"\
+	"..\..\..\include\random.h"\
+	"..\..\..\include\ref.h"\
+	"..\..\..\include\render.h"\
+	"..\..\..\include\RenderElements.h"\
+	"..\..\..\include\rtclick.h"\
+	"..\..\..\include\sbmtlapi.h"\
+	"..\..\..\include\sceneapi.h"\
+	"..\..\..\include\sfx.h"\
+	"..\..\..\include\shape.h"\
+	"..\..\..\include\shphier.h"\
+	"..\..\..\include\shpsels.h"\
+	"..\..\..\include\snap.h"\
+	"..\..\..\include\soundobj.h"\
+	"..\..\..\include\spline3d.h"\
+	"..\..\..\include\stack.h"\
+	"..\..\..\include\stack3.h"\
+	"..\..\..\include\strbasic.h"\
+	"..\..\..\include\strclass.h"\
+	"..\..\..\include\SvCore.h"\
+	"..\..\..\include\SystemUtilities.h"\
+	"..\..\..\include\tab.h"\
+	"..\..\..\include\templt.h"\
+	"..\..\..\include\trig.h"\
+	"..\..\..\include\triobj.h"\
+	"..\..\..\include\udmIA64.h"\
+	"..\..\..\include\units.h"\
+	"..\..\..\include\utilexp.h"\
+	"..\..\..\include\utilintf.h"\
+	"..\..\..\include\utillib.h"\
+	"..\..\..\include\vedge.h"\
+	"..\..\..\include\winutil.h"\
+	".\DDS.H"\
+	".\dxtlib.h"\
+	
diff --git a/NifProps/dds/dds.h b/NifProps/dds/dds.h
new file mode 100644
index 0000000000000000000000000000000000000000..6af084cf9bc04c4f3ee41409ba766741bd395e2a
--- /dev/null
+++ b/NifProps/dds/dds.h
@@ -0,0 +1,159 @@
+// File ....: dds.h
+// ----------------
+// Author...: Sean Palmer
+// Date ....: April 2001
+// Descr....: DDS File I/O Module
+
+#ifndef _DDSCLASS_
+#define _DDSCLASS_
+
+#define DLLEXPORT __declspec(dllexport)
+
+#define DDS_CLASS_ID Class_ID(0xe3061ca, 0xd2120de)
+
+#pragma pack(push,1)
+
+struct DDSCOLORKEY
+{
+  DWORD       dwColorSpaceLowValue;   // low boundary of color space that is to
+                                      // be treated as Color Key, inclusive
+  DWORD       dwColorSpaceHighValue;  // high boundary of color space that is
+};
+
+struct DDSFILEHEADER
+{
+  DWORD dwMagic;         // (0x20534444, or "DDS ") 
+
+  // the following matches DDSURFACEDESC2
+  DWORD               dwSize;                 // size of the DDSURFACEDESC structure
+  DWORD               dwFlags;                // determines what fields are valid
+  DWORD               dwHeight;               // height of surface to be created
+  DWORD               dwWidth;                // width of input surface
+  long                lPitch;                 // distance to start of next line (return value only)
+  DWORD               dwDepth;                // the depth if this is a volume texture 
+  DWORD               dwMipMapCount;          // number of mip-map levels requested
+  DWORD               dwAlphaBitDepth;        // depth of alpha buffer requested
+  DWORD               dwReserved;             // reserved
+  void*               lpSurface;              // pointer to the associated surface memory
+  DDSCOLORKEY         ddckCKDestOverlay;      // color key for destination overlay use
+  DDSCOLORKEY         ddckCKDestBlt;          // color key for destination blt use
+  DDSCOLORKEY         ddckCKSrcOverlay;       // color key for source overlay use
+  DDSCOLORKEY         ddckCKSrcBlt;           // color key for source blt use
+
+  // from DDPIXELFORMAT structure
+  DWORD   dwPFSize;               // size of DDPIXELFORMAT structure
+  DWORD   dwPFFlags;              // pixel format flags
+  DWORD   dwFourCC;               // (FOURCC code)
+  DWORD   dwRGBBitCount;          // how many bits per pixel
+  DWORD   dwRBitMask;             // mask for red bit
+  DWORD   dwGBitMask;             // mask for green bits
+  DWORD   dwBBitMask;             // mask for blue bits
+  DWORD   dwRGBAlphaBitMask;      // mask for alpha channel
+
+  // from DDSCAPS2 structure
+  DWORD       dwCaps;         // capabilities of surface wanted
+  DWORD       dwCaps2;
+  DWORD       dwCaps3;
+  DWORD       dwVolumeDepth;
+
+  DWORD               dwTextureStage;         // stage in multitexture cascade
+//BYTE bData1[];         // Data for the main surface 
+//[BYTE bData2[]];       // Data for attached surfaces, if any, follows. 
+};
+
+#pragma pack(pop)
+
+enum
+{
+  TF_DITHER  = 0x40000000,
+  TF_MIPMAPS = 0x80000000,
+  TF_FMTMASK = 0x0000FFFF,
+};
+
+struct DDSParams
+{
+  int outFormat;   // Output format
+};
+
+class BitmapIO_DDS : public BitmapIO
+{
+
+private:
+
+  DDSFILEHEADER  hdr;
+  DDSParams     mParams;
+
+public:
+
+  //-- Constructors/Destructors
+
+  BitmapIO_DDS       ();
+  ~BitmapIO_DDS      ();
+
+  //-- Number of extemsions supported
+
+  int            ExtCount           ()       { return 1; }
+
+  //-- Extension #n (i.e. "3DS")
+
+  const TCHAR   *Ext                (int n) { return _T("dds"); }
+
+  //-- Descriptions
+
+  const TCHAR   *LongDesc           ();
+  const TCHAR   *ShortDesc          ();
+
+  //-- Miscelaneous Messages
+
+  const TCHAR   *AuthorName         ()       { return _T("Sean Palmer");}
+  const TCHAR   *CopyrightMessage   ()       { return _T("Copyright 2001 Treyarch LLC");}
+  const TCHAR   *OtherMessage1      ()       { return _T("");}
+  const TCHAR   *OtherMessage2      ()       { return _T("");}
+
+  unsigned int   Version            ()       { return (100);}
+
+  //-- Driver capabilities
+
+  int            Capability         ()       { return BMMIO_READER    |
+//                                                      BMMIO_WRITER    |
+                                                      BMMIO_EXTENSION |
+                                                      BMMIO_CONTROLWRITE;}
+
+  //-- Driver Configuration
+
+  BOOL           LoadConfigure      (void *ptr);
+  BOOL           SaveConfigure      (void *ptr);
+  DWORD          EvaluateConfigure  ()       { return sizeof(DDSParams); }
+
+  //-- Show DLL's "About..." box
+
+  void           ShowAbout          (HWND hWnd);
+
+  //-- Show Image's control Dlg Box
+  BOOL           ShowControl      (HWND hWnd, DWORD flag);
+
+  //-- Return info about image
+
+  BMMRES         GetImageInfo       (BitmapInfo *fbi);
+
+  //-- Image Input
+
+  BitmapStorage *Load               (BitmapInfo *fbi, Bitmap *map, BMMRES *status);
+
+  //-- Image Output
+
+  BMMRES         OpenOutput         (BitmapInfo *fbi, Bitmap *map);
+  BMMRES         Write              (int frame);
+  int            Close              (int flag);
+
+  //-- This handler's specialized functions
+
+  int            ReadDDSHeader      (FILE *stream);
+
+  //-- Dialog Proc for the Image control Dlg box
+
+  BOOL ConfigCtrlDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
+};
+
+#endif _DDSCLASS_
+
diff --git a/NifProps/dds/dds.rc b/NifProps/dds/dds.rc
new file mode 100644
index 0000000000000000000000000000000000000000..2d6329bc6fd19bbad065c291de4a9968226f8632
--- /dev/null
+++ b/NifProps/dds/dds.rc
@@ -0,0 +1,156 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "ddsres.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include <windows.h>
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "ddsres.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+    "#include <windows.h>\r\n"
+    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""veroverrides.h""\r\n"
+    "#include ""maxversion.r""\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DDS_ABOUT DIALOG DISCARDABLE  0, 0, 166, 97
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About DDS Image File I/O"
+FONT 8, "MS Sans Serif"
+BEGIN
+    DEFPUSHBUTTON   "OK",IDOK,108,77,50,14
+    RTEXT           "DDS File I/O Module",IDC_STATIC,37,9,118,9
+    RTEXT           "Version 1.0",IDC_STATIC,37,19,118,9
+    GROUPBOX        "",IDC_STATIC,8,2,151,29
+    RTEXT           "Author: Sean L. Palmer",IDC_STATIC,9,38,148,8
+    RTEXT           "Copyright 2001 Treyarch LLC",IDC_STATIC,9,50,148,8
+    RTEXT           "Using NVIDIA nvDXTlib DDS converter",IDC_STATIC,9,62,
+                    148,8
+END
+
+IDD_DDS_CONFIG DIALOG DISCARDABLE  0, 0, 177, 185
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "DDS Configuration"
+FONT 8, "MS Sans Serif"
+BEGIN
+    GROUPBOX        "Colors",-1,6,2,164,127,WS_GROUP
+    CONTROL         "DXT1 Compression",IDC_DDS_DXT1,"Button",
+                    BS_AUTORADIOBUTTON | WS_GROUP,29,15,128,10
+    CONTROL         "DXT1 with 1 bit alpha",IDC_DDS_DXT1ALPHA,"Button",
+                    BS_AUTORADIOBUTTON,29,29,125,10
+    CONTROL         "DXT3 Compressed with alpha",IDC_DDS_DXT3,"Button",
+                    BS_AUTORADIOBUTTON,29,43,125,10
+    CONTROL         "DXT5 Compressed with alpha",IDC_DDS_DXT5,"Button",
+                    BS_AUTORADIOBUTTON,29,57,125,10
+    CONTROL         "ARGB 4444",IDC_DDS_ARGB4444,"Button",BS_AUTORADIOBUTTON,
+                    29,71,125,10
+    CONTROL         "ARGB 1555",IDC_DDS_ARGB1555,"Button",BS_AUTORADIOBUTTON,
+                    29,85,125,10
+    CONTROL         "RGB 565",IDC_DDS_RGB565,"Button",BS_AUTORADIOBUTTON,29,
+                    99,125,10
+    CONTROL         "ARGB 8888",IDC_DDS_ARGB8888,"Button",BS_AUTORADIOBUTTON,
+                    29,113,125,10
+    DEFPUSHBUTTON   "OK",IDOK,38,165,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,94,165,50,14
+    CONTROL         "Dither",IDC_DDS_DITHER,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,30,135,95,9
+    CONTROL         "Generate Mipmaps",IDC_DDS_MIPMAPS,"Button",
+                    BS_AUTOCHECKBOX | WS_TABSTOP,30,148,96,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE 
+BEGIN
+    IDD_DDS_CONFIG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 170
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 179
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE 
+BEGIN
+    IDS_DDS                 "DDS"
+    IDS_BITMAP_IO           "Bitmap I/O"
+    IDS_DDS_FILE            "DDS Image File"
+    IDS_UNSUPPORTED         "Unsupported DDS Image File"
+    IDS_CONVERT_ERROR       "Error converting bitmap"
+    IDS_DDS_DESC            "DDS file I/O"
+    IDS_NONPOWEROF2_ERROR   "Dimensions not power of 2"
+    IDS_UNSUPPORTEDFORMAT_ERROR "Unsupported format"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "veroverrides.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/NifProps/dds/ddsTypes.h b/NifProps/dds/ddsTypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..576b75c15e814de7d8d9cea4d0be9ac4531e8700
--- /dev/null
+++ b/NifProps/dds/ddsTypes.h
@@ -0,0 +1,375 @@
+#pragma once
+#include <windows.h>
+#include <memory.h>
+
+#if defined(WIN32_LEAN_AND_MEAN)
+    #include <mmsystem.h>	// MAKEFOURCC
+#endif
+
+#include "tPixel.h"
+#include "nvErrorCodes.h"
+
+
+typedef	unsigned char	BYTE;
+typedef	unsigned short	WORD;
+typedef	unsigned long	DWORD;
+
+
+
+
+typedef enum nvD3DFORMAT
+{
+    nvD3DFMT_UNKNOWN              =  0,
+
+    nvD3DFMT_R8G8B8               = 20,
+    nvD3DFMT_A8R8G8B8             = 21,
+    nvD3DFMT_X8R8G8B8             = 22,
+    nvD3DFMT_R5G6B5               = 23,
+    nvD3DFMT_X1R5G5B5             = 24,
+    nvD3DFMT_A1R5G5B5             = 25,
+    nvD3DFMT_A4R4G4B4             = 26,
+    nvD3DFMT_R3G3B2               = 27,
+    nvD3DFMT_A8                   = 28,
+    nvD3DFMT_A8R3G3B2             = 29,
+    nvD3DFMT_X4R4G4B4             = 30,
+    nvD3DFMT_A2B10G10R10          = 31,
+    nvD3DFMT_A8B8G8R8             = 32,
+    nvD3DFMT_X8B8G8R8             = 33,
+    nvD3DFMT_G16R16               = 34,
+    nvD3DFMT_A2R10G10B10          = 35,
+    nvD3DFMT_A16B16G16R16         = 36,
+
+    nvD3DFMT_A8P8                 = 40,
+    nvD3DFMT_P8                   = 41,
+
+    nvD3DFMT_L8                   = 50,
+    nvD3DFMT_A8L8                 = 51,
+    nvD3DFMT_A4L4                 = 52,
+
+    nvD3DFMT_V8U8                 = 60,
+    nvD3DFMT_L6V5U5               = 61,
+    nvD3DFMT_X8L8V8U8             = 62,
+    nvD3DFMT_Q8W8V8U8             = 63,
+    nvD3DFMT_V16U16               = 64,
+    nvD3DFMT_A2W10V10U10          = 67,
+
+    nvD3DFMT_UYVY                 = MAKEFOURCC('U', 'Y', 'V', 'Y'),
+    nvD3DFMT_R8G8_B8G8            = MAKEFOURCC('R', 'G', 'B', 'G'),
+    nvD3DFMT_YUY2                 = MAKEFOURCC('Y', 'U', 'Y', '2'),
+    nvD3DFMT_G8R8_G8B8            = MAKEFOURCC('G', 'R', 'G', 'B'),
+    nvD3DFMT_DXT1                 = MAKEFOURCC('D', 'X', 'T', '1'),
+    nvD3DFMT_DXT2                 = MAKEFOURCC('D', 'X', 'T', '2'),
+    nvD3DFMT_DXT3                 = MAKEFOURCC('D', 'X', 'T', '3'),
+    nvD3DFMT_DXT4                 = MAKEFOURCC('D', 'X', 'T', '4'),
+    nvD3DFMT_DXT5                 = MAKEFOURCC('D', 'X', 'T', '5'),
+    nvD3DFMT_3Dc                  = MAKEFOURCC('A', 'T', 'I', '2'),
+
+    nvD3DFMT_D16_LOCKABLE         = 70,
+    nvD3DFMT_D32                  = 71,
+    nvD3DFMT_D15S1                = 73,
+    nvD3DFMT_D24S8                = 75,
+    nvD3DFMT_D24X8                = 77,
+    nvD3DFMT_D24X4S4              = 79,
+    nvD3DFMT_D16                  = 80,
+
+    nvD3DFMT_D32F_LOCKABLE        = 82,
+    nvD3DFMT_D24FS8               = 83,
+
+
+    nvD3DFMT_L16                  = 81,
+
+    nvD3DFMT_VERTEXDATA           =100,
+    nvD3DFMT_INDEX16              =101,
+    nvD3DFMT_INDEX32              =102,
+
+    nvD3DFMT_Q16W16V16U16         =110,
+
+    nvD3DFMT_MULTI2_ARGB8         = MAKEFOURCC('M','E','T','1'),
+
+    // Floating point surface formats
+
+    // s10e5 formats (16-bits per channel)
+    nvD3DFMT_R16F                 = 111,
+    nvD3DFMT_G16R16F              = 112,
+    nvD3DFMT_A16B16G16R16F        = 113,
+
+    // IEEE s23e8 formats (32-bits per channel)
+    nvD3DFMT_R32F                 = 114,
+    nvD3DFMT_G32R32F              = 115,
+    nvD3DFMT_A32B32G32R32F        = 116,
+
+    nvD3DFMT_CxV8U8               = 117,
+
+
+    nvD3DFMT_FORCE_DWORD          =0x7fffffff
+} nvD3DFORMAT;
+
+typedef enum nvRescaleTypes
+{
+    kRescaleNone,               // no rescale
+    kRescaleNearestPower2,     // rescale to nearest power of two
+    kRescaleBiggestPower2,   // rescale to next bigger power of 2
+    kRescaleSmallestPower2,  // rescale to smaller power of 2 
+    kRescaleNextSmallestPower2,  // rescale to next smaller power of 2
+    kRescalePreScale,           // rescale to this size
+    kRescaleRelScale,           // relative rescale
+
+} RescaleTypes;
+
+
+typedef enum nvSharpenFilterTypes
+{
+    kSharpenFilterNone,
+    kSharpenFilterNegative,
+    kSharpenFilterLighter,
+    kSharpenFilterDarker,
+    kSharpenFilterContrastMore,
+    kSharpenFilterContrastLess,
+    kSharpenFilterSmoothen,
+    kSharpenFilterSharpenSoft,
+    kSharpenFilterSharpenMedium,
+    kSharpenFilterSharpenStrong,
+    kSharpenFilterFindEdges,
+    kSharpenFilterContour,
+    kSharpenFilterEdgeDetect,
+    kSharpenFilterEdgeDetectSoft,
+    kSharpenFilterEmboss,
+    kSharpenFilterMeanRemoval,
+    kSharpenFilterUnSharp,
+    kSharpenFilterXSharpen,
+    kSharpenFilterWarpSharp,
+    kSharpenFilterCustom,
+};
+
+
+typedef enum nvMipMapGeneration
+{
+    kGenerateMipMaps = 30,
+    kUseExistingMipMaps = 31,
+    kNoMipMaps = 32,
+    kCompleteMipMapChain = 33,  // fill in missing MIP maps
+
+};
+
+
+typedef enum nvMipFilterTypes
+{
+    kMipFilterPoint ,    
+    kMipFilterBox ,      
+    kMipFilterTriangle , 
+    kMipFilterQuadratic ,
+    kMipFilterCubic ,    
+
+    kMipFilterCatrom ,   
+    kMipFilterMitchell , 
+
+    kMipFilterGaussian , 
+    kMipFilterSinc ,     
+    kMipFilterBessel ,   
+
+    kMipFilterHanning ,  
+    kMipFilterHamming ,  
+    kMipFilterBlackman , 
+    kMipFilterKaiser,
+};
+
+
+enum nvTextureFormats
+{
+	kDXT1 ,
+	kDXT1a ,  // DXT1 with one bit alpha
+	kDXT3 ,   // explicit alpha
+	kDXT5 ,   // interpolated alpha
+	k4444 ,   // a4 r4 g4 b4
+	k1555 ,   // a1 r5 g5 b5
+	k565 ,    // a0 r5 g6 b5
+	k8888 ,   // a8 r8 g8 b8
+	k888 ,    // a0 r8 g8 b8
+	k555 ,    // a0 r5 g5 b5
+	kP8c   ,   // paletted color only
+	kV8U8 ,   // DuDv 
+	kCxV8U8 ,   // normal map
+	kA8 ,            // alpha only
+	kP4c  ,            // 16 bit color palette
+	kQ8W8V8U8,
+	kA8L8,
+	kR32F,
+	kA32B32G32R32F,
+	kA16B16G16R16F,
+	kL8,       // luminance
+	kP8a   ,   // paletted with alpha
+	kP4a  ,            // 16 bit color palette with alpha
+	kR16F,            // single component fp16
+	kDXT5_NM ,   // normal map compression.  G = Y, A = X
+	kX888 ,    // aX r8 g8 b8
+	kV16U16,
+	kG16R16,
+	kG16R16F,
+	k3Dc,
+	kL16,
+
+    kUnknownTextureFormat = 0xFFFFFFFF,
+    
+};
+
+
+enum nvTextureTypes
+{
+    kTextureTypeTexture2D,
+    kTextureTypeCubeMap,
+    kTextureTypeVolumeMap,  
+};
+
+
+enum nvCompressionWeighting
+{
+    kLuminanceWeighting,
+    kGreyScaleWeighting,
+    kTangentSpaceNormalMapWeighting,
+    kObjectSpaceNormalMapWeighting,
+    kUserDefinedWeighting,     // used values stored in 'weight'
+};
+    
+enum nvNormalMapFilters
+{
+    kFilter4x = 1040,
+    kFilter3x3 = 1041,
+    kFilter5x5 = 1042,
+    kFilter7x7 = 1043,
+    kFilter9x9 = 1044,
+    kFilterDuDv = 1045,
+};
+
+
+enum nvHeightConversionMethods
+{
+    kAlphaChannel = 1009,
+    kAverageRGB = 1010,
+    kBiasedRGB = 1011,
+    kRed = 1012,
+    kGreen = 1013,
+    kBlue = 1014,
+    kMaxRGB = 1015,
+    kColorSpace = 1016,
+    kNormalize = 1017,
+    kNormalMapToHeightMap = 1018,
+};
+
+enum nvAlphaResult
+{
+    kAlphaUnchanged = 1033,
+    kAlphaHeight = 1034,
+    kAlphaSetToZero = 1035,  
+    kAlphaSetToOne = 1036,
+};
+
+         
+enum nvQualitySetting 
+{
+    kQualityFastest = 68,
+    kQualityNormal = 69,
+    kQualityProduction = 71,  // typical value
+    kQualityHighest = 72,
+};
+
+
+enum nvPixelFormat
+{
+    PF_RGBA,
+    PF_FP32,
+};
+
+
+
+// filled in by reading a dds file
+struct DDS_PIXELFORMAT
+{
+    DWORD dwSize;
+    DWORD dwFlags;
+    DWORD dwFourCC;
+    DWORD dwRGBBitCount;
+    DWORD dwRBitMask;
+    DWORD dwGBitMask;
+    DWORD dwBBitMask;
+    DWORD dwRGBAlphaBitMask;
+};
+
+
+class nvImageContainer
+{
+
+public:
+   // loaded directly from the .dds header
+    DDS_PIXELFORMAT m_ddpfPixelFormat;
+
+
+    nvImageContainer()
+    {
+
+        bits_per_component = 0; //image's resolution in bits per pixel per plane
+        paletteSize = 0;
+    
+
+
+        bFoundAlphaInRead = false;
+        bCompressed = false;
+        fmt = 0;  // nvD3DFMT_UNKNOWN
+
+        dwCubeMapFlags = 0;
+
+        actualMipMapCount = 1;
+        //maxPossibleMipMapCount = 1;
+        nMIPMapsToLoad = 1;
+        depth = 0;
+
+
+    }
+    
+ 
+
+    // in file read
+    size_t width;  // of MIP 0
+    size_t height; // of MIP 0
+    size_t depth; // for volume maps
+
+    size_t actualMipMapCount;
+    size_t nMIPMapsToLoad;
+
+
+    bool bFoundAlphaInRead; // is alpha field present and non-zero
+
+    // in the input file
+
+    DWORD dwCubeMapFlags;
+    size_t bits_per_component; 
+    size_t nPlanes;      // number of planes in the file format
+    bool   bCompressed;  // is file a compressed format
+    size_t paletteSize;  // 16 or 256 entries
+    rgba_t palette[256];
+
+    DWORD fmt;       // D3DFORMAT specified in .dds file
+
+    nvTextureFormats textureFormat;
+    
+    nvTextureTypes textureType;
+
+
+ 
+
+
+    fpMipMappedImage fpMIPImage;
+    fpMipMappedCubeMap fpMIPCubeMap;
+    fpMipMappedVolumeMap fpMIPVolumeMap;
+
+    RGBAMipMappedImage   rgbaMIPImage;
+    RGBAMipMappedCubeMap  rgbaMIPCubeMap;
+    RGBAMipMappedVolumeMap rgbaMIPVolumeMap;
+
+
+    ~nvImageContainer()
+    {
+    }
+};
+         
+
+
diff --git a/NifProps/dds/ddsres.h b/NifProps/dds/ddsres.h
new file mode 100644
index 0000000000000000000000000000000000000000..17688d0d4b7aac49b2b642a6213c1460f756c7df
--- /dev/null
+++ b/NifProps/dds/ddsres.h
@@ -0,0 +1,46 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by dds.rc
+//
+#define IDS_DDS                         1
+#define IDS_BITMAP_IO                   2
+#define IDS_DDS_FILE                    3
+#define IDS_UNSUPPORTED                 4
+#define IDS_CONVERT_ERROR               5
+#define IDS_DDS_DESC                    6
+#define IDS_NONPOWEROF2_ERROR           7
+#define IDS_UNSUPPORTEDFORMAT_ERROR     8
+#define IDD_DDS_ABOUT                   101
+#define IDD_DDS_CONTROL                 102
+#define IDD_DDS_CONFIG                  102
+#define IDC_DDS_PALETTE                 1000
+#define IDC_DDS_DXT1                    1000
+#define IDC_RAD_NTSC                    1001
+#define IDC_RAD_24                      1001
+#define IDC_DDS_RGB24                   1001
+#define IDC_DDS_ARGB8888                1001
+#define IDC_RAD_PAL                     1002
+#define IDC_RAD_8                       1002
+#define IDC_DDS_DXT3                    1002
+#define IDC_EDIT_X                      1003
+#define IDC_DDS_DXT1ALPHA               1003
+#define IDC_EDIT_Y                      1004
+#define IDC_DDS_DXT5                    1004
+#define IDC_RAD_CUSTOM                  1005
+#define IDC_DDS_ARGB1555                1005
+#define IDC_DDS_ARGB4444                1006
+#define IDC_DDS_RGB565                  1007
+#define IDC_DDS_DITHER                  1008
+#define IDC_DDS_MIPMAPS                 1009
+#define IDC_STATIC                      -1
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        103
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1010
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/NifProps/dds/dxtlib.h b/NifProps/dds/dxtlib.h
new file mode 100644
index 0000000000000000000000000000000000000000..84f6852b113944914dd90ae9623543eacbb44e8d
--- /dev/null
+++ b/NifProps/dds/dxtlib.h
@@ -0,0 +1,124 @@
+/*********************************************************************NVMH2****
+Path:  C:\Dev\devrel\Nv_sdk_4\Dx8_private\PhotoShop\dxtlib
+File:  dxtlib.h
+
+Copyright (C) 1999, 2000 NVIDIA Corporation
+This file is provided without support, instruction, or implied warranty of any
+kind.  NVIDIA makes no guarantee of its fitness for a particular purpose and is
+not liable under any circumstances for any damages or loss whatsoever arising
+from the use or inability to use this file or items derived from it.
+
+Comments:
+
+
+******************************************************************************/
+
+
+
+
+#pragma comment(lib, "C:\\Development\\Projects\\NifLib\\niftools\\trunk\\max\\NifProps\\dds\\nvDXTlib.lib")
+//#pragma comment(lib, "C:\\Development\\Projects\\NifLib\\niftools\\trunk\\max\\NifProps\\dds\\nvDXTlib.vc7.lib")
+
+
+
+
+
+
+
+
+typedef HRESULT (*MIPcallback)(void * data, int miplevel, DWORD size);
+// call back
+// pointer to data
+// mip level
+// size of chunk
+
+
+/*
+   Compresses an image with a user supplied callback with the data for each MIP level created
+   Only supports input of RGB 24 or ARGB 32 bpp
+*/
+HRESULT nvDXTcompress(unsigned char * raw_data, // pointer to data (24 or 32 bit)
+                unsigned long w, // width in texels
+                unsigned long h, // height in texels
+                DWORD TextureFormat, // list below
+                bool bGenMipMaps,    // auto gen MIP maps
+                bool bDither,
+                DWORD depth, // 3 or 4
+                MIPcallback callback = 0);   // callback for generated levels
+// if callback is == 0 (or not specified), then WriteDTXnFile is called with all file info
+//
+// You must write the routines (or provide stubs)
+// void WriteDTXnFile(count, buffer);
+// void ReadDTXnFile(count, buffer);
+// 
+//
+/* returns 
+  w width
+  h height
+  depth ( 3 or 4)
+  total_width 
+  rowBytes - pitch
+
+*/
+unsigned char * nvDXTdecompress(int & w, int & h, int & depth, int & total_width, int & rowBytes);
+
+
+// see examples
+
+
+void WriteDTXnFile(DWORD count, void * buffer);
+void ReadDTXnFile(DWORD count, void * buffer);
+
+
+// TextureFormat
+#define TF_DXT1            10
+#define TF_DXT1_1BitAlpha  11
+#define TF_DXT3            12
+#define TF_DXT5            13
+#define TF_RGB4444         14
+#define TF_RGB1555         15
+#define TF_RGB565          16
+#define TF_RGB8888         17
+
+
+#define DXTERR_INPUT_POINTER_ZERO -1
+#define DXTERR_DEPTH_IS_NOT_3_OR_4 -2
+#define DXTERR_NON_POWER_2 -3
+
+/* example
+
+LPDIRECT3DTEXTURE8 pCurrentTexture = 0; 
+
+HRESULT LoadAllMipSurfaces(void * data, int iLevel)
+{
+    HRESULT hr;
+    LPDIRECT3DSURFACE8 psurf;
+    D3DSURFACE_DESC sd;
+    D3DLOCKED_RECT lr;
+       
+    hr = pCurrentTexture->GetSurfaceLevel(iLevel, &psurf);
+    
+    if (FAILED(hr))
+        return hr;
+    psurf->GetDesc(&sd);
+    
+    
+    hr = pCurrentTexture->LockRect(iLevel, &lr, NULL, 0);
+    if (FAILED(hr))
+        return hr;
+    
+    memcpy(lr.pBits, data, sd.Size);
+    
+    hr = pCurrentTexture->UnlockRect(iLevel);
+    
+    ReleasePpo(&psurf);
+    
+    return 0;
+}
+       
+
+    hr = D3DXCreateTexture(m_pd3dDevice, Width, Height, nMips,  0,   D3DFMT_DXT3,  D3DPOOL_MANAGED, &pCurrentTexture);
+    nvDXTcompress(raw_data, Width, Height, DXT3, true, 4, LoadAllMipSurfaces);
+
+*/
+
diff --git a/NifProps/dds/nvDXTlib.lib b/NifProps/dds/nvDXTlib.lib
new file mode 100644
index 0000000000000000000000000000000000000000..8675cab326a4d86972a04a50c0ff88c9151c930c
Binary files /dev/null and b/NifProps/dds/nvDXTlib.lib differ
diff --git a/NifProps/dds/nvErrorCodes.h b/NifProps/dds/nvErrorCodes.h
new file mode 100644
index 0000000000000000000000000000000000000000..e6fa48bc448f5f55aee6b716aaaa1804e7966f03
--- /dev/null
+++ b/NifProps/dds/nvErrorCodes.h
@@ -0,0 +1,112 @@
+#pragma once
+
+typedef enum NV_ERROR_CODE
+{
+    NV_OK                   =   0,
+    NV_FAIL                 =  -1, // generic
+    NV_CANT_OPEN_INPUT_FILE    =  -2,
+    NV_CANT_OPEN_OUTPUT_FILE   =  -3,
+    NV_BAD_OPTION              =  -4,
+    NV_BAD_OUTPUT_DIRECTORY    =  -5,
+    NV_CANT_DECOMPRESS_IMAGE   =  -6,
+    NV_BAD_LIST_FILE           =  -7,
+    NV_CANT_OPEN_LIST_FILE     =  -8,
+    NV_BAD_LIST_FILE_CONTENTS  =  -9,
+    NV_IMAGE_NOT_SQUARE        = -10,
+    NV_IMAGES_NOT_SAME_SIZE    = -11,    
+    NV_UNKNOWN_CONVERSION      = -12,       // for normal map generation
+    NV_CANT_OPEN_PROFILE       = -13,
+    NV_IMAGE_NOT_MULT4         = -14,
+    NV_OUTPUT_FILE_IS_READ_ONLY= -15,
+    NV_INPUT_POINTER_ZERO      = -16,
+    NV_DEPTH_IS_NOT_3_OR_4     = -17,
+    NV_IMAGE_NOT_POWER_2       = -18,
+    NV_CANT_MAKE_MATRIX        = -19,
+    NV_CANT_NORMALIZE          = -20,
+    NV_CANT_INVERT_MATRIX      = -21,
+    NV_CANT_MAKE_VECTOR        = -22,
+    NV_CANT_INITIALIZE_CONVOLVER = -23,
+    NV_EMPTY_IMAGE             = -24,
+    NV_BAD_FLAGS               = -25,
+    NV_GBM_IO_ERR              = -26,
+    NV_TGA_IO_ERR              = -27,
+    NV_TGA_RLE_ERR             = -28,
+    NV_PNG_IO_ERR              = -29,
+    NV_CANT_CREATE_INDEX_BUFFER= -30,
+    NV_CANT_CREATE_CUBE_MAP    = -31,
+    NV_BAD_FORMAT              = -32,
+    NV_CANT_CREATE_TEXTURE     = -33,
+    NV_UNKNOWN_FORMAT          = -34,
+    NV_CANT_CREATE_VERTEX_BUFFER = -35,
+    NV_CANT_CREATE_PIXEL_SHADER= -36,
+    NV_CANT_CREATE_VERTEX_DECL = -37,
+    NV_NEED_4_PLANES_FOR_RGBE  = -38,
+    NV_PSD_IO_ERR              = -39,
+    NV_NO_FILENAME             = -40,
+
+    NV_CANT_DECOMPOSE_MATRIX   = -41,
+    NV_HDR_IO_ERR              = -42,
+    NV_RGBA_IO_ERR             = -43,
+    NV_READ_FAILED             = -44,
+    NV_WRITE_FAILED            = -45,
+    NV_BAD_ARG                 = -46,
+    NV_CANT_LOCK               = -47,
+    NV_FAILED_UNLOCK           = -48,
+    NV_NOT_RING_LOOP           = -49,
+
+    NV_CHART_FOLDED            = -50, 
+    NV_CHART_CANNOT_INVERT     = -51,
+    NV_CHART_BAD_PERIMETER     = -52,
+    NV_CHART_NO_DATA           = -53,
+    NV_CHART_CANT_OPTIMIZE     = -54,
+    NV_CHART_NO_POINTS_FOUND   = -55,
+    NV_CHART_ZERO_SIZE         = -56,
+    NV_CHART_NO_UNPINNED       = -57,
+    NV_CHART_OVERLAP           = -58,
+    NV_CHART_NO_FACES          = -59,
+    NV_CHART_MAX_DISTORTION_EXCEEDED = -60,
+    NV_CHART_AVE_DISTORTION_EXCEEDED = -61,
+
+    NV_CANT_CREATE_PRECONDITIONER = -70,
+    NV_NO_CONVERGENCE           = -71,
+    NV_ZERO_DIAGONAL            = -72,
+    NV_ZERO_TRIANGLE_AREA       = -73,
+    NV_LINE_ON_PLANE            = -74,
+    NV_LINE_AND_PLANE_PARALLEL  = -75,
+    NV_CANT_COMPILE_EFFECT_FILE = -76,
+                                               // open
+    NV_CANT_UNLOCK_INDEX_BUFFER = -78,
+    NV_CANT_CLONE_MESH          = -79,
+    NV_CANT_FIND_FILE           = -80,
+    NV_INVALID_FILENAME         = -81,
+    NV_CANT_SET_MATRIX          = -82,
+    NV_NEED_PIXEL_SHADER2       = -83,
+    NV_CANT_UNLOCK_TEXTURE      = -84,
+    NV_OUT_OF_MEMORY            = -85,
+    NV_TIFF_IO_ERR             =  -86,
+
+
+    NV_FILE_BAD_INDEX           = -90,
+    NV_FILE_NOT_ENOUGH_INDICES  = -91,
+    NV_FILE_FORMAT_NOT_SUPPORTED= -92,
+    NV_CANT_CREATE_EFFECT       = -93,
+    NV_NAN                      = -94,
+
+    NV_SURFACE_IS_CUBE_MAP         = -95,
+    NV_SURFACE_IS_VOLUME_MAP       = -96,
+    NV_UNSUPPORTED_FORMAT        = -97,
+    NV_MEMORY_ALLOCATION_FAILED        = -98,
+    NV_CUBE_MAP_NEEDS_SIX_FACES  = -99,
+    NV_IMAGE_EXCEEDS_INTERNAL_SIZE  = -100,
+    NV_CUBE_MAP_WIDTH_IS_NOT_SIX_TIMES_HEIGHT  = -101,
+    NV_VOLUME_MAP_IS_NOT_POWER2  = -102,
+
+
+
+
+};
+
+ const char *getErrorString(NV_ERROR_CODE hr);
+
+
+   
diff --git a/NifProps/dds/nvdxt_options.h b/NifProps/dds/nvdxt_options.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c8251626f77ee59368a661dc1ca5ac191aa3572
--- /dev/null
+++ b/NifProps/dds/nvdxt_options.h
@@ -0,0 +1,779 @@
+/****************************************************************************************
+	
+    Copyright (C) NVIDIA Corporation 2003
+
+    TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
+    *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
+    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+    AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
+    BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
+    WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
+    BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
+    ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
+    BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+*****************************************************************************************/
+#pragma once
+
+#include <windows.h>
+#include "tPixel.h"
+#include "ddsTypes.h"
+                    
+inline char * GetDXTCVersion() { return "Version 8.30";}
+
+// max mip maps
+#define MAX_MIP_MAPS 17
+
+
+typedef unsigned char nvBoolean;  // for photoshop scripting
+
+
+
+
+typedef struct nvNormalMap
+{
+public:
+
+        
+    nvNormalMap()
+    {
+        bEnableNormalMapConversion = false;
+
+        minz = 0;
+        scale = 1;
+        filterKernel = kFilter3x3;
+         
+        heightConversionMethod = kAverageRGB;
+        alphaResult = kAlphaUnchanged;
+
+        bWrap = false;
+        bInvertX = false;
+        bInvertY = false;
+        bInvertZ = false;
+        bAddHeightMap = false;
+        bNormalMapSwapRGB = false;
+
+
+    }
+    nvBoolean bEnableNormalMapConversion; // do not convert to a normal map
+    int minz;       // minimum value the z value can attain in the x y z  normal
+                    // keeps normal point "upwards"
+    float scale;    // height multiplier
+
+
+
+    nvNormalMapFilters filterKernel;  // kernel used to create normal maps.  Done this way to be compatible with plugins
+    nvHeightConversionMethods heightConversionMethod;  // method to convert color to height
+    nvAlphaResult alphaResult;     // what to do with the alpha channel when done
+
+    nvBoolean bWrap;
+    nvBoolean bInvertX;       // flip the x direction
+    nvBoolean bInvertY;       // flip the y direction
+    nvBoolean bInvertZ;       // flip the z direction
+
+    nvBoolean bAddHeightMap;
+    nvBoolean bNormalMapSwapRGB; // swap color channels
+} nvNormalMap;
+
+class nvCompressionOptions
+{
+public:
+
+    nvCompressionOptions()
+    {
+        SetDefaultOptions();
+    }
+
+
+    void SetDefaultOptions()
+    {
+        quality = kQualityProduction;
+        rmsErrorSearchThreshold = 400; // in  kQualityHighest mode, rms error above which will cause a long search for a better answer
+
+        rescaleImageType = kRescaleNone; 
+        rescaleImageFilter = kMipFilterCubic; 
+        scaleX = 1;
+        scaleY = 1;
+        bClamp = false;
+        clampX = 4096;
+        clampY = 4096;
+
+        bClampScale = false;
+        clampScaleX = 4096;
+        clampScaleY = 4096;
+
+        mipMapGeneration = kGenerateMipMaps;         // dNoMipMaps, dUseExistingMipMaps, dGenerateMipMaps
+        numMipMapsToWrite = 0;   // (number of mipmaps to write out)
+
+        mipFilterType = kMipFilterTriangle;      // for MIP maps
+        
+        bBinaryAlpha = false;       // zero or one alpha channel
+
+        bRGBE = false;
+
+        bAlphaBorder = false;       // make an alpha border
+        bAlphaBorderLeft = false;    
+        bAlphaBorderRight = false;   
+
+        bAlphaBorderTop = false;     
+        bAlphaBorderBottom = false;  
+
+        
+        bBorder = false;            // make a color border
+        borderColor32F.r = 0.0f;        // color of border
+        borderColor32F.g = 0.0f;        // color of border
+        borderColor32F.b = 0.0f;        // color of border
+        borderColor32F.a = 0.0f;        // alpha of border
+
+        bFadeColor = false;         // fade color over MIP maps
+        bFadeAlpha = false;         // fade alpha over MIP maps
+
+        fadeToColor32F.r = 0.0f;        // color to fade to
+        fadeToColor32F.g = 0.0f;        // color to fade to
+        fadeToColor32F.b = 0.0f;        // color to fade to
+        fadeToColor32F.a = 0.0f;        // alpha to fade to
+
+        fadeToDelay = 0;        // start fading after 'n' MIP maps
+
+        fadeAmount32F = 0.15f;         // percentage of color to fade in %15
+
+        alphaThreshold32F = 0.5;  // When Binary Alpha is selected, below this value, alpha is zero
+
+
+        bDitherColor = false;       // enable dithering during 16 bit conversion
+        bDitherMip0 = false;// enable dithering during 16 bit conversion for each MIP level (after filtering)
+
+        bForceDXT1FourColors = false;  // do not let DXT1 use 3 color representation
+
+
+        sharpenFilterType = kSharpenFilterNone;
+        bErrorDiffusion = false;
+        errorDiffusionWidth = 1;
+
+        weightType = kLuminanceWeighting;     
+        bNormalizeTexels = false;
+
+        weight[0] = 0.3086f; // luminance conversion values   
+        weight[1] = 0.6094f;    
+        weight[2] = 0.0820f;    
+
+        // gamma value for all filters
+        bEnableFilterGamma = false;
+        filterGamma = 2.2f;
+
+        // alpha value for 
+        filterBlur = 1.0f;
+        // width of filter
+        filterWidth = 10.0f;
+        bOverrideFilterWidth = false;
+
+        textureType = kTextureTypeTexture2D;        // regular decal, cube or volume  
+        textureFormat = kDXT1;	             // 
+
+        bSwapRG = false;           // swap color positions R and G
+		bSwapRB = false;           // swap color positions R and G
+        user_data = NULL;            // user supplied point passed down to write functions
+
+        int i,j;
+
+        float default_filter[5][5] = 
+        { 
+            0, 0,  0, 0, 0,
+            0, 0, -2, 0, 0,
+            0,-2, 11,-2, 0,
+            0, 0, -2, 0, 0,
+            0, 0,  0, 0, 0,  
+        };
+
+
+        for(i = 0; i<5; i++)
+        {    
+            for(j = 0; j<5; j++)
+            {
+                custom_filter_data.filter[i][j] = default_filter[i][j];
+            }
+        }
+
+        custom_filter_data.div = 3;   // div
+        custom_filter_data.bias = 0;  // bias
+
+        unsharp_data.radius32F = 5.0; // radius
+        unsharp_data.amount32F = 0.5;  // amount
+        unsharp_data.threshold32F = 0;     // threshold
+
+        xsharp_data.strength32F  = 1.0f; // xsharp strength
+        xsharp_data.threshold32F  = 1.0f; // xsharp threshold
+
+
+        sharpening_passes_per_mip_level[0] = 0;
+
+        for(i = 1; i<MAX_MIP_MAPS; i++)
+            sharpening_passes_per_mip_level[i] = 1;
+
+        bAlphaFilterModulate = false;
+        bPreModulateColorWithAlpha = false;
+
+
+        bUserSpecifiedFadingAmounts = false;
+
+
+        for(i = 0; i<256; i++)
+        {
+            color_palette[i].r = 0;
+            color_palette[i].g = 0;
+            color_palette[i].b = 0;
+            color_palette[i].a = 0;
+        }
+
+        paletteSize = 0;                // this will be set by the format read or write
+        autoGeneratePalette = false;
+
+
+        outputScale.r = 1.0f;             // scale and bias when writing output values
+        outputScale.g = 1.0f;             // scale and bias when writing output values
+        outputScale.b = 1.0f;             // scale and bias when writing output values
+        outputScale.a = 1.0f;             // scale and bias when writing output values
+
+        outputBias.r = 0.0f;
+        outputBias.g = 0.0f;
+        outputBias.b = 0.0f;
+        outputBias.a = 0.0f;
+
+        inputScale.r = 1.0f;             // scale and bias after loading data
+        inputScale.g = 1.0f;             // scale and bias 
+        inputScale.b = 1.0f;             // scale and bias 
+        inputScale.a = 1.0f;             // scale and bias 
+
+        inputBias.r = 0.0f;
+        inputBias.g = 0.0f;
+        inputBias.b = 0.0f;
+        inputBias.a = 0.0f;
+
+
+
+        bConvertToGreyScale = false;
+        greyScaleWeight.r = 0.3086f;             // scale and bias after loading data
+        greyScaleWeight.g = 0.6094f;             // scale and bias 
+        greyScaleWeight.b = 0.0820f;             // scale and bias 
+        greyScaleWeight.a = 0.0f;             // scale and bias 
+
+
+        brightness.r = 0.0;             // adjust brightness = 0 none
+        brightness.g = 0.0;             // 
+        brightness.b = 0.0;             // 
+        brightness.a = 0.0;             // 
+
+        contrast.r = 1;                // contrast 1 == none
+        contrast.g = 1;
+        contrast.b = 1;
+        contrast.a = 1;
+
+        bCalcLuminance = false;       // do not convert to luminance by default
+
+        bOutputWrap = false;          // wrap the values when outputting to the desired format
+                                      // 
+
+        bCreateOnePalette = false;
+
+    }
+
+    /////////////////////////// COMPRESSION QUALITY //////////////////////////////////
+
+    nvQualitySetting      quality;
+    float rmsErrorSearchThreshold;
+    
+    
+    void SetQuality(nvQualitySetting setting,  float threshold)
+    {
+        quality = setting;
+        // if setting == kQualityHighest, if the RMS error for a 4x4 block is bigger than
+        // this, an extended search is performed.  In practice this has been equivalent to and 
+        // exhaustive search in the entire domain. aka it doesn't get any better than this.
+
+        rmsErrorSearchThreshold = threshold;
+
+
+    }
+
+    /////////////////////////////// COMPRESSION  WEIGHTING //////////////////////////////
+    nvCompressionWeighting weightType;   // weighting type for DXT compressop
+    float               weight[3];                    // weights used for compress
+
+    void SetCompressionWeighting(nvCompressionWeighting type, float new_weight[3])
+    {
+        weightType = type;
+
+        // if type == kUserDefinedWeighting, then use these weights
+        weight[0] = new_weight[0];
+        weight[1] = new_weight[1];
+        weight[2] = new_weight[2];
+        
+    }
+
+
+    /////////////////////////////////////////////////////////////
+
+    nvNormalMap         normalMap;               // filled when processing normal maps
+    
+    nvBoolean           bNormalizeTexels;        // normalize the texels
+
+
+
+
+    ///////////////////////////  SCALING IMAGE /////////////////////////////////
+
+    nvRescaleTypes        rescaleImageType;     // rescaling type before image before compression
+    nvMipFilterTypes      rescaleImageFilter;   // rescaling filter
+
+    float               scaleX;             // scale to this if we are prescaling images before compressing
+    float               scaleY;
+
+
+    // scale the image to this size first
+    void PreScaleImage(float x, float y, nvMipFilterTypes filter)
+    {
+        rescaleImageType = kRescalePreScale;
+        scaleX = x;
+        scaleY = y;
+        rescaleImageFilter = filter;
+    }
+    // relative scaling.  0.5 is half the image size
+    void RelativeScaling(float x, float y, nvMipFilterTypes filter)
+    {
+        rescaleImageType = kRescaleRelScale;
+        scaleX = x;
+        scaleY = y;
+        rescaleImageFilter = filter;
+
+    }
+
+    void RescaleToNearestPOW2(nvMipFilterTypes filter)
+    {
+        rescaleImageType = kRescaleNearestPower2;
+        rescaleImageFilter = filter;
+
+    }
+    void RescaleToNearestBiggestPOW2(nvMipFilterTypes filter)
+    {
+        rescaleImageType = kRescaleBiggestPower2;
+        rescaleImageFilter = filter;
+
+    }
+    void RescaleToNearestSmallestPOW2(nvMipFilterTypes filter)
+    {
+        rescaleImageFilter = filter;
+        rescaleImageType = kRescaleSmallestPower2;
+
+    }
+    void RescaleToNearestNextSmallestPOW2(nvMipFilterTypes filter)
+    {
+        rescaleImageType = kRescaleNextSmallestPower2;
+        rescaleImageFilter = filter;
+
+    }
+
+    ///////////////////   CLAMPING IMAGE SIZE ///////////////////////////////////
+    nvBoolean           bClamp;             // Clamp to max size     
+    float               clampX;             // clamping values
+    float               clampY;
+
+    // image no bigger than...
+    void ClampMaxImageSize(float maxX, float maxY)
+    {    
+        bClamp = true;
+        clampX = maxX;
+        clampY = maxY;
+    }
+
+
+    nvBoolean           bClampScale;      // maximum value of h or w (retain scale)
+    float               clampScaleX;             // clamping values
+    float               clampScaleY;
+
+    // clamp max image size and maintain image proportions.
+    // Evenly scale down in both directions so that the given image size is not exceeded
+    void ClampMaxImageSizeContrained(float maxX, float maxY)
+    {    
+        bClampScale = true;
+        clampScaleX = maxX;
+        clampScaleY = maxY;
+    }
+
+    ///////////////////////////// MIP MAPS ///////////////////////////////////
+
+    nvMipMapGeneration  mipMapGeneration;         // changed MIPMaptype to an enum
+
+    long                numMipMapsToWrite;   // max number of Mip maps to generate
+
+    // 0 = all
+    void GenerateMIPMaps(int n)
+    {
+        mipMapGeneration = kGenerateMipMaps;
+        numMipMapsToWrite = n;
+
+    }
+    void DoNotGenerateMIPMaps()
+    {
+        mipMapGeneration = kNoMipMaps;
+
+    }
+    void UseExisitingMIPMaps()
+    {
+        // what ever is in the image
+        mipMapGeneration = kUseExistingMipMaps;
+        //numMipMapsToWrite is ignored
+    }
+    void CompleteMIPMapChain(int n)
+    {
+        mipMapGeneration = kCompleteMipMapChain;
+        numMipMapsToWrite = n;
+    }
+
+    nvMipFilterTypes      mipFilterType;      // for MIP map, select from MIPFilterTypes
+
+
+    ///////////////////   ALPHA //////////////////////////////////////////
+    nvBoolean           bBinaryAlpha;       // zero or one alpha channel
+
+    // [0,1]
+    float               alphaThreshold32F;          // threshold for alpha transparency DXT1
+                                              // or wen Binary Alpha is selected, below this value, alpha is zero
+
+    void SetBinaryAlpha(float threshold)
+    {
+        bBinaryAlpha = true;
+        alphaThreshold32F = threshold;
+
+    }
+
+
+
+
+    ////////////////////////// BORDERS /////////////////////////////////////////
+
+    // set any of these to generate an alpha border
+    nvBoolean           bAlphaBorder;           // make an alpha border
+    nvBoolean           bAlphaBorderLeft;       // make an alpha border on just the left
+    nvBoolean           bAlphaBorderRight;      // make an alpha border on just the right
+
+    nvBoolean           bAlphaBorderTop;        // make an alpha border on just the top
+    nvBoolean           bAlphaBorderBottom;      // make an alpha 
+
+    nvBoolean           bBorder;            // make a color border
+    fpPixel             borderColor32F;      // color of border [0,1]
+
+    void SetBorderColor(fpPixel & color)
+    {
+        bBorder = true;
+        borderColor32F = color;
+
+    }
+    void NoBorderColor()
+    {
+        bBorder = false;
+
+    }
+
+    /////////////////////// FADING MIP LEVELS ////////////////////////////
+
+    nvBoolean           bFadeColor;         // fade color over MIP maps
+    nvBoolean           bFadeAlpha;         // fade alpha over MIP maps
+
+    fpPixel             fadeToColor32F;        // color and alpha to fade to
+
+    long                fadeToDelay;        // start fading after 'n' MIP maps
+
+    float               fadeAmount32F;      // percentage of color to fade in
+
+    nvBoolean           bUserSpecifiedFadingAmounts;
+    float               userFadingAmounts[MAX_MIP_MAPS];
+      
+
+    // [0,1]
+    void FadeAlphaInMIPMaps(float alpha)
+    {
+        bFadeAlpha = true;
+        fadeToColor32F.a = alpha;
+
+
+    }
+    // 0 - 255
+    void FadeColorInMIPMaps(float r, float g, float b)
+    {
+        fadeToColor32F.r = r;
+        fadeToColor32F.g = g;
+        fadeToColor32F.b = b;
+
+
+        bFadeColor = true;
+    } 
+    void SetFadingAsPercentage(float percentPerMIP, int mipLevelToStartFading)
+    {
+        bUserSpecifiedFadingAmounts = false;
+
+        fadeAmount32F = percentPerMIP;
+        fadeToDelay = mipLevelToStartFading;
+    }
+    // or 
+    void SpecifyFadingPerMIPLevel(float fadeAmounts[MAX_MIP_MAPS])
+    {
+        bUserSpecifiedFadingAmounts = true;
+
+        for(int i = 0; i < MAX_MIP_MAPS; i++)
+        {
+            userFadingAmounts[i] = fadeAmounts[i];
+        }
+    }
+
+
+
+    /////////////////////////// SHARPENING /////////////////////////////////////
+
+    // sharpening after creating each MIP map level
+
+    // used when custom sharping filter is used
+    // 5x5 filter 
+    struct 
+    {
+        float filter[5][5];
+        float div;
+        float bias;
+
+    }  custom_filter_data; 
+
+
+
+    // used when unsharpen sharping filter is used
+    struct  
+    {
+        float radius32F; // radius
+        float amount32F;  // amount
+        float threshold32F;  // threshold [0,1]
+
+    } unsharp_data; 
+    
+    // used when xsharpen sharping filter is used
+    struct 
+    {
+        // 0 - 1
+        float strength32F;
+        float threshold32F;
+    } xsharp_data;
+
+
+    int                 sharpening_passes_per_mip_level[MAX_MIP_MAPS]; 
+
+    nvSharpenFilterTypes  sharpenFilterType; // post filtering image sharpening
+
+
+    void SetNumberOfSharpeningPassesPerMIPLevel( int passes[MAX_MIP_MAPS])
+    {
+        for (int i = 0; i < MAX_MIP_MAPS; i++)
+        {
+            sharpening_passes_per_mip_level[i] = passes[i];
+        }
+    }
+
+    // [0,1]
+    void XSharpenImage(float strength, float threshold)
+    {
+        sharpenFilterType = kSharpenFilterXSharpen;
+        xsharp_data.strength32F = strength;
+        xsharp_data.threshold32F = threshold;
+    }
+
+    void UnSharpenImage(float radius, float amount, float threshold)
+    {
+        sharpenFilterType = kSharpenFilterUnSharp;
+        unsharp_data.radius32F = radius;
+        unsharp_data.amount32F = amount;
+        unsharp_data.threshold32F = threshold;
+    }
+
+    // roll your own post filter sharpen
+    void SetCustomFilter(float filter[5][5], float div, float bias)
+    {
+        sharpenFilterType = kSharpenFilterCustom;
+        custom_filter_data.div = div;
+        custom_filter_data.bias = bias;
+
+        for(int i = 0; i<5; i++)
+            for(int j = 0; j<5; j++)
+                custom_filter_data.filter[i][j] = filter[i][j];
+
+    }
+
+    /////////////////////////////////////////////////////
+
+
+
+    
+
+    nvBoolean           bErrorDiffusion;        // diffuse error, used for helping gradient images
+    int                 errorDiffusionWidth; // number of texel to include
+
+    void EnableErrorDiffusion(int width)
+    {
+        bErrorDiffusion = true;
+        errorDiffusionWidth = width;
+    }
+    ///////////////////// FILTERING ////////////////////////////////////////
+    // convert to gamma space before filtering
+    nvBoolean           bEnableFilterGamma;
+    float               filterGamma;               // gamma value for filtering (MIP map generation)
+
+
+    float               filterBlur;               // sharpness or blurriness of filtering
+    nvBoolean           bOverrideFilterWidth; // use the specified width in FilterWidth,instead of the default
+    float               filterWidth;     // override fiter width with this value
+
+
+    // 0 is no gamma correction
+    void EnableGammaFiltering(float gamma)
+    {
+        bEnableFilterGamma = true;
+
+        filterGamma = gamma;
+    }
+
+    void OverrideFilterWidth(float w)
+    {  
+        bOverrideFilterWidth = true;
+        filterWidth = w;
+
+
+    }
+    void SetFilterSharpness(float sharp)
+    {
+        filterBlur = sharp;
+    }
+
+    /////////////////////////////////////////////////////
+
+
+
+
+	nvTextureTypes 		textureType;        // what type of texture is this?
+
+    
+    nvTextureFormats 		textureFormat;	    // format to convert to
+
+    void SetTextureFormat(nvTextureTypes type, nvTextureFormats format )
+    {
+        textureType = type;
+        textureFormat = format;
+    }
+
+
+    size_t              paletteSize;
+    rgba_t              color_palette[256];
+
+    nvBoolean           autoGeneratePalette;     // generate palette for p8 and p4 formats
+
+
+    // for P4 and P8 formats    
+    // set 16 for P4 format and 256 for P8 format
+
+    void SetPalette(int n, rgba_t user_palette[256])
+    {  
+        paletteSize = n;
+        for(int i = 0; i < n; i++)
+            color_palette[i] = user_palette[i];
+
+        autoGeneratePalette = false;
+
+    }
+
+
+
+
+    ////////////////// DATA SCALING 
+
+
+    fpPixel             outputScale;             // scale and bias when writing output values
+    fpPixel             outputBias;
+
+    void ScaleBiasOutput(fpPixel & scale, fpPixel & bias)
+    {
+        outputScale = scale;
+        outputBias = bias;
+
+    }
+
+
+    fpPixel             inputScale;             // scale and bias on input to compressor
+    fpPixel             inputBias;
+
+    void ScaleBiasInput(fpPixel & scale, fpPixel & bias)
+    {
+        inputScale = scale;
+        inputBias = bias;
+
+    }
+
+     ///////////////////////////////////////////////////////////////////////////////////
+
+    bool                bConvertToGreyScale;
+    fpPixel             greyScaleWeight;
+
+    void SetGreyScale(fpPixel & w)
+    {
+        bConvertToGreyScale = true;
+        greyScaleWeight = w;
+
+    }
+
+
+    
+
+    /////////////////////////////////////////////////////////////////////////////
+    fpPixel             brightness;
+    fpPixel             contrast;
+
+
+    void SetBrightnessAndContrast(fpPixel & _brightness, fpPixel & _contrast)
+    {
+        brightness = _brightness;
+        contrast = _contrast;
+    }
+
+
+
+    ///////////   general enables
+   /////////////////////////////////////////////////////////////////////////////
+    nvBoolean           bOutputWrap;          // wrap the values (before clamping to the format range) 
+                                    // when outputting to the desired format
+
+    nvBoolean           bCalcLuminance; // convert color to luminance for 'L' formats
+
+    nvBoolean           bSwapRB;             // swap color positions R and G
+	nvBoolean           bSwapRG;             // swap color positions R and G
+
+ 
+    nvBoolean           bForceDXT1FourColors;  // do not let DXT1 use 3 color representation
+
+    
+    nvBoolean           bRGBE;              // rgba_t is in RGBE format
+    
+    nvBoolean           bCreateOnePalette;      // All 4x4 compression blocks share the same palette
+
+
+
+
+    ///////////////////  DISABLED
+
+    nvBoolean           bDitherColor;       // enable dithering during 16 bit conversion
+    nvBoolean           bDitherMip0;        // enable dithering during 16 bit conversion for each MIP level (after filtering)
+    
+    
+    nvBoolean           bPreModulateColorWithAlpha;    // modulate color by alpha 
+    nvBoolean           bAlphaFilterModulate;            // modulate color by alpha for filtering only
+
+
+
+    ///////////////////////// USER DATA
+
+    void *              user_data;               // user supplied values passed down to write functions
+
+} ;
+
diff --git a/NifProps/dds/tPixel.h b/NifProps/dds/tPixel.h
new file mode 100644
index 0000000000000000000000000000000000000000..d34f9e8663bbdd2b1392aa4af6d1d683f8b03153
--- /dev/null
+++ b/NifProps/dds/tPixel.h
@@ -0,0 +1,1840 @@
+#pragma once
+
+#include <math.h>
+#include <memory.h>
+#include "tVector.h"
+#include "nvErrorCodes.h"
+
+#pragma warning(disable : 4201)
+
+namespace nv
+{
+// modulo value x between [lo,hi]
+// allows value 'hi'
+template < class _Type > 
+inline _Type Clamp(const _Type &x, 
+                   const _Type &lo, 
+                   const _Type &hi)
+{
+    if (x < lo)
+        return lo;
+    else if (x > hi)
+        return hi;
+    else
+        return x;
+}
+
+
+inline int iClamp(int x, int lo, int hi)
+{
+    if (x < lo)
+        return lo;
+    if (x > hi)
+        return hi;
+    return x;
+}
+
+inline float fClamp(float x, float lo, float hi)
+{
+    if (x < lo)
+        return lo;
+    if (x > hi)
+        return hi;
+    return x;
+}
+
+
+inline int fmod(int x, int size)
+{
+    return x % size;
+}
+
+inline __int64 fmod(__int64 x, __int64 size)
+{
+    return x % size;
+}
+inline unsigned __int64 fmod(unsigned __int64 x, unsigned __int64 size)
+{
+    return x % size;
+}
+
+
+inline float __cdecl fmod(float _X, float _Y)
+{
+    return ( fmodf(_X, _Y) ); 
+}
+
+// calcMaxMipmap
+//  calculates max # of mipmap levels for given texture size
+inline size_t calcMaxMipmap(size_t w, size_t h)
+{
+    size_t n = 0;
+    size_t count = 0;
+
+    assert(w >= 0);
+    assert(h >= 0);
+
+    if (w < h)
+        count = h;
+    else
+        count = w;
+
+    while (count)
+    {
+        n++; 
+        count >>= 1; 
+    }
+    return n;
+}
+
+
+inline size_t calcMaxMipmap(size_t w, size_t h, size_t d)
+{
+    size_t n = 0;
+    size_t count = 0;
+
+    assert(w >= 0);
+    assert(h >= 0);
+    assert(d >= 0);
+
+    if (w < h)
+        count = h;
+    else
+        count = w;
+
+    if (d > count)
+        count = d;
+
+
+    while (count)
+    {
+        n++; 
+        count >>= 1; 
+    }
+    return n;
+}
+
+
+// get next mip level size
+inline size_t NextMip(size_t m)
+{
+    size_t next = m / 2; // round down
+    if (next == 0)
+        return 1;
+    else
+        return next;
+}
+
+
+
+// lo = 0;
+// allow hi value
+template < class _Type > 
+inline _Type Modulo(const _Type &x, const _Type &hi)
+{
+    if (x >= 0 && x <= hi)
+        return x;
+
+    _Type f = fmod(x, hi);
+    
+    if (f < 0)
+        f += hi;
+
+    return f;
+}
+// does not allow x == size
+inline int iModulo(int x, int size)
+{
+    if (x < 0)
+    {
+        int n = x / size;
+        x += size * (n + 1);
+    }
+        
+    return x % size;
+}
+
+
+
+template < class _Type > 
+inline _Type Modulo(const _Type &x, const _Type &lo, const _Type &hi)
+{
+    if (x >= lo && x <= hi)
+        return x;
+
+    _Type dw = hi - lo;
+    _Type t = x - lo;
+
+    _Type f = fmod(t, dw);
+
+    
+    if (f < 0)
+        f += dw;
+
+    f += lo;
+
+    return f;
+}
+
+}
+
+
+
+
+#pragma pack(push,4)
+
+// red and green
+class v16u16_t	
+{
+public:
+
+    union
+    {
+        short uv[4];
+        struct
+        {
+            short u;
+            short v;
+        };
+    };
+    v16u16_t & operator += ( const v16u16_t & v );     // incrementation by a Vec4f
+
+
+    void set(unsigned short _u, unsigned short _v)
+    {
+        u = _u;
+        v = _v;
+    }
+};
+
+class r12g12b8_t	
+{
+public:
+
+    union
+    {
+        
+        struct
+        {
+            unsigned long r:12;
+            unsigned long g:12;
+            unsigned long b:8;
+        };
+    };
+    r12g12b8_t & operator += ( const r12g12b8_t& v );     // incrementation by a Vec4f
+
+
+    void set(unsigned long _r, unsigned long _g, unsigned long _b)
+    {
+        r = _r;
+        g = _g;
+        b = _b;
+    }
+};
+
+
+
+class rgba_t	
+{
+public:
+
+    union
+    {
+        unsigned long u;
+        unsigned char p[4];
+        struct
+        {
+            unsigned char r;
+            unsigned char g;
+            unsigned char b;
+            unsigned char a;
+        };
+    };
+
+    rgba_t() 
+    {
+    }
+
+    // 
+    
+    unsigned long bgra() 
+    {
+        
+        return ((unsigned long)a << 24) | ((unsigned long)r << 16) | ((unsigned long)g << 8) | ((unsigned long)b);
+    }
+    rgba_t(unsigned char _r, unsigned char _g, unsigned char _b,unsigned char _a) 
+    {
+        a = _a; 
+        r = _r; 
+        g = _g;
+        b = _b;
+    }
+
+    rgba_t & operator += ( const rgba_t& v )     // incrementation by a rgba_t
+    {
+        r = (unsigned char)nv::Clamp((int)((int)r + (int)v.r), 0, 255);   
+        g = (unsigned char)nv::Clamp((int)g + (int)v.g, 0, 255);   
+        b = (unsigned char)nv::Clamp((int)b + (int)v.b, 0, 255);   
+        a = (unsigned char)nv::Clamp((int)a + (int)v.a, 0, 255);   
+
+        return *this;
+    }
+
+    rgba_t & operator -= ( const rgba_t& v );     // decrementation by a rgba_t
+    rgba_t & operator *= ( const float d );     // multiplication by a constant
+    rgba_t & operator /= ( const float d );     // division by a constant
+
+
+    rgba_t& operator = (const rgba_t& v)
+    { 
+        r = v.r; 
+        g = v.g; 
+        b = v.b; 
+        a = v.a; 
+        return *this; 
+    }
+
+    friend rgba_t operator + (const rgba_t & v1, const rgba_t& v2)
+    {
+
+        int r,g,b,a;
+        r = nv::Clamp((int)v1.r + (int)v2.r, 0, 255);   
+        g = nv::Clamp((int)v1.g + (int)v2.g, 0, 255);   
+        b = nv::Clamp((int)v1.b + (int)v2.b, 0, 255);   
+        a = nv::Clamp((int)v1.a + (int)v2.a, 0, 255);  
+
+        return rgba_t((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
+    }
+
+    friend rgba_t operator / (const rgba_t& v, float s)
+    {
+        return rgba_t(
+            (unsigned char)(v.r/s), 
+            (unsigned char)(v.g/s), 
+            (unsigned char)(v.b/s), 
+            (unsigned char)(v.a/s));
+    }
+
+    friend rgba_t operator / (const rgba_t& v, int s)
+    {
+        return rgba_t(
+            (unsigned char)(v.r/s), 
+            (unsigned char)(v.g/s), 
+            (unsigned char)(v.b/s), 
+            (unsigned char)(v.a/s));
+    }
+
+    void set(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a)
+    {
+        r = _r;
+        g = _g;
+        b = _b;
+        a = _a;
+    }
+
+    void SetToZero()
+    {
+        r = g = b = a = 0;
+    }
+};
+
+class rgba16_t	
+{
+public:
+
+    union
+    {
+        //unsigned __int64 u;
+        unsigned short rgba[4];
+        struct
+        {
+            unsigned short r;
+            unsigned short g;
+            unsigned short b;
+            unsigned short a;
+        };
+    };
+
+    rgba16_t() 
+    {
+    }
+    rgba16_t(unsigned short _r, unsigned short _g, unsigned short _b,unsigned short _a) 
+    {
+        a = _a; 
+        r = _r; 
+        g = _g;
+        b = _b;
+    }
+
+    rgba16_t & operator += ( const rgba16_t& v )     // incrementation by a rgba_t
+    {
+        r = (unsigned char)nv::Clamp((int)r + (int)v.r, 0, 65535);   
+        g = (unsigned char)nv::Clamp((int)g + (int)v.g, 0, 65535);   
+        b = (unsigned char)nv::Clamp((int)b + (int)v.b, 0, 65535);   
+        a = (unsigned char)nv::Clamp((int)a + (int)v.a, 0, 65535);   
+
+        return *this;
+    }
+
+    rgba16_t & operator -= ( const rgba16_t& v );     // decrementation by a rgba_t
+    rgba16_t & operator *= ( const float d );     // multiplication by a constant
+    rgba16_t & operator /= ( const float d );     // division by a constant
+
+
+    rgba16_t& operator = (const rgba16_t& v)
+    { 
+        r = v.r; 
+        g = v.g; 
+        b = v.b; 
+        a = v.a; 
+        return *this; 
+    }
+
+    friend rgba16_t operator + (const rgba16_t & v1, const rgba16_t& v2)
+    {
+
+        int r,g,b,a;
+        r = nv::Clamp((int)v1.r + (int)v2.r, 0, 65535);   
+        g = nv::Clamp((int)v1.g + (int)v2.g, 0, 65535);   
+        b = nv::Clamp((int)v1.b + (int)v2.b, 0, 65535);   
+        a = nv::Clamp((int)v1.a + (int)v2.a, 0, 65535);  
+
+        return rgba16_t((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
+    }
+
+    friend rgba16_t operator / (const rgba16_t& v, float s)
+    {
+        return rgba16_t((unsigned short)(v.r/s), 
+            (unsigned short)(v.g/s), 
+            (unsigned short)(v.b/s), 
+            (unsigned short)(v.a/s));
+    }
+
+    friend rgba16_t operator / (const rgba16_t& v, int s)
+    {
+        return rgba16_t(
+            (unsigned short)(v.r/s), 
+            (unsigned short)(v.g/s), 
+            (unsigned short)(v.b/s), 
+            (unsigned short)(v.a/s));
+    }
+
+    void set(unsigned short _r, unsigned short _g, unsigned short _b, unsigned short _a)
+    {
+        r = _r;
+        g = _g;
+        b = _b;
+        a = _a;
+    }
+};
+
+
+class urgba_t	
+{
+public:
+
+    union
+    {
+        unsigned long u;
+        char rgba[4];
+        struct
+        {
+            char r;
+            char g;
+            char b;
+            char a;
+        };
+    };
+    urgba_t & operator += ( const urgba_t& v );     // incrementation by a Vec4f
+
+
+    void set(char _r, char _g, char _b, char _a)
+    {
+        r = _r;
+        g = _g;
+        b = _b;
+        a = _a;
+    }
+};
+
+
+ 
+
+class q8w8v8u8_t	
+{
+public:
+
+    union
+    {
+        char qwvu[4];
+        struct
+        {
+            char q;
+            char w;
+            char v;
+            char u;
+        };
+    };
+    q8w8v8u8_t & operator += ( const q8w8v8u8_t& v );     // incrementation by a Vec4f
+
+
+    void set(char _r, char _g, char _b, char _a)
+    {
+        q = _r;
+        w = _g;
+        v = _b;
+        u = _a;
+    }
+};
+
+
+
+
+
+
+
+#define _R 0
+#define _G 1
+#define _B 2
+#define _A 3
+
+
+
+
+class fpPixel
+{
+public:
+    union
+    {
+        float p[4];
+        struct
+        {
+            float r;
+            float g;
+            float b;
+            float a;
+        };
+        struct
+        {
+            float x;
+            float y;
+            float z;
+            float w;
+        };
+
+    };
+
+    void SetToZero()
+    {
+        r = 0;
+        g = 0;
+        b = 0;
+        a = 0;
+
+    }
+
+
+    void Clamp(fpPixel & lo, fpPixel & hi)
+    {
+
+        r = nv::Clamp(r, lo.r, hi.r);
+        g = nv::Clamp(g, lo.g, hi.g);
+        b = nv::Clamp(b, lo.b, hi.b);
+        a = nv::Clamp(a, lo.a, hi.a);
+    }
+
+    void Wrap(fpPixel & lo, fpPixel & hi)
+    {
+
+        r = nv::Modulo(r, lo.r, hi.r);
+        g = nv::Modulo(g, lo.g, hi.g);
+        b = nv::Modulo(b, lo.b, hi.b);
+        a = nv::Modulo(a, lo.a, hi.a);
+
+
+
+
+    }
+
+     
+    void dot(fpPixel & w)
+    {
+        float grey = r * w.r + 
+                     g * w.g + 
+                     b * w.b + 
+                     a * w.a;
+        r = grey;
+        g = grey;
+        b = grey;
+
+    }
+
+
+
+    //float& operator () ( int i) { return p[i]; };       // indexing
+    //const float& operator()(int i) const { return p[i];}
+
+
+
+    fpPixel() {}
+    fpPixel(const float _r, const float _g, const float _b, const float _a) 
+    {
+        a = _a; 
+        r = _r; 
+        g = _g;
+        b = _b;
+    }
+
+
+    fpPixel(const fpPixel& v)
+    {
+        a = v.a; 
+        r = v.r; 
+        g = v.g;
+        b = v.b;
+    }          // copy constructor
+
+    void set(const float _r, const float _g, const float _b, const float _a)
+    {
+        a = _a; 
+        r = _r; 
+        g = _g;
+        b = _b;
+    }
+
+    void set(const fpPixel& v)
+    {
+        a = v.a; 
+        r = v.r; 
+        g = v.g;
+        b = v.b;
+    }
+
+
+    fpPixel & operator += ( const fpPixel& v )     // incrementation by a rgba_t
+    {
+        r += v.r;   
+        g += v.g;   
+        b += v.b;   
+        a += v.a;   
+
+        return *this;
+    }
+
+
+    fpPixel & operator -= ( const fpPixel& v )     // incrementation by a rgba_t
+    {
+        r -= v.r;   
+        g -= v.g;   
+        b -= v.b;   
+        a -= v.a;   
+
+        return *this;
+    }
+
+
+    fpPixel & operator *= ( const fpPixel& v )     // incrementation by a rgba_t
+    {
+        r *= v.r;   
+        g *= v.g;   
+        b *= v.b;   
+        a *= v.a;   
+
+        return *this;
+    }
+
+    fpPixel & operator /= ( const fpPixel& v )     // incrementation by a rgba_t
+    {
+        r /= v.r;   
+        g /= v.g;   
+        b /= v.b;   
+        a /= v.a;   
+
+        return *this;
+    }
+
+    fpPixel & operator /= ( const float& s  )     // incrementation by a rgba_t
+    {
+        r /= s;   
+        g /= s;   
+        b /= s;   
+        a /= s;   
+
+        return *this;
+    }
+
+    fpPixel & operator = ( const fpPixel& v );      // assignment of a Vec3f         
+
+
+
+    friend fpPixel operator + (const fpPixel& v1, const fpPixel& v2)
+    {
+        return fpPixel(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
+    }
+
+    friend fpPixel operator / (const fpPixel& v, float s)
+    {
+        return fpPixel(v.r/s, v.g/s, v.b/s, v.a/s);
+
+    }
+    friend int operator == (const fpPixel& v1, const fpPixel& v2);      // v1 == v2 ?
+
+    NV_ERROR_CODE normalize()
+    {
+        double u;
+        u = x * x + y * y + z * z;
+
+        if ( fabs(u - 1.0) < 1e-12)
+            return NV_OK; // already normalized
+
+        if ( fabs((double)u) < 1e-12)
+        {
+            x = y = z = 0.0f;
+            return NV_CANT_NORMALIZE;
+        }
+
+
+        u = 1.0 / sqrt(u);
+
+
+        x = (float)(x*u);
+        y = (float)(y*u);
+        z = (float)(z*u);
+
+        return NV_OK;
+    }
+
+
+};
+
+
+
+class fpPixel3
+{
+public:
+    union
+    {
+        float p[3];
+        struct
+        {
+            float r;
+            float g;
+            float b;
+        };
+        struct
+        {
+            float x;
+            float y;
+            float z;
+        };
+
+    };
+
+
+    void SetToZero()
+    {
+        r = 0;
+        g = 0;
+        b = 0;
+    }
+    
+    //float& operator () ( int i) { return p[i]; };       // indexing
+    //const float& operator()(int i) const { return p[i];}
+
+
+
+    fpPixel3() {}
+    fpPixel3(const float _r, const float _g, const float _b) 
+    {
+        r = _r; 
+        g = _g;
+        b = _b;
+    }
+
+
+    fpPixel3(const fpPixel3& v)
+    {
+        r = v.r; 
+        g = v.g;
+        b = v.b;
+    }          // copy constructor
+
+    void set(const float _r, const float _g, const float _b)
+    {
+        r = _r; 
+        g = _g;
+        b = _b;
+    }
+
+    void set(const fpPixel3& v)
+    {
+        r = v.r; 
+        g = v.g;
+        b = v.b;
+    }
+
+    fpPixel3 & operator += ( const fpPixel3& v );     // incrementation by a Vec4f
+
+    fpPixel3 & operator = ( const fpPixel3& v );      // assignment of a Vec3f         
+    fpPixel3 & operator -= ( const fpPixel3& v );     // decrementation by a Vec3f
+    fpPixel3 & operator *= ( const float d );     // multiplication by a constant
+    fpPixel3 & operator /= ( const float d );     // division by a constant
+
+
+
+    friend fpPixel3 operator + (const fpPixel3& v1, const fpPixel3& v2)
+    {
+        return fpPixel3(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b);
+    }
+
+    friend fpPixel3 operator / (const fpPixel3& v, float s)
+    {
+        return fpPixel3(v.r/s, v.g/s, v.b/s);
+
+    }
+    friend int operator == (const fpPixel3& v1, const fpPixel3& v2);      // v1 == v2 ?
+
+    NV_ERROR_CODE normalize()
+    {
+        double u;
+        u = x * x + y * y + z * z;
+
+        if ( fabs(u - 1.0) < 1e-12)
+            return NV_OK; // already normalized
+
+        if ( fabs((double)u) < 1e-12)
+        {
+            x = y = z = 0.0f;
+            return NV_CANT_NORMALIZE;
+        }
+
+
+        u = 1.0 / sqrt(u);
+
+
+        x = (float)(x*u);
+        y = (float)(y*u);
+        z = (float)(z*u);
+
+        return NV_OK;
+    }
+
+
+};
+
+
+typedef fpPixel * fp_i;
+
+
+inline int operator == (const fpPixel& v1, const fpPixel& v2)
+{
+    return 
+        v1.a == v2.a && 
+        v1.r == v2.r && 
+        v1.b == v2.g && 
+        v1.g == v2.b;
+}
+
+inline fpPixel& fpPixel::operator = (const fpPixel& v)
+{ 
+    a = v.a; 
+    r = v.r; 
+    g = v.g; 
+    b = v.b; 
+    return *this; 
+}
+
+
+
+
+
+
+
+template <class _Type>
+class nvImage 
+{
+    size_t m_width;
+    size_t m_height;
+    nvVector<_Type> m_pixels;
+
+    bool m_RGBE;
+
+
+public:
+    void SetRGBE(bool b)
+    {
+      m_RGBE = b;
+    }
+     
+    bool isRGBE() const
+    {
+        return m_RGBE;
+    }
+
+
+
+    size_t size()
+    {
+        return m_width * m_height;
+    }
+    
+
+    nvImage < _Type > & operator = ( const nvImage < _Type >& v ) 
+    {
+
+        // resize and copy over
+        resize(v.width(), v.height());
+
+        m_pixels = v.m_pixels;
+        m_RGBE = v.m_RGBE;
+
+        return *this; 
+    }
+
+
+    _Type& operator [] ( size_t i) 
+    {
+#ifdef _DEBUG
+        assert(i < m_width * m_height);
+#endif
+        return m_pixels[i]; 
+    };  
+    
+    const _Type& operator[](size_t i) const 
+    { 
+#ifdef _DEBUG
+        assert(i < m_width * m_height);
+#endif
+        return m_pixels[i];
+    }
+
+    _Type & operator () (const size_t &y, const size_t &x) 
+    {
+#if _DEBUG
+        assert(y < m_height);
+        assert(x < m_width);
+#endif
+        return m_pixels[y * m_width + x]; 
+
+    }
+    const _Type & operator () (const size_t &y, const size_t &x) const  
+    {
+#if _DEBUG
+        assert(y < m_height);
+        assert(x < m_width);
+#endif
+        return m_pixels[y * m_width + x]; 
+
+    }
+
+
+    size_t width() const
+    {
+        return m_width;
+
+    }
+
+    size_t height() const
+    {
+        return m_height;
+
+    }
+
+
+
+    _Type * pixels(size_t n = 0)
+    {
+        
+        return &m_pixels[n];
+    }
+    _Type * pixelsXY(size_t x, size_t y)
+    {
+        return &m_pixels[y * width() + x];
+    }
+    _Type * pixelsXY_Safe(size_t x, size_t y)
+    {
+        if (m_pixels.size() == 0)
+            return 0;
+        else
+            return &m_pixels[y * width() + x];
+    }
+
+    _Type * pixelsYX(size_t y, size_t x)
+    {
+        return &m_pixels[y * width() + x];
+
+    }
+    // row / column
+    _Type * pixelsRC(size_t y, size_t x)
+    {
+        return &m_pixels[y * width() + x];
+
+    }
+
+
+    _Type & pixel_ref(size_t n = 0)
+    {
+        return m_pixels[n];
+    }
+    _Type & pixelsXY_ref(size_t x, size_t y)
+    {
+        return m_pixels[y * width() + x];
+    }
+
+    _Type & pixelsYX_ref(size_t y, size_t x)
+    {
+        return m_pixels[y * width() + x];
+
+    }
+    // row / column
+    _Type & pixelsRC_ref(size_t y, size_t x)
+    {
+        return m_pixels[y * width() + x];
+
+    }
+
+    _Type * pixelsXY_wrapped(int x, int y)
+    {
+        y = mod(y, m_height);
+        x = mod(x, m_width);
+
+        return &m_pixels[y * m_width + x];
+    }
+
+
+
+    nvImage( const nvImage < _Type > & other)
+    {
+        m_width = other.m_width;
+        m_height = other.m_height;
+
+        m_pixels = other.m_pixels;
+        m_RGBE = other.m_RGBE;
+
+
+    }
+
+    nvImage()
+    {
+        m_width = 0;
+
+        m_height = 0;
+        m_RGBE = false;
+
+        m_pixels.clear();
+        
+    };
+   ~nvImage()
+    {
+ 
+    }
+    void clear()
+    {
+        m_width = 0;
+        m_height = 0;
+        m_pixels.clear();
+    }
+
+    void resize(size_t width, size_t height)
+    {
+        m_pixels.resize(width * height);
+        m_width = width;
+        m_height = height;
+
+    }
+    void realloc(size_t width, size_t height)
+    {
+        m_pixels.realloc(width * height);
+        m_width = width;
+        m_height = height;
+
+    }
+
+    nvImage<_Type>(size_t width, size_t height)
+    {
+        m_pixels.resize(width * height);
+        m_width = width;
+        m_height = height;
+        m_RGBE = false;
+
+    };
+
+
+    void SwapRB()
+    {
+		
+        _Type * p = &m_pixels[0];
+        _Type tmp;
+		for(size_t i=0; i < m_width * m_height; i++ );
+		{
+
+
+            tmp.r = p->r;
+            p->r = p->b;
+            p->b = tmp.r;
+
+	        p++;
+        } 
+    }
+
+
+
+    void Scale(_Type s)
+    {
+
+        _Type * p = &m_pixels[0];
+		for(size_t i=0; i < m_width * m_height; i++ );
+		{
+
+            *p++ *= s;
+        } 
+
+    }
+
+    void Bias(_Type b)
+    {
+
+        _Type * p = &m_pixels[0];
+		for(size_t i=0; i < m_width * m_height; i++ );
+		{
+
+            *p++ += b;
+        } 
+
+    }
+
+    
+    void dot(_Type w)
+    {
+
+
+        _Type * p = &m_pixels[0];
+		for(size_t i=0; i < m_width * m_height; i++ );
+		{
+
+            p->dot(w);
+            p++;
+        } 
+    }
+
+
+
+    void Clamp(_Type low, _Type hi)
+    {
+
+        _Type * p = &m_pixels[0];
+		for(size_t i=0; i < m_width * m_height; i++ );
+		{
+
+            p->Clamp(low, hi);
+            p++;
+        } 
+
+    }
+
+    void Wrap(_Type low, _Type hi)
+    {
+        _Type * p = &m_pixels[0];
+		for(size_t i=0; i < m_width * m_height; i++ );
+		{
+
+            p->Wrap(low, hi);
+            p++;
+        } 
+
+    }
+
+
+
+    void	FlipTopToBottom()
+    {
+
+        _Type * swap = new _Type[ m_width];
+
+        size_t row;
+
+        _Type * end_row;
+        _Type * start_row;
+
+        size_t len = sizeof(_Type) * m_width;
+
+        for( row = 0; row < m_height / 2; row ++ )
+        {
+            end_row =   &m_pixels[ m_width * ( m_height - row - 1) ];
+            start_row = &m_pixels[ m_width * row ];
+
+            // copy row toward end of image into temporary swap buffer
+            memcpy( swap, end_row, len );
+
+            // copy row at beginning to row at end
+            memcpy( end_row, start_row, len );
+
+            // copy old bytes from row at end (in swap) to row at beginning
+            memcpy( start_row, swap, len );
+        }
+
+        delete [] swap;
+    }
+
+    void SetToZero()
+    {
+
+        for(size_t i=0; i< m_width * m_height; i++)
+        {
+            pixel_ref(i).SetToZero();
+
+        }
+    }
+    void SetToZeroDirect()
+    {
+        for(size_t i=0; i< m_width * m_height; i++)
+        {
+            m_pixels[i] = 0;
+
+        }
+    }
+
+
+ 
+};
+
+
+
+
+
+typedef nvImage<rgba_t> RGBAImage;
+typedef nvVector<RGBAImage> RGBAImageArray;
+
+
+class RGBAMipMappedImage
+{
+    RGBAImageArray mipArray; // array of images, one for each MIP map RGBA
+
+
+public:
+
+
+    void resize(size_t width, size_t height, size_t nMIPMaps)
+    {
+        if (nMIPMaps == 0)
+            nMIPMaps = nv::calcMaxMipmap(width, height); 
+
+        mipArray.resize(nMIPMaps);
+
+        for(size_t mipLevel = 0;  mipLevel < nMIPMaps; mipLevel++)
+        {
+            RGBAImage & mip = mipArray[mipLevel];
+            
+            mip.resize(width, height);
+
+            width = nv::NextMip(width);
+            height = nv::NextMip(height);
+
+        }
+
+
+    }
+
+
+    RGBAMipMappedImage(int width, int height, int nMIPMaps)
+    {
+        resize(width, height, nMIPMaps);
+
+
+
+    }
+    RGBAMipMappedImage()
+    {
+
+
+
+    }
+
+
+    
+    RGBAImage & operator [] ( size_t i) { return mipArray[i]; };       // indexing
+    const RGBAImage& operator[](size_t i) const { return mipArray[i];}
+
+    size_t numMIPMaps() const
+    {
+        return mipArray.size();
+    }
+
+
+    void resize(size_t size)
+    {
+        mipArray.resize(size);
+    }
+    void realloc(size_t size)
+    {
+        mipArray.realloc(size);
+    }
+
+    size_t width() const 
+    {
+        if (mipArray.size() == 0)
+            return 0;
+        return mipArray[0].width();
+
+    }
+    size_t height() const 
+    {
+        if (mipArray.size() == 0)
+            return 0;
+        return mipArray[0].height();
+
+    }
+
+    void clear()
+    {
+        mipArray.clear();
+    }
+
+
+};
+
+
+class RGBAMipMappedCubeMap
+{
+    RGBAMipMappedImage cubeFaces[6]; // array of images, one for each MIP map RGBA
+
+public:
+
+    void resize(size_t width, size_t height, size_t nMIPMaps)
+    {
+        if (nMIPMaps == 0)
+            nMIPMaps = nv::calcMaxMipmap(width, height);
+
+        for(int f = 0; f < 6; f++)
+        {
+            RGBAMipMappedImage & mipFace = cubeFaces[f];
+            mipFace.resize(width, height, nMIPMaps);
+        }
+
+
+    }
+
+    RGBAMipMappedCubeMap(size_t width, size_t height, size_t nMIPMaps)
+    {
+        resize(width, height, nMIPMaps);
+
+    }
+
+    RGBAMipMappedCubeMap()
+    {
+    }    
+
+    RGBAMipMappedImage & operator [] ( size_t i) { return cubeFaces[i]; };       // indexing
+    const RGBAMipMappedImage& operator[](size_t i) const { return cubeFaces[i];}
+
+
+    size_t numMIPMaps() const
+    {
+        return cubeFaces[0].numMIPMaps();
+    }
+         
+    size_t height() const
+    {
+        return cubeFaces[0].height();
+    }
+         
+    size_t width() const
+    {
+        return cubeFaces[0].height();
+    }
+
+    void clear()
+    {
+        for(size_t f = 0; f < 6; f++)
+        {
+            RGBAMipMappedImage & mipFace = cubeFaces[f];
+            mipFace.clear();
+        }
+
+    }
+
+
+
+
+};
+
+
+
+typedef nvVector< RGBAImageArray > RGBAVolume;
+
+class RGBAMipMappedVolumeMap
+{
+    // array of MIP mapped images
+    RGBAVolume volumeArray; 
+
+public:
+
+    void resize(size_t width, size_t height, size_t depth, size_t nMIPMaps)
+    {
+        if (nMIPMaps == 0)
+            nMIPMaps = nv::calcMaxMipmap(width, height, depth);
+
+        volumeArray.resize(nMIPMaps);
+
+        size_t w = width;
+        size_t h = height;
+        size_t d = depth;
+
+        for(size_t mipLevel = 0; mipLevel < nMIPMaps; mipLevel++)
+        {
+
+            RGBAImageArray & volImage = volumeArray[mipLevel];
+
+            volImage.resize(d);
+
+
+            for(size_t slice = 0; slice < d; slice++)
+            {
+                RGBAImage & mipFace = volImage[slice];
+
+                mipFace.resize(w, h);
+            }
+            w = nv::NextMip(w);
+            h = nv::NextMip(h);
+            d = nv::NextMip(d);
+
+
+        }
+    }
+
+
+    RGBAMipMappedVolumeMap(size_t width, size_t height, size_t depth, size_t nMIPMaps)
+    {
+        resize(width, height, depth, nMIPMaps);
+    }
+
+
+    // mip level
+    RGBAImageArray & operator [] ( size_t i) { return volumeArray[i]; };       // indexing
+    const RGBAImageArray& operator[](size_t i) const { return volumeArray[i];}
+
+    RGBAMipMappedVolumeMap()
+    {
+    }
+    size_t numMIPMaps() const
+    {
+        return volumeArray.size();
+    }
+
+
+
+
+    const RGBAImageArray * vol0() const 
+    {
+        if (numMIPMaps() == 0)
+            return 0;
+                        
+        return &volumeArray[0];
+    }
+
+     
+    const RGBAImage * slice0() const 
+    {
+        const RGBAImageArray * v0 = vol0();
+
+        if (v0 == 0)
+            return 0;
+
+        if (v0->size() == 0)
+            return 0;
+
+        const RGBAImageArray &array = *v0;
+
+        return &array[0];
+    }
+
+    size_t width() const
+    {
+        const RGBAImage * image0 = slice0();
+
+        if (image0 == 0)
+            return 0;
+
+        else 
+            return image0->width();
+
+    }
+    size_t height() const
+    {
+        const RGBAImage * image0 = slice0();
+
+        if (image0 == 0)
+            return 0;
+
+        else 
+            return image0->height();
+    }
+
+    size_t depth() const
+    {
+        const RGBAImageArray * v0 = vol0();
+
+        if (v0 == 0)
+            return 0;
+
+        return v0->size();
+
+    }
+
+
+
+
+};
+
+
+typedef nvMatrix<float> floatImage;
+typedef nvMatrix<fpPixel> fpImage;
+typedef nvMatrix<fpPixel3> fpImage3;
+
+
+//typedef nvImage<fpPixel> fpImage;
+//typedef nvImage<float> floatImage;
+//typedef nvImage<fpPixel3> fpImage3;
+
+
+
+typedef nvVector<fpImage> fpImageArray;
+
+
+
+
+class fpMipMappedImage
+{
+    fpImageArray mipArray; // array of images, one for each MIP map RGBA
+
+public:
+
+    fpMipMappedImage()
+    {
+    }
+
+    fpMipMappedImage(size_t width, size_t height, size_t nMIPMaps)
+    {
+        resize(width, height, nMIPMaps);
+    }
+
+    // copy constructor
+    fpMipMappedImage(const fpMipMappedImage& v)
+    {
+        // copy the images over
+        mipArray.resize(v.mipArray.size() );
+        for(size_t mipLevel = 0;  mipLevel < numMIPMaps(); mipLevel++)
+        {
+            fpImage & dst = mipArray[mipLevel];
+            const fpImage & src = v.mipArray[mipLevel];
+            dst = src;
+        }
+    }
+
+
+    void resize(size_t width, size_t height, size_t nMIPMaps)
+    {
+        if (nMIPMaps == 0)
+            nMIPMaps = nv::calcMaxMipmap(width, height); 
+
+        mipArray.resize(nMIPMaps);
+
+        for(size_t mipLevel = 0;  mipLevel < nMIPMaps; mipLevel++)
+        {
+            fpImage & mip = mipArray[mipLevel];
+            
+            mip.resize(width, height);
+
+            width = nv::NextMip(width);
+            height = nv::NextMip(height);
+        }
+    }
+
+    void FlipTopToBottom()
+    {
+        // copy the images over
+        for(size_t mipLevel = 0;  mipLevel < numMIPMaps(); mipLevel++)
+        {
+            fpImage & mip = mipArray[mipLevel];
+            mip.FlipTopToBottom();
+        }
+    }  
+             
+    fpImage & operator [] ( size_t i) { return mipArray[i]; };       // indexing
+    const fpImage& operator[](size_t i) const { return mipArray[i];}
+
+    void SetToZero()
+    { 
+        for(size_t mipLevel = 0;  mipLevel < numMIPMaps(); mipLevel++)
+        {
+            fpImage & mip = mipArray[mipLevel];
+            mip.SetToZero();
+        }
+    }
+
+    void clear()
+    {
+        mipArray.clear();
+    }
+    void realloc(size_t size)
+    {
+        mipArray.realloc(size);
+    }
+    void resize(size_t nMIPLevels)
+    {
+        mipArray.resize(nMIPLevels);
+    }
+
+    size_t numMIPMaps()  const
+    {
+        return mipArray.size();
+    }
+
+    size_t width()  const
+    {
+        return mipArray[0].width();
+
+    }
+    size_t height() const 
+    {
+        return mipArray[0].height();
+    }
+
+};
+
+
+class fpMipMappedCubeMap
+{
+    fpMipMappedImage cubeFaces[6]; // array of images, one for each MIP map RGBA
+
+public:
+
+    void resize(size_t width, size_t height, size_t nMIPMaps)
+    {
+        if (nMIPMaps == 0)
+            nMIPMaps = nv::calcMaxMipmap(width, height); 
+
+        for(size_t f = 0; f < 6; f++)
+        {
+            fpMipMappedImage & mipFace = cubeFaces[f];
+            mipFace.resize(width, height, nMIPMaps);
+        }
+
+
+    }
+
+    fpMipMappedCubeMap(int width, int height, int nMIPMaps)
+    {
+        resize(width, height, nMIPMaps);
+
+    }
+
+    fpMipMappedCubeMap()
+    {
+    }    
+
+    fpMipMappedImage & operator [] ( size_t i) { return cubeFaces[i]; };       // indexing
+    const fpMipMappedImage& operator[](size_t i) const { return cubeFaces[i];}
+
+
+    size_t numMIPMaps() const
+    {
+        return cubeFaces[0].numMIPMaps();
+    }
+           
+    size_t height() const
+    {
+        return cubeFaces[0].height();
+    }
+         
+    size_t width() const
+    {
+        return cubeFaces[0].height();
+    }
+         
+    void clear()
+    {
+        for(size_t f = 0; f < 6; f++)
+        {
+            fpMipMappedImage & mipFace = cubeFaces[f];
+            mipFace.clear();
+        }
+
+    }
+
+
+    void FlipTopToBottom()
+    {
+        for(size_t f = 0; f < 6; f++)
+        {
+            fpMipMappedImage & mipFace = cubeFaces[f];
+            mipFace.FlipTopToBottom();
+        }
+
+    }
+
+
+};
+
+
+// mip level, array
+typedef nvVector< fpImageArray > fpVolume;
+
+class fpMipMappedVolumeMap
+{
+    // array of MIP mapped images
+    fpVolume volumeArray; 
+
+public:
+
+    void resize(size_t width, size_t height, size_t depth, size_t nMIPMaps)
+    {
+        if (nMIPMaps == 0)
+            nMIPMaps = nv::calcMaxMipmap(width, height, depth); 
+        volumeArray.resize(nMIPMaps);
+
+        size_t w = width;
+        size_t h = height;
+        size_t d = depth;
+
+        for(size_t mipLevel = 0; mipLevel < nMIPMaps; mipLevel++)
+        {
+
+            fpImageArray & volImage = volumeArray[mipLevel];
+
+            volImage.resize(d);
+
+
+            for(size_t slice = 0; slice < d; slice++)
+            {
+                fpImage & mipFace = volImage[slice];
+
+                mipFace.resize(w, h);
+            }
+
+            w = nv::NextMip(w);
+            h = nv::NextMip(h);
+            d = nv::NextMip(d);
+
+        }
+    }
+
+    void FlipTopToBottom()
+    {
+        for(size_t mipLevel = 0; mipLevel < numMIPMaps(); mipLevel++)
+        {
+
+            fpImageArray & volImage = volumeArray[mipLevel];
+
+
+            for(size_t slice = 0; slice < volImage.size(); slice++)
+            {
+                fpImage & mipFace = volImage[slice];
+                mipFace.FlipTopToBottom();
+            }
+        }
+    }  
+
+
+     
+    void realloc(size_t size)
+    {
+        volumeArray.realloc(size);
+    }
+
+
+    fpMipMappedVolumeMap(size_t width, size_t height, size_t depth, size_t nMIPMaps)
+    {
+        resize(width, height, depth, nMIPMaps);
+    }
+
+
+    // mip level
+    fpImageArray & operator [] ( size_t i) { return volumeArray[i]; };       // indexing
+    const fpImageArray& operator[](size_t i) const { return volumeArray[i];}
+
+    fpMipMappedVolumeMap()
+    {
+    }
+    size_t numMIPMaps() const
+    {
+        return volumeArray.size();
+    }
+
+
+
+
+    const fpImageArray * vol0() const 
+    {
+        if (numMIPMaps() == 0)
+            return 0;
+                        
+        return &volumeArray[0];
+    }
+
+     
+    const fpImage * slice0() const 
+    {
+        const fpImageArray * v0 = vol0();
+
+        if (v0 == 0)
+            return 0;
+
+        if (v0->size() == 0)
+            return 0;
+
+        const fpImageArray &array = *v0;
+
+        return &array[0];
+    }
+
+    size_t width() const
+    {
+        const fpImage * image0 = slice0();
+
+        if (image0 == 0)
+            return 0;
+
+        else 
+            return image0->width();
+
+    }
+    size_t height() const
+    {
+        const fpImage * image0 = slice0();
+
+        if (image0 == 0)
+            return 0;
+
+        else 
+            return image0->height();
+    }
+
+    size_t depth() const
+    {
+        const fpImageArray * v0 = vol0();
+
+        if (v0 == 0)
+            return 0;
+
+        return v0->size();
+
+    }      
+
+    void clear()
+    {
+        volumeArray.clear();
+
+    }
+
+
+
+
+};
+#pragma pack(pop)
+
+
+
+
+#include "ConvertColor.h"   
+
diff --git a/NifProps/dds/tVector.h b/NifProps/dds/tVector.h
new file mode 100644
index 0000000000000000000000000000000000000000..22bbfade7180889cf3587f197668f64405bdd350
--- /dev/null
+++ b/NifProps/dds/tVector.h
@@ -0,0 +1,778 @@
+#pragma once
+#include <assert.h>
+
+
+
+
+template <class _Type>
+class nvMatrix
+{
+    _Type **m;
+
+    size_t rows, cols;
+
+public:
+
+    nvMatrix()
+    { 
+        rows = 0;
+        cols = 0;
+        m = 0;
+    }
+
+    // copy constructor
+    nvMatrix(const nvMatrix & v)
+    {         
+        rows = 0;
+        cols = 0;
+        m = 0;
+
+        resize(v.width(), v.height());
+
+        for(size_t i = 0; i < v.rows; i++)
+        {
+            for(size_t j = 0; j<v.cols; j++)
+                m[i][j] = v.m[i][j];
+        }
+    }
+
+    nvMatrix(size_t width, size_t height)
+    { 
+        m = 0;
+        rows = 0;
+        cols = 0;
+        resize(width, height);
+    }
+	~nvMatrix()
+	{
+		tvfree();
+	}
+
+    _Type& operator [] ( size_t i) 
+    {
+        size_t r = i / cols;
+        size_t c = i % cols;
+
+#if _DEBUG
+        assert(r < rows);
+        assert(c < cols);
+#endif
+        return m[r][c]; 
+    };  
+
+
+    _Type * pixels( size_t i = 0) 
+    {
+
+        size_t r = i / cols;
+        size_t c = i % cols;
+
+#if _DEBUG
+        assert(r < rows);
+        assert(c < cols);
+#endif
+        return &m[r][c]; 
+    };  
+
+
+    _Type & operator () (const size_t &r, const size_t &c) const
+    {
+#if _DEBUG
+        assert(r < rows);
+        assert(c < cols);
+#endif
+        return m[r][c]; 
+    }
+
+    _Type & operator () (const size_t &r, const size_t &c) 
+    {
+#if _DEBUG
+        assert(r < rows);
+        assert(c < cols);
+#endif
+        return m[r][c]; 
+    }
+
+    _Type * pixelsRC( size_t r,  size_t c) 
+    {
+#if _DEBUG
+        assert(r < rows);
+        assert(c < cols);
+#endif
+        return &m[r][c]; 
+    };  
+
+    _Type * pixelsXY( size_t x,  size_t y) 
+    {
+#if _DEBUG
+        assert(y < rows);
+        assert(x < cols);
+#endif
+        return &m[y][x]; 
+    };  
+
+
+    _Type * pixelsYX( size_t y,  size_t x) 
+    {
+#if _DEBUG
+        assert(y < rows);
+        assert(x < cols);
+#endif
+        return &m[y][x]; 
+    };  
+
+
+    _Type * pixelsXY_wrapped(int x, int y)
+    {
+        y = iModulo(y, (int)rows);
+        x = iModulo(x, (int)cols);
+
+        return &m[y][x]; 
+    }
+
+    size_t width() const
+    {
+        return cols;
+    }
+    size_t height() const
+    {
+        return rows;
+    }
+
+
+    void tvfree()
+    {
+        if (m)
+        {
+            for(size_t i = 0; i < rows; i++)
+                delete [] m[i];
+
+            delete [] m;
+            m = 0;
+            rows = 0;
+            cols = 0;
+        }
+    }
+
+    void tvallocate(size_t r, size_t c)
+    {
+		assert(m == NULL);
+
+        rows = r;
+        cols = c;
+        if (r == 0 || c == 0)
+            return;
+
+        m = new _Type *[r];
+        
+        
+        for(size_t i = 0; i < r; i++)
+        {
+            m[i] = new _Type [c];
+        }
+    }
+
+    nvMatrix & operator = ( const nvMatrix& v )
+    {
+        resize(v.width(), v.height());
+
+        for(size_t i = 0; i < v.rows; i++)
+        {
+            for(size_t j = 0; j<v.cols; j++)
+                m[i][j] = v.m[i][j];
+        }
+        return *this; 
+    }
+
+
+    void SetToZero()
+    {
+        for(size_t i = 0; i < rows; i++)
+        {
+            for(size_t j = 0; j<cols; j++)
+                m[i][j].SetToZero();
+        }
+    }
+
+
+  
+
+    // destructive
+    void resize(size_t width, size_t height)
+    {
+        if (height != rows || width != cols)
+        {
+            tvfree ();
+
+            tvallocate(height, width);
+        }
+    }
+
+
+    void Release()
+    {
+        tvfree ();
+    }
+    void clear()
+    {
+        tvfree();
+    }
+
+    size_t size() const
+    {
+        return rows * cols;
+    }
+
+
+
+    void FlipTopToBottom()
+    {
+        _Type * swap = new _Type[ cols];
+
+        size_t row;
+
+        //_Type * end_row;
+        //_Type * start_row;
+        int end_row;
+        int start_row;
+
+        size_t len = sizeof(_Type) * cols;
+
+        for( row = 0; row < rows / 2; row ++ )
+        {
+            /*end_row =   &m[( rows - row - 1) ][0];
+            start_row = &m[ row ][0];
+
+            // copy row toward end of image into temporary swap buffer
+            memcpy( swap, end_row, len );
+
+            // copy row at beginning to row at end
+            memcpy( end_row, start_row, len );
+
+            // copy old bytes from row at end (in swap) to row at beginning
+            memcpy( start_row, swap, len );*/
+
+            end_row =   rows - row - 1;
+            start_row =  row ;
+
+            // copy row toward end of image into temporary swap buffer
+            //memcpy( swap, end_row, len );
+            for(size_t i = 0; i < cols; i++)
+                swap[i] = m[end_row][i];
+
+            // copy row at beginning to row at end
+            //memcpy( end_row, start_row, len );
+            for(size_t i = 0; i < cols; i++)
+                m[end_row][i] = m[start_row][i];
+
+            // copy old bytes from row at end (in swap) to row at beginning
+            //memcpy( start_row, swap, len );
+            for(size_t i = 0; i < cols; i++)
+                m[start_row][i] = swap[i];
+
+        }
+
+        delete [] swap;
+    }
+
+
+    void Scale(_Type s)
+    {
+        for(size_t i = 0; i < rows; i++)
+        {
+            for(size_t j = 0; j<cols; j++)
+                m[i][j] *= s;
+        }
+    }
+
+    void Bias(_Type s)
+    {
+        for(size_t i = 0; i < rows; i++)
+        {
+            for(size_t j = 0; j<cols; j++)
+                m[i][j] += s;
+        }
+    }
+     
+    void dot(_Type w)
+    {
+        for(size_t i = 0; i < rows; i++)
+        {
+            for(size_t j = 0; j<cols; j++)
+                m[i][j].dot(w);
+        }
+    }
+    
+
+
+    void Clamp(_Type low, _Type hi)
+    {
+        for(size_t i = 0; i < rows; i++)
+        {
+            for(size_t j = 0; j<cols; j++)
+            {
+                m[i][j].Clamp(low, hi);
+            }
+        }
+    }
+
+    void Wrap(_Type low, _Type hi)
+    {
+        // to do
+        for(size_t i = 0; i < rows; i++)
+        {
+            for(size_t j = 0; j<cols; j++)
+            {
+
+                m[i][j].Wrap(low, hi);
+            }
+        }
+    }
+
+};
+
+/*
+#include <vector>
+
+template <class T>
+class nvVector : public std::vector<T>
+{
+public:
+
+	void resize(size_t newSize)
+	{
+		// Hack to emulate nvVector behaviour.
+		nvVector tmp;
+		((std::vector<T> &)tmp).resize(newSize);
+		std::swap(*this, tmp);
+	}
+
+	void realloc(size_t newSize)
+	{
+		std::vector<T>::resize(newSize);
+	}
+};
+
+
+template <class _Type>
+class nvVector
+{
+    _Type *m_data;
+
+    size_t allocated_size;
+    size_t current_size;
+
+public:
+
+    nvVector()
+    { 
+        m_data = 0;
+        current_size = 0;
+        allocated_size = 0;
+    }
+
+    nvVector(const nvVector<_Type> & other)
+    {
+        resize(other.size());
+
+        for(size_t i = 0; i < other.size(); i++)
+        {
+            m_data[i] = other.m_data[i];
+        }
+    }
+
+    ~nvVector()
+    {
+        Release();
+    }
+
+    static void tvfree(_Type * & ptr)
+    {
+        if (ptr)
+        {
+            delete [] ptr;
+            ptr = 0;
+        }
+    }
+
+    static _Type * tvallocate(size_t elements)
+    {
+        return new _Type[elements];
+    }
+
+    nvVector & operator = ( const nvVector& v )
+    {
+        resize(v.size());
+
+        for(size_t i = 0; i < v.size(); i++)
+        {
+            m_data[i] = v.m_data[i];
+        }
+        return *this; 
+    }
+
+
+    void FirstAllocation()
+    {
+        // start with 256 entries
+
+        tvfree (m_data);
+
+        allocated_size = 256;
+        current_size = 0;
+        m_data = tvallocate(allocated_size);
+    }
+
+
+
+    void resize(size_t newSize)
+    {
+        if (newSize != allocated_size)
+        {
+            allocated_size = newSize;
+
+            tvfree (m_data);
+
+            m_data = tvallocate(allocated_size);
+        }
+
+        current_size = newSize;
+    }
+
+    // keep old contents
+    void realloc(size_t newSize)
+    {
+        if (newSize != allocated_size)
+        {
+            _Type * oldData = new _Type[current_size];
+            size_t oldSize = current_size;
+
+            for(size_t i = 0; i < current_size; i++)
+            {
+                oldData[i] = m_data[i];
+            }
+
+
+            allocated_size = newSize;
+
+            tvfree (m_data);
+
+            m_data = tvallocate(allocated_size);
+
+            size_t minSize;
+            if (oldSize < newSize)
+                minSize = oldSize;
+            else
+                minSize = newSize;
+
+            for(size_t i = 0; i < minSize; i++)
+            {
+                m_data[i] = oldData[i];
+            }
+        }
+
+        current_size = newSize;
+    }
+
+    void push_back(_Type item)
+    {
+        if (allocated_size == 0)
+        {
+            FirstAllocation();
+        }
+        else if (current_size >= allocated_size)
+        {
+            allocated_size = allocated_size * 2;
+
+            _Type *temp = tvallocate(allocated_size);
+
+            // copy old data to new area
+            for(size_t i = 0; i< current_size; i++)
+                temp[i] = m_data[i];
+
+            tvfree (m_data);
+
+            m_data = temp;
+        }
+
+        
+        m_data[current_size] = item;
+        current_size++;
+     }
+
+    // indexing
+
+    _Type& operator [] ( size_t i) 
+    {
+#ifdef _DEBUG
+        assert(i < current_size);
+        assert(current_size <= allocated_size);
+#endif
+        return m_data[i]; 
+    };  
+    
+    const _Type& operator[](size_t i) const 
+    { 
+#ifdef _DEBUG
+        assert(i < current_size);
+        assert(current_size <= allocated_size);
+#endif
+        return m_data[i];
+    }
+
+    void Release()
+    {
+        tvfree (m_data);
+
+        current_size = 0;
+        allocated_size = 0;
+    }
+    void clear()
+    {
+        Release();
+    }
+
+    size_t size() const
+    {
+        return current_size;
+    }
+
+};
+*/
+
+#include <new>
+
+template<typename T>
+class nvVector {
+public:
+	
+	/** Ctor. */
+	nvVector() : m_buffer(NULL), m_size(0), m_buffer_size(0) {
+	}
+
+	/** Copy ctor. */
+	nvVector( const nvVector & a ) : m_buffer(NULL), m_size(0), m_buffer_size(0) {
+		copy( a.m_buffer, a.m_size); 
+	}
+
+
+	/** Ctor that initializes the array with the given elements. */
+	nvVector( const T * ptr, size_t num ) : m_buffer(NULL), m_size(0), m_buffer_size(0) {
+		copy( ptr, num); 
+	}
+
+
+	/** Dtor. */
+	~nvVector() {
+		clear();
+		allocate(0);
+	}
+
+
+	/** Const and save array access. */
+	const T & operator[]( size_t index ) const {
+		assert( index < m_size );
+		return m_buffer[index];
+	}
+
+	/** Safe array access. */
+	T & operator[] ( size_t index ) {
+		assert( index < m_size );
+		return m_buffer[index];
+	}
+
+
+	/** Get array size. */
+	size_t size() const { return m_size; }
+
+
+	/** Push an element at the end of the array. */
+	void push_back( const T & val ) {
+		// DO NOT pass elements of your own vector into
+		// push_back()!  Since we're using references,
+		// resize() may munge the element storage!
+		assert( &val < &m_buffer[0] || &val > &m_buffer[m_size] );
+		
+		int	new_size = m_size + 1;
+		resize( new_size );
+		m_buffer[new_size-1] = val;
+	}
+	
+	/** Pop and return element at the end of the array. */
+	void pop_back() {
+		assert( m_size > 0 );
+		resize( m_size-1 );
+	}
+
+	/** Get back element. */
+	const T & back() const {
+		assert( m_size > 0 );
+		return m_buffer[m_size-1];
+	}
+
+	/** Get back element. */
+	T & back() {
+		assert( m_size > 0 );
+		return m_buffer[m_size-1];
+	}
+
+	/** Get back element. */
+	const T & front() const {
+		assert( m_size > 0 );
+		return m_buffer[0];
+	}
+
+	/** Get back element. */
+	T & front() {
+		assert( m_size > 0 );
+		return m_buffer[0];
+	}
+
+
+	// nvVector semantics: realloc preserves contents, resize does not.
+	void realloc( size_t new_size ) {
+		resize(new_size);
+	}
+
+
+	/** Resize the array preserving existing elements. */
+	void resize( size_t new_size ) {
+		size_t i;
+		size_t old_size = m_size;
+		m_size = new_size;
+		
+		// Destruct old elements (if we're shrinking).
+		for( i = new_size; i < old_size; i++ ) {
+			(m_buffer+i)->~T();							// Explicit call to the destructor
+		}
+		
+		if( m_size == 0 ) {
+			//allocate(0);	// Don't shrink automatically.
+		}
+		else if( m_size <= m_buffer_size && m_size > m_buffer_size >> 1) {
+			// don't compact yet.
+			assert(m_buffer != NULL);
+		}
+		else {
+			size_t new_buffer_size;
+			if( m_buffer_size == 0 ) {
+				// first allocation
+				new_buffer_size = m_size;
+			}
+			else {
+				// growing
+				new_buffer_size = m_size + (m_size >> 2);
+			}
+			allocate( new_buffer_size );
+		}
+		
+		// Call default constructors
+		for( i = old_size; i < new_size; i++ ) {
+			new(m_buffer+i) T();							// placement new
+		}
+	}
+
+
+	/**
+	 * Resize the array preserving existing elements and initializing the
+	 * new ones with the given value.
+	 */
+	void resize( size_t new_size, const T &elem ) {
+		size_t i;
+		size_t old_size = m_size;
+		m_size = new_size;
+		
+		// Destruct old elements (if we're shrinking).
+		for( i = new_size; i < old_size; i++ ) {
+			(m_buffer+i)->~T();							// Explicit call to the destructor
+		}
+		
+		if( m_size == 0 ) {
+			//allocate(0);	// Don't shrink automatically.
+		}
+		else if( m_size <= m_buffer_size && m_size > m_buffer_size >> 1 ) {
+			// don't compact yet.
+			assert(m_buffer != NULL);
+		}
+		else {
+			size_t new_buffer_size;
+			if( m_buffer_size == 0 ) {
+				// first allocation
+				new_buffer_size = m_size;
+			}
+			else {
+				// growing
+				new_buffer_size = m_size + (m_size >> 2);
+			}
+			allocate( new_buffer_size );
+		}
+		
+		// Call copy constructors
+		for( i = old_size; i < new_size; i++ ) {
+			new(m_buffer+i) T( elem );					// placement new
+		}
+	}
+
+	/** Clear the buffer. */
+	void clear() {
+		resize(0);
+	}
+
+	/** Shrink the allocated array. */
+	void shrink() {
+		if( m_size < m_buffer_size) {
+			allocate(m_size);
+		}
+	}
+	
+	/** Preallocate space. */
+	void reserve( size_t desired_size ) {
+		if( desired_size > m_buffer_size ) {
+			allocate( desired_size );
+		}
+	}
+	
+
+	/** Assignment operator. */
+	void operator=( const nvVector & a ) {
+		copy( a.m_buffer, a.m_size );
+	}
+
+
+private:
+
+	/** Change buffer size. */
+	void allocate( size_t rsize ) {
+		
+		m_buffer_size = rsize;
+		
+		// free the buffer.
+		if( m_buffer_size == 0 ) {
+			if( m_buffer ) {
+				free( m_buffer );
+				m_buffer = NULL;
+			}
+		}
+		
+		// realloc the buffer
+		else {
+			if( m_buffer ) m_buffer = (T *) ::realloc( m_buffer, sizeof(T) * m_buffer_size );
+			else m_buffer = (T *) malloc( sizeof(T) * m_buffer_size );
+		}
+	}
+
+	/** Copy memory to our array. Resizes the array if needed. */
+	void copy( const T * ptr, size_t num ) {
+		resize( num );
+		for( size_t i = 0; i < m_size; i++ ) {
+			m_buffer[i] = ptr[i];
+		}
+	}
+
+private:
+
+	T * m_buffer;
+	size_t m_size;
+	size_t m_buffer_size;
+
+};
diff --git a/NifProps/dds/veroverrides.h b/NifProps/dds/veroverrides.h
new file mode 100644
index 0000000000000000000000000000000000000000..744b070ba4e54a642aabccaffc9a5c7f4e77ef26
--- /dev/null
+++ b/NifProps/dds/veroverrides.h
@@ -0,0 +1,15 @@
+// The to be #defined in a .h file included by a .rc file before maxversion.r
+
+
+#define MAXVER_INTERNALNAME "dds\0"//should  be overidden on a per-dll level
+#define MAXVER_ORIGINALFILENAME "dds.bmi\0"//should  be overidden on a per-dll level
+#define MAXVER_FILEDESCRIPTION "A DDS image IO plugin\0"//should  be overidden on a per-dll level
+#define MAXVER_COMMENTS "TECH: neil.hazzard\0"//should  be overidden on a per-dll level
+
+// #define MAXVER_PRODUCTNAME //generally not overridden at the maxversion.r level
+// #define MAXVER_COPYRIGHT //only in exceptions should this be overridden
+// #define MAXVER_LEGALTRADEMARKS //only in exceptions should this be overridden
+// #define MAXVER_COMPANYNAME //only in exceptions should this be overridden
+// #define MAX_VERSION_MAJOR //only in exceptions should this be overridden
+// #define MAX_VERSION_MINOR //only in exceptions should this be overridden
+// #define MAX_VERSION_POINT //only in exceptions should this be overridden