From f57dae1d5f443a48237500d6d831401eaecdccc3 Mon Sep 17 00:00:00 2001
From: Tazpn <tazpn@users.sourceforge.net>
Date: Wed, 18 Jul 2007 03:06:06 +0000
Subject: [PATCH] Add support for 20.1.0.3, 20.3.0.3, 20.3.0.6 nif formats.

---
 include/NIF_IO.h                         | 192 ++++++++++----
 include/gen/AVObject.h                   |   2 +-
 include/gen/ControllerLink.h             |  12 +-
 include/gen/Header.h                     |  21 +-
 include/gen/Morph.h                      |   2 +-
 include/gen/TexDesc.h                    |   9 +-
 include/gen/TexSource.h                  |   4 +-
 include/nif_basic_types.h                |  12 +-
 include/nif_versions.h                   |   3 +
 include/obj/NiControllerSequence.h       |   2 +-
 include/obj/NiExtraData.h                |   2 +-
 include/obj/NiFloatExtraDataController.h |   2 +-
 include/obj/NiGeometry.h                 |   4 +-
 include/obj/NiGeometryData.h             |  11 +-
 include/obj/NiImage.h                    |   2 +-
 include/obj/NiObjectNET.h                |   2 +-
 include/obj/NiPSysModifier.h             |   2 +-
 include/obj/NiPSysModifierCtlr.h         |   2 +-
 include/obj/NiSequence.h                 |   4 +-
 include/obj/NiSourceTexture.h            |   8 +-
 include/obj/NiStencilProperty.h          |   2 +
 include/obj/NiStringExtraData.h          |   2 +-
 include/obj/NiStringsExtraData.h         |   2 +-
 include/obj/NiTextKeyExtraData.h         |   2 +-
 include/obj/NiTriShape.h                 |   5 +
 include/obj/NiVertexColorProperty.h      |   8 +-
 include/obj/NiZBufferProperty.h          |   2 +-
 include/obj/bhkBoxShape.h                |   2 +-
 niflib.vcproj                            | 176 +++++++------
 src/NIF_IO.cpp                           | 139 +++++++++-
 src/gen/Header.cpp                       | 127 +++++++--
 src/gen/TexDesc.cpp                      |   3 +-
 src/niflib.cpp                           |  91 ++++++-
 src/obj/NiControllerSequence.cpp         |   6 +-
 src/obj/NiGeometry.cpp                   |  26 ++
 src/obj/NiGeometryData.cpp               |  52 ++--
 src/obj/NiSequence.cpp                   |   6 +-
 src/obj/NiSkinInstance.cpp               |   3 +-
 src/obj/NiSourceTexture.cpp              |  14 +-
 src/obj/NiStencilProperty.cpp            |  50 +++-
 src/obj/NiStringsExtraData.cpp           |   9 +-
 src/obj/NiTextKeyExtraData.cpp           |  49 +++-
 src/obj/NiTexturingProperty.cpp          | 311 ++++++++++++++++++-----
 src/obj/NiTriShape.cpp                   |  12 +-
 src/obj/NiVertexColorProperty.cpp        |  12 +-
 src/obj/NiZBufferProperty.cpp            |   4 +-
 src/obj/bhkBoxShape.cpp                  |   8 +-
 47 files changed, 1052 insertions(+), 369 deletions(-)

diff --git a/include/NIF_IO.h b/include/NIF_IO.h
index 898ac3b3..773f196f 100644
--- a/include/NIF_IO.h
+++ b/include/NIF_IO.h
@@ -12,6 +12,7 @@ All rights reserved.  Please see niflib.h for license. */
 #include "gen/enums_intl.h"
 #include "nif_math.h"
 #include "nif_versions.h"
+
 namespace Niflib {
 using namespace std;
 
@@ -98,102 +99,107 @@ void PackField( storage & dest, T new_value, size_t lshift, size_t num_bits ) {
 //--Basic Types--//
 
 //int
-void NifStream( int & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( int const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( int & val, istream& in, const NifInfo & info);
+void NifStream( int const & val, ostream& out, const NifInfo & info );
 
 //unsigned int
-void NifStream( unsigned int & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( unsigned int const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( unsigned int & val, istream& in, const NifInfo & info);
+void NifStream( unsigned int const & val, ostream& out, const NifInfo & info);
 
 //unsigned short
-void NifStream( unsigned short & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( unsigned short const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( unsigned short & val, istream& in, const NifInfo & info);
+void NifStream( unsigned short const & val, ostream& out, const NifInfo & info );
 
 //short
-void NifStream( short & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( short const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( short & val, istream& in, const NifInfo & info);
+void NifStream( short const & val, ostream& out, const NifInfo & info);
 
 //byte
-void NifStream( byte & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( byte const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( byte & val, istream& in, const NifInfo & info);
+void NifStream( byte const & val, ostream& out, const NifInfo & info);
 
 //bool
-void NifStream( bool & val, istream& in, const NifInfo & info = NifInfo() );  // version is significant
-void NifStream( bool const & val, ostream& out, const NifInfo & info = NifInfo() ); // version is significant
+void NifStream( bool & val, istream& in, const NifInfo & info);  // version is significant
+void NifStream( bool const & val, ostream& out, const NifInfo & info); // version is significant
 
 //float
-void NifStream( float & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( float const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( float & val, istream& in, const NifInfo & info);
+void NifStream( float const & val, ostream& out, const NifInfo & info);
 
 //string
-void NifStream( string & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( string const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( string & val, istream& in, const NifInfo & info);
+void NifStream( string const & val, ostream& out, const NifInfo & info);
 
 //--Structs--//
 
 //TexCoord
-void NifStream( TexCoord & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( TexCoord const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( TexCoord & val, istream& in, const NifInfo & info);
+void NifStream( TexCoord const & val, ostream& out, const NifInfo & info);
 
 //Triangle
-void NifStream( Triangle & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Triangle const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( Triangle & val, istream& in, const NifInfo & info);
+void NifStream( Triangle const & val, ostream& out, const NifInfo & info);
 
 //Vector3
-void NifStream( Vector3 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Vector3 const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Vector3 & val, istream& in, const NifInfo & info);
+void NifStream( Vector3 const & val, ostream& out, const NifInfo & info );
 
 //Float2
-void NifStream( Float2 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Float2 const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Float2 & val, istream& in, const NifInfo & info);
+void NifStream( Float2 const & val, ostream& out, const NifInfo & info );
 
 //Matrix22
-void NifStream( Matrix22 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Matrix22 const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( Matrix22 & val, istream& in, const NifInfo & info);
+void NifStream( Matrix22 const & val, ostream& out, const NifInfo & info);
 
 //Float3
-void NifStream( Float3 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Float3 const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Float3 & val, istream& in, const NifInfo & info);
+void NifStream( Float3 const & val, ostream& out, const NifInfo & info );
 
 //Matrix33
-void NifStream( Matrix33 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Matrix33 const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( Matrix33 & val, istream& in, const NifInfo & info);
+void NifStream( Matrix33 const & val, ostream& out, const NifInfo & info);
 
 //Float4
-void NifStream( Float4 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Float4 const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Float4 & val, istream& in, const NifInfo & info);
+void NifStream( Float4 const & val, ostream& out, const NifInfo & info );
 
 //Matrix44
-void NifStream( Matrix44 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Matrix44 const & val, ostream& out, const NifInfo & info = NifInfo() );
+void NifStream( Matrix44 & val, istream& in, const NifInfo & info);
+void NifStream( Matrix44 const & val, ostream& out, const NifInfo & info);
 
 //Color3
-void NifStream( Color3 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Color3 const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Color3 & val, istream& in, const NifInfo & info);
+void NifStream( Color3 const & val, ostream& out, const NifInfo & info );
 
 //Color4
-void NifStream( Color4 & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Color4 const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Color4 & val, istream& in, const NifInfo & info);
+void NifStream( Color4 const & val, ostream& out, const NifInfo & info );
 
 //Quaternion
-void NifStream( Quaternion & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( Quaternion const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( Quaternion & val, istream& in, const NifInfo & info);
+void NifStream( Quaternion const & val, ostream& out, const NifInfo & info );
 
 //HeaderString
 void NifStream( HeaderString & val, istream& in, NifInfo & info ); //Sets the passed in info
-void NifStream( HeaderString const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( HeaderString const & val, ostream& out, const NifInfo & info );
 ostream & operator<<( ostream & out, HeaderString const & val );
 
 //LineString
-void NifStream( LineString & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( LineString const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( LineString & val, istream& in, const NifInfo & info);
+void NifStream( LineString const & val, ostream& out, const NifInfo & info );
 ostream & operator<<( ostream & out, LineString const & val );
 
 //ShortString
-void NifStream( ShortString & val, istream& in, const NifInfo & info = NifInfo() );
-void NifStream( ShortString const & val, ostream& out, const NifInfo & info = NifInfo()  );
+void NifStream( ShortString & val, istream& in, const NifInfo & info);
+void NifStream( ShortString const & val, ostream& out, const NifInfo & info );
 ostream & operator<<( ostream & out, ShortString const & val );
 
+//IndexString
+void NifStream( IndexString & val, istream& in, const NifInfo & info );
+void NifStream( IndexString const & val, ostream& out, const NifInfo & info );
+ostream & operator<<( ostream & out, IndexString const & val );
+
 //--Templates--//
 
 void NifStream( Key<Quaternion> & key, istream& file, const NifInfo & info, KeyType type );
@@ -211,11 +217,11 @@ void NifStream( Key<T> & key, istream& file, const NifInfo & info, KeyType type
 	}
 
 	//Read data based on the type of key
-	NifStream( key.data, file );
+	NifStream( key.data, file, info );
 	if ( type == QUADRATIC_KEY ) {
 		//Uses Quadratic interpolation
-		NifStream( key.forward_tangent, file );
-		NifStream( key.backward_tangent, file );
+		NifStream( key.forward_tangent, file, info );
+		NifStream( key.backward_tangent, file, info );
 	} else if ( type == TBC_KEY ) {
 		//Uses TBC interpolation
 		key.tension = ReadFloat( file );
@@ -240,11 +246,11 @@ void NifStream( Key<T> const & key, ostream& file, const NifInfo & info, KeyType
 	}
 
 	//Read data based on the type of key
-	NifStream( key.data, file );
+	NifStream( key.data, file, info );
 	if ( type == QUADRATIC_KEY ) {
 		//Uses Quadratic interpolation
-		NifStream( key.forward_tangent, file );
-		NifStream( key.backward_tangent, file );
+		NifStream( key.forward_tangent, file, info );
+		NifStream( key.backward_tangent, file, info );
 	} else if ( type == TBC_KEY ) {
 		//Uses TBC interpolation
 		WriteFloat( key.tension, file);
@@ -258,6 +264,10 @@ void NifStream( Key<T> const & key, ostream & file, const NifInfo & info, int ty
 	NifStream( key, file, info, (KeyType)type );
 }
 
+template <> void NifStream( Key<IndexString> & key, istream& file, const NifInfo & info, KeyType type );
+template <> void NifStream( Key<IndexString> const & key, ostream& file, const NifInfo & info,  KeyType type );
+
+
 //The HexString function creates a formatted hex display of the given data for use in printing
 //a debug string for information that is not understood
 string HexString( const byte * src, unsigned int len );
@@ -265,5 +275,85 @@ string HexString( const byte * src, unsigned int len );
 //Byte
 ostream & operator<<( ostream & out, byte const & val );
 
+// strInfo
+struct NifInfo;
+class strInfo
+{
+public:
+	strInfo(NifInfo * value) : info(value) {}
+private:
+	NifInfo *info;
+	static const int infoIdx;
+	friend static ostream & operator<<( ostream & out, strInfo const & val );
+	friend static istream & operator>>( istream & out, strInfo & val );
+public:
+	static NifInfo * getInfo(ios_base& str) {
+		return (NifInfo *)str.pword(infoIdx);
+	}
+};
+
+static ostream & operator<<( ostream & out, strInfo const & val ) {
+	out.pword(strInfo::infoIdx) = (void*)val.info;
+	return (out);
+}
+
+static istream & operator>>( istream & istr, strInfo & val ) {
+	istr.pword(strInfo::infoIdx) = (void*)val.info;
+	return (istr);
+}
+
+
+// hdrInfo
+struct Header;
+class hdrInfo
+{
+public:
+	hdrInfo(Header * value) : info(value) {}
+private:
+	Header *info;
+	static const int infoIdx;
+	friend static ostream & operator<<( ostream & out, hdrInfo const & val );
+	friend static istream & operator>>( istream & out, hdrInfo & val );
+public:
+	static Header * getInfo(ios_base& str) {
+		return (Header *)str.pword(infoIdx);
+	}
+};
+
+static ostream & operator<<( ostream & out, hdrInfo const & val ) {
+	out.pword(hdrInfo::infoIdx) = (void*)val.info;
+	return (out);
+}
+
+static istream & operator>>( istream & istr, hdrInfo & val ) {
+	istr.pword(hdrInfo::infoIdx) = (void*)val.info;
+	return (istr);
+}
+
+class NifStreamBuf : public std::streambuf {
+	streamsize size; 
+	pos_type pos;
+public:
+	NifStreamBuf () : size(0), pos(0) {}
+private:
+	friend class NifSizeStream;
+    char *pbase( ) const { return NULL; }
+    char *pptr( ) const { return NULL; }
+    char *epptr( ) const { return NULL; }
+    virtual streamsize xsgetn( char_type *_Ptr, streamsize _Count ) { return 0; }
+    virtual streamsize xsputn(const char_type *_Ptr, streamsize _Count);
+	virtual streampos seekoff(streamoff, ios_base::seekdir, ios_base::openmode = ios_base::in | ios_base::out);
+	virtual streampos seekpos(streampos, ios_base::openmode = ios_base::in | ios_base::out);
+
+	void reset() { size = 0; pos = 0; }
+};
+
+class NifSizeStream : public std::ostream {
+	NifStreamBuf _buf;
+public:
+	NifSizeStream() : std::ostream( &_buf ) {}
+	void reset() { _buf.reset(); }
+};
+
 }
 #endif
diff --git a/include/gen/AVObject.h b/include/gen/AVObject.h
index 42f2a102..c78d5f8a 100644
--- a/include/gen/AVObject.h
+++ b/include/gen/AVObject.h
@@ -26,7 +26,7 @@ struct AVObject {
 	/*! Copy Operator */
 	NIFLIB_API AVObject & operator=( const AVObject & src );
 	/*! Object name. */
-	string name;
+	IndexString name;
 	/*! Object reference. */
 	NiAVObject * avObject;
 };
diff --git a/include/gen/ControllerLink.h b/include/gen/ControllerLink.h
index 823a51ae..f3051ffb 100644
--- a/include/gen/ControllerLink.h
+++ b/include/gen/ControllerLink.h
@@ -36,7 +36,7 @@ struct ControllerLink {
 	/*! Copy Operator */
 	NIFLIB_API ControllerLink & operator=( const ControllerLink & src );
 	/*! Name of a controllable object in another NIF file. */
-	string targetName;
+	IndexString targetName;
 	/*! Link to a controller. */
 	Ref<NiTimeController > controller;
 	/*! Link to an interpolator. */
@@ -56,7 +56,7 @@ struct ControllerLink {
 	 */
 	Ref<NiStringPalette > stringPalette;
 	/*! The name of the animated node. */
-	string nodeName;
+	IndexString nodeName;
 	/*!
 	 * Offset in the string palette where the name of the controlled node (NiNode,
 	 * NiTriShape, ...) starts.
@@ -66,7 +66,7 @@ struct ControllerLink {
 	 * Name of the property (NiMaterialProperty, ...), if this controller controls a
 	 * property.
 	 */
-	string propertyType;
+	IndexString propertyType;
 	/*!
 	 * Offset in the string palette where the property (NiMaterialProperty, ...)
 	 * starts, if this controller controls a property. Otherwise, -1.
@@ -76,7 +76,7 @@ struct ControllerLink {
 	 * Probably the object type name of the controller in the NIF file that is child of
 	 * the controlled object.
 	 */
-	string controllerType;
+	IndexString controllerType;
 	/*!
 	 * Apparently the offset in the string palette of some type of controller related
 	 * to Interpolator (for example, a 'NiTransformInterpolator' will have here a
@@ -89,14 +89,14 @@ struct ControllerLink {
 	 * Some variable string (such as 'SELF_ILLUM', '0-0-TT_TRANSLATE_U', 'tongue_out',
 	 * etc.).
 	 */
-	string variable1;
+	IndexString variable1;
 	/*!
 	 * Offset in the string palette where some variable string starts (such as
 	 * 'SELF_ILLUM', '0-0-TT_TRANSLATE_U', 'tongue_out', etc.). Usually, -1.
 	 */
 	unsigned int variableOffset1;
 	/*! Another variable string, apparently used for particle system controllers. */
-	string variable2;
+	IndexString variable2;
 	/*!
 	 * Offset in the string palette where some variable string starts (so far only
 	 * 'EmitterActive' and 'BirthRate' have been observed in official files, used for
diff --git a/include/gen/Header.h b/include/gen/Header.h
index 93b4bbab..b10cbb60 100644
--- a/include/gen/Header.h
+++ b/include/gen/Header.h
@@ -11,6 +11,8 @@ All rights reserved.  Please see niflib.h for license. */
 #include "../NIF_IO.h"
 #include "../obj/NiObject.h"
 
+// Include structures
+#include "ExportInfo.h"
 namespace Niflib {
 
 
@@ -48,15 +50,8 @@ struct Header {
 	 * circumstances.
 	 */
 	unsigned int userVersion2;
-	/*! Could be the name of the creator of the NIF file? */
-	ShortString creator;
-	/*! Unknown. Can be something like 'TriStrip Process Script'. */
-	ShortString exportInfo1;
-	/*!
-	 * Unknown. Possibly the selected option of the export script. Can be something
-	 * like 'Default Export Script'.
-	 */
-	ShortString exportInfo2;
+	/*! Unknown. */
+	ExportInfo exportInfo;
 	/*! Number of object types in this NIF file. */
 	mutable unsigned short numBlockTypes;
 	/*! List of all object types used in this NIF file. */
@@ -67,6 +62,14 @@ struct Header {
 	 * object_types[object_type_index[1]], etc.
 	 */
 	vector<unsigned short > blockTypeIndex;
+	/*! Array of block sizes? */
+	vector<unsigned int > blockSize;
+	/*! Number of strings. */
+	mutable unsigned int numStrings;
+	/*! Maximum string length. */
+	unsigned int maxStringLength;
+	/*! Strings. */
+	vector<string > strings;
 	/*! Unknown. */
 	unsigned int unknownInt2;
 	NIFLIB_HIDDEN NifInfo Read( istream& in );
diff --git a/include/gen/Morph.h b/include/gen/Morph.h
index d148bbc6..93d7d7dd 100644
--- a/include/gen/Morph.h
+++ b/include/gen/Morph.h
@@ -24,7 +24,7 @@ struct Morph {
 	/*! Copy Operator */
 	NIFLIB_API Morph & operator=( const Morph & src );
 	/*! Name of the frame. */
-	string frameName;
+	IndexString frameName;
 	/*! The number of morph keys that follow. */
 	mutable unsigned int numKeys;
 	/*!
diff --git a/include/gen/TexDesc.h b/include/gen/TexDesc.h
index 7fa4db0a..9f00b63f 100644
--- a/include/gen/TexDesc.h
+++ b/include/gen/TexDesc.h
@@ -29,13 +29,12 @@ struct TexDesc {
 	NIFLIB_API TexDesc & operator=( const TexDesc & src );
 	/*! NiSourceTexture object index. */
 	Ref<NiSourceTexture > source;
-	/*!
-	 * Determines how UV coordinaes that are outside the 0-1 range will be mapped to
-	 * the texture.
-	 */
+	/*! 0=clamp S clamp T, 1=clamp S wrap T, 2=wrap S clamp T, 3=wrap S wrap T */
 	TexClampMode clampMode;
-	/*! Determines how the texture will be scaled up and down. */
+	/*! 0=nearest, 1=bilinear, 2=trilinear, 3=..., 4=..., 5=... */
 	TexFilterMode filterMode;
+	/*! Texture mode flags. */
+	unsigned short flags;
 	/*! The texture coordinate set in NiGeometryData that this texture slot will use. */
 	unsigned int uvSet;
 	/*! 0? */
diff --git a/include/gen/TexSource.h b/include/gen/TexSource.h
index a00ea663..a2480877 100644
--- a/include/gen/TexSource.h
+++ b/include/gen/TexSource.h
@@ -38,7 +38,7 @@ struct TexSource {
 	 * is due to a feature in Morrowind resource manager: it loads name.ext,
 	 * textures/name.ext and textures/subdir/name.ext but NOT subdir/name.ext.
 	 */
-	string fileName;
+	IndexString fileName;
 	/*! Unknown. */
 	Ref<NiObject > unknownLink;
 	/*! Unknown. */
@@ -47,7 +47,7 @@ struct TexSource {
 	 * The original source filename of the image embedded by the referred NiPixelData
 	 * object.
 	 */
-	string originalFileName_;
+	IndexString originalFileName_;
 	/*! Pixel data object index. */
 	Ref<NiPixelData > pixelData;
 };
diff --git a/include/nif_basic_types.h b/include/nif_basic_types.h
index afba346c..b987dfac 100644
--- a/include/nif_basic_types.h
+++ b/include/nif_basic_types.h
@@ -23,6 +23,16 @@ struct LineString {
 	string line;
 };
 
+struct IndexString : public std::string {
+	IndexString() {}
+	IndexString( const IndexString & ref ) : std::string((std::string const &)ref) {}
+	IndexString( const std::string & ref ) : std::string(ref) {}
+	IndexString& operator=( const IndexString & ref ) { assign((std::string const &)ref); return *this; }
+	IndexString& operator=( const std::string & ref ) { assign(ref); return *this; }
+	operator std::string const &() const { return *this; }
+	operator std::string &() { return *this; }
+};
+
 //--Non-mathematical Basic Types--//
 #ifndef byte
 typedef unsigned char	byte;
@@ -49,7 +59,7 @@ struct NifInfo {
 	EndianType endian;
 	/*! This is only supported in Oblivion.  It contains the name of the person who created the NIF file. */
 	string creator;
-	/*! This is only supported in Oblivion.  It seems to contiain the type of script or program used to export the file. */
+	/*! This is only supported in Oblivion.  It seems to contain the type of script or program used to export the file. */
 	string exportInfo1;
 	/*! This is only supported in Oblivion.  It seems to contain the more specific script or options of the above. */
 	string exportInfo2;
diff --git a/include/nif_versions.h b/include/nif_versions.h
index 62be3444..d26ef02a 100644
--- a/include/nif_versions.h
+++ b/include/nif_versions.h
@@ -25,6 +25,9 @@ const unsigned VER_10_1_0_106  = 0x0A01006A; /*!< NIF Version 10.1.0.106 */
 const unsigned VER_10_2_0_0    = 0x0A020000; /*!< NIF Version 10.2.0.0 */ 
 const unsigned VER_20_0_0_4    = 0x14000004; /*!< NIF Version 20.0.0.4 */ 
 const unsigned VER_20_0_0_5    = 0x14000005; /*!< NIF Version 20.0.0.4 */ 
+const unsigned VER_20_1_0_3    = 0x14010003; /*!< NIF Version 20.1.0.3 */ 
+const unsigned VER_20_3_0_3    = 0x14030003; /*!< NIF Version 20.3.0.3 */ 
+const unsigned VER_20_3_0_6    = 0x14030006; /*!< NIF Version 20.3.0.6 */ 
 const unsigned VER_UNSUPPORTED = 0xFFFFFFFF; /*!< Unsupported NIF Version */
 const unsigned VER_INVALID     = 0xFFFFFFFE; /*!< Not a NIF file */
 
diff --git a/include/obj/NiControllerSequence.h b/include/obj/NiControllerSequence.h
index 199b04b8..95763e18 100644
--- a/include/obj/NiControllerSequence.h
+++ b/include/obj/NiControllerSequence.h
@@ -251,7 +251,7 @@ protected:
 	/*! Refers to NiControllerManager which references this object, if any. */
 	NiControllerManager * manager;
 	/*! Name of target node Controller acts on. */
-	string targetName;
+	IndexString targetName;
 	/*! Refers to NiStringPalette. */
 	Ref<NiStringPalette > stringPalette;
 public:
diff --git a/include/obj/NiExtraData.h b/include/obj/NiExtraData.h
index f39534fd..8b8dc266 100644
--- a/include/obj/NiExtraData.h
+++ b/include/obj/NiExtraData.h
@@ -99,7 +99,7 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Name of this object. */
-	string name;
+	IndexString name;
 	/*! Block number of the next extra data object. */
 	Ref<NiExtraData > nextExtraData;
 public:
diff --git a/include/obj/NiFloatExtraDataController.h b/include/obj/NiFloatExtraDataController.h
index 74197bf5..8f7ef244 100644
--- a/include/obj/NiFloatExtraDataController.h
+++ b/include/obj/NiFloatExtraDataController.h
@@ -56,7 +56,7 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Refers to a NiFloatExtraData name. */
-	string controllerData;
+	IndexString controllerData;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiGeometry.h b/include/obj/NiGeometry.h
index 8ea5f317..9bd0d477 100644
--- a/include/obj/NiGeometry.h
+++ b/include/obj/NiGeometry.h
@@ -166,8 +166,10 @@ protected:
 	Ref<NiSkinInstance > skinInstance;
 	/*! Shader. */
 	bool hasShader;
+	/*! Unknown Booleans. */
+	array<3,bool > unknownBools;
 	/*! The shader name. */
-	string shaderName;
+	IndexString shaderName;
 	/*! Unknown link, usually -1. */
 	NiObject * unknownLink;
 public:
diff --git a/include/obj/NiGeometryData.h b/include/obj/NiGeometryData.h
index 07ad9392..381eaad6 100644
--- a/include/obj/NiGeometryData.h
+++ b/include/obj/NiGeometryData.h
@@ -175,7 +175,7 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Name of this object. */
-	string name;
+	IndexString name;
 	/*! Number of vertices. For NiPSysData this is max particles. */
 	mutable unsigned short numVertices;
 	/*! Unknown. */
@@ -186,11 +186,10 @@ protected:
 	vector<Vector3 > vertices;
 	/*!
 	 * The lower 6 (or less?) bits of this field represent the number of UV texture
-	 * sets. The other bits are probably flag bits.
+	 * sets. The other bits are probably flag bits. For versions 10.1.0.0 and up, if
+	 * bit 12 is set then extra vectors are present after the normals.
 	 */
-	mutable byte numUvSets2;
-	/*! Unknown. If bit 4 is set then extra vectors are present after the normals. */
-	byte unknownByte1;
+	mutable unsigned short numUvSets;
 	/*!
 	 * Do we have lighting normals? These are essential for proper lighting: if not
 	 * present, the model will only be influenced by ambient light.
@@ -228,8 +227,6 @@ protected:
 	bool hasVertexColors;
 	/*! The vertex colors. */
 	vector<Color4 > vertexColors;
-	/*! Number of texture sets. */
-	mutable unsigned short numUvSets;
 	/*!
 	 * Do we have UV coordinates?
 	 * 
diff --git a/include/obj/NiImage.h b/include/obj/NiImage.h
index 11645584..b2b48820 100644
--- a/include/obj/NiImage.h
+++ b/include/obj/NiImage.h
@@ -96,7 +96,7 @@ protected:
 	/*! 0 if the texture is internal to the NIF file. */
 	byte external;
 	/*! The filepath to the texture. */
-	string fileName;
+	IndexString fileName;
 	/*! Link to the internally stored image data. */
 	Ref<NiRawImageData > imageData;
 	/*! Unknown.  Often seems to be 7. Perhaps m_uiMipLevels? */
diff --git a/include/obj/NiObjectNET.h b/include/obj/NiObjectNET.h
index 621b2a57..1cb289b9 100644
--- a/include/obj/NiObjectNET.h
+++ b/include/obj/NiObjectNET.h
@@ -133,7 +133,7 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Name of this controllable object, used to refer to the object in .kf files. */
-	string name;
+	IndexString name;
 	/*! Extra data object index. (The first in a chain) */
 	Ref<NiExtraData > extraData;
 	/*! The number of Extra Data objects referenced through the list. */
diff --git a/include/obj/NiPSysModifier.h b/include/obj/NiPSysModifier.h
index 5780d545..1b14ec38 100644
--- a/include/obj/NiPSysModifier.h
+++ b/include/obj/NiPSysModifier.h
@@ -58,7 +58,7 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! The object name. */
-	string name;
+	IndexString name;
 	/*! Modifier ID in the particle modifier chain (always a multiple of 1000)? */
 	unsigned int order;
 	/*! NiParticleSystem parent of this modifier. */
diff --git a/include/obj/NiPSysModifierCtlr.h b/include/obj/NiPSysModifierCtlr.h
index 3d6861d4..8e1078bd 100644
--- a/include/obj/NiPSysModifierCtlr.h
+++ b/include/obj/NiPSysModifierCtlr.h
@@ -56,7 +56,7 @@ public:
 	//--END CUSTOM CODE--//
 protected:
 	/*! Refers to modifier object by its name? */
-	string modifierName;
+	IndexString modifierName;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiSequence.h b/include/obj/NiSequence.h
index 4043c20d..006c1295 100644
--- a/include/obj/NiSequence.h
+++ b/include/obj/NiSequence.h
@@ -67,9 +67,9 @@ protected:
 	 * animation file contains an attack sequence, then the file would be called
 	 * "demon_attack1.kf" and this field would contain the string "attack1".
 	 */
-	string name;
+	IndexString name;
 	/*! Name of following referenced NiTextKeyExtraData class. */
-	string textKeysName;
+	IndexString textKeysName;
 	/*! Link to NiTextKeyExtraData. */
 	Ref<NiTextKeyExtraData > textKeys;
 	/*! Number of controlled objects. */
diff --git a/include/obj/NiSourceTexture.h b/include/obj/NiSourceTexture.h
index 703a03ef..2110af2d 100644
--- a/include/obj/NiSourceTexture.h
+++ b/include/obj/NiSourceTexture.h
@@ -132,7 +132,7 @@ protected:
 	/*! Is the texture external? */
 	byte useExternal;
 	/*! The external texture file name. */
-	string fileName;
+	IndexString fileName;
 	/*! Unknown. */
 	Ref<NiObject > unknownLink;
 	/*! Unknown. */
@@ -141,7 +141,7 @@ protected:
 	 * The original source filename of the image embedded by the referred NiPixelData
 	 * object.
 	 */
-	string originalFileName_;
+	IndexString originalFileName_;
 	/*! Pixel data object index. */
 	Ref<NiPixelData > pixelData;
 	/*! Specifies the way the image will be stored. */
@@ -153,8 +153,12 @@ protected:
 	 * list of properties to enable material and/or texture transparency.
 	 */
 	AlphaFormat alphaFormat;
+	/*! Unknown, usually 1. */
+	byte unknownByte1;
 	/*! Set to one if textures have mipmaps? */
 	byte unknownByte2;
+	/*! Set to one if textures have mipmaps? */
+	byte unknownByte3;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiStencilProperty.h b/include/obj/NiStencilProperty.h
index 4e663aa6..09bd788c 100644
--- a/include/obj/NiStencilProperty.h
+++ b/include/obj/NiStencilProperty.h
@@ -182,6 +182,8 @@ protected:
 	StencilAction passAction;
 	/*! Used to enabled double sided faces. */
 	FaceDrawMode drawMode;
+	/*! Unknown. */
+	array<5,byte > unknownBytes;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiStringExtraData.h b/include/obj/NiStringExtraData.h
index 5fd4f962..acf12ea7 100644
--- a/include/obj/NiStringExtraData.h
+++ b/include/obj/NiStringExtraData.h
@@ -79,7 +79,7 @@ protected:
 	 */
 	unsigned int bytesRemaining;
 	/*! The string. */
-	string stringData;
+	IndexString stringData;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiStringsExtraData.h b/include/obj/NiStringsExtraData.h
index 42e103b3..c08931a0 100644
--- a/include/obj/NiStringsExtraData.h
+++ b/include/obj/NiStringsExtraData.h
@@ -71,7 +71,7 @@ protected:
 	/*! Number of strings. */
 	mutable unsigned int numStrings;
 	/*! The strings. */
-	vector<string > data;
+	vector<IndexString > data;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiTextKeyExtraData.h b/include/obj/NiTextKeyExtraData.h
index 9db3bfce..c071691c 100644
--- a/include/obj/NiTextKeyExtraData.h
+++ b/include/obj/NiTextKeyExtraData.h
@@ -78,7 +78,7 @@ protected:
 	 * List of textual notes and at which time they take effect. Used for designating
 	 * the start and stop of animations and the triggering of sounds.
 	 */
-	vector<Key<string > > textKeys;
+	vector<Key<IndexString > > textKeys;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiTriShape.h b/include/obj/NiTriShape.h
index 50c60e4c..cfe3a7ab 100644
--- a/include/obj/NiTriShape.h
+++ b/include/obj/NiTriShape.h
@@ -54,6 +54,11 @@ public:
 
 	//--BEGIN MISC CUSTOM CODE--//
 	//--END CUSTOM CODE--//
+protected:
+	/*! Unknown value. */
+	int unknownInt1;
+	/*! Unknown value. */
+	bool unknownBoolean1;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/include/obj/NiVertexColorProperty.h b/include/obj/NiVertexColorProperty.h
index 577b4d1e..6ec92123 100644
--- a/include/obj/NiVertexColorProperty.h
+++ b/include/obj/NiVertexColorProperty.h
@@ -98,9 +98,13 @@ public:
 protected:
 	/*! Property flags. */
 	unsigned short flags;
-	/*! Determines how vertex and material colors are mixed. */
+	/*!
+	 * Determines how vertex and material colors are mixed.
+	 *             related gl function: glColorMaterial
+	 *             In Flags from version 20.1.0.3 onwards.
+	 */
 	VertMode vertexMode;
-	/*! The light mode. */
+	/*! The light mode. In Flags from 20.1.0.3 on. */
 	LightMode lightingMode;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/NiZBufferProperty.h b/include/obj/NiZBufferProperty.h
index c065316b..5ff98e9c 100644
--- a/include/obj/NiZBufferProperty.h
+++ b/include/obj/NiZBufferProperty.h
@@ -86,7 +86,7 @@ protected:
 	 * (1)
 	 */
 	unsigned short flags;
-	/*! Z-Test function (see: glDepthFunc) */
+	/*! Z-Test function (see: glDepthFunc). In Flags from 20.1.0.3 on. */
 	CompareMode function;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
diff --git a/include/obj/bhkBoxShape.h b/include/obj/bhkBoxShape.h
index afa20930..c2d156de 100644
--- a/include/obj/bhkBoxShape.h
+++ b/include/obj/bhkBoxShape.h
@@ -79,7 +79,7 @@ protected:
 	/*! Looks like this could be the box size. */
 	Vector3 dimensions;
 	/*! The smallest of the three sizes. Might be used for optimization. */
-	float min_Size;
+	float minimumSize;
 public:
 	/*! NIFLIB_HIDDEN function.  For internal use only. */
 	NIFLIB_HIDDEN virtual void Read( istream& in, list<unsigned int> & link_stack, const NifInfo & info );
diff --git a/niflib.vcproj b/niflib.vcproj
index 995f65d5..5020d477 100644
--- a/niflib.vcproj
+++ b/niflib.vcproj
@@ -45,7 +45,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="NIFLIB_STATIC_LINK; WIN32;_DEBUG;_CONSOLE"
+				PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -84,13 +84,12 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - Static|Win32"
-			OutputDirectory="$(ProjectDir)obj\$(ConfigurationName)"
-			IntermediateDirectory="$(ProjectDir)obj\$(ConfigurationName)"
+			Name="Debug - Static|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
 			ConfigurationType="4"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			CharacterSet="2"
-			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -106,14 +105,16 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				WholeProgramOptimization="false"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="0"
+				PreprocessorDefinitions="NIFLIB_STATIC_LINK; WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
 				UsePrecompiledHeader="0"
 				PrecompiledHeaderThrough=""
 				WarningLevel="3"
@@ -130,7 +131,7 @@
 			/>
 			<Tool
 				Name="VCLibrarianTool"
-				OutputFile="lib/niflib_static.lib"
+				OutputFile="lib/niflib_static_debug_x64.lib"
 			/>
 			<Tool
 				Name="VCALinkTool"
@@ -149,10 +150,10 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - DLL|Win32"
+			Name="Release - Static|Win32"
 			OutputDirectory="$(ProjectDir)obj\$(ConfigurationName)"
 			IntermediateDirectory="$(ProjectDir)obj\$(ConfigurationName)"
-			ConfigurationType="2"
+			ConfigurationType="4"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			CharacterSet="2"
 			WholeProgramOptimization="0"
@@ -174,10 +175,11 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="3"
+				Optimization="0"
+				WholeProgramOptimization="false"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="BUILDING_NIFLIB_DLL;WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="2"
+				PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				PrecompiledHeaderThrough=""
 				WarningLevel="3"
@@ -193,17 +195,12 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
-				Name="VCLinkerTool"
-				OutputFile="bin\niflib.dll"
-				Version="0.7.2"
-				ImportLibrary="lib/niflib_dll.lib"
+				Name="VCLibrarianTool"
+				OutputFile="lib/niflib_static.lib"
 			/>
 			<Tool
 				Name="VCALinkTool"
 			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
 			<Tool
 				Name="VCXDCMakeTool"
 			/>
@@ -213,23 +210,18 @@
 			<Tool
 				Name="VCFxCopTool"
 			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
 			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - DLL|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
+			Name="Release - Static|x64"
+			OutputDirectory="$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="4"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			CharacterSet="2"
+			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -245,15 +237,15 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
+				WholeProgramOptimization="false"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="BUILDING_NIFLIB_DLL;WIN32;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
+				PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				PrecompiledHeaderThrough=""
 				WarningLevel="3"
@@ -269,18 +261,12 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
-				Name="VCLinkerTool"
-				OutputFile="bin\niflib_debug.dll"
-				Version="0.7.2"
-				GenerateDebugInformation="true"
-				ImportLibrary="lib/niflib_dll_debug.lib"
+				Name="VCLibrarianTool"
+				OutputFile="lib/niflib_static_x64.lib"
 			/>
 			<Tool
 				Name="VCALinkTool"
 			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
 			<Tool
 				Name="VCXDCMakeTool"
 			/>
@@ -290,23 +276,18 @@
 			<Tool
 				Name="VCFxCopTool"
 			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
 			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug - Static|x64"
-			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
-			ConfigurationType="4"
+			Name="Release - DLL|Win32"
+			OutputDirectory="$(ProjectDir)obj\$(ConfigurationName)"
+			IntermediateDirectory="$(ProjectDir)obj\$(ConfigurationName)"
+			ConfigurationType="2"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			CharacterSet="2"
+			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -322,16 +303,13 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="0"
+				Optimization="3"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="NIFLIB_STATIC_LINK; WIN32;_DEBUG;_CONSOLE"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
+				PreprocessorDefinitions="BUILDING_NIFLIB_DLL;WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
 				UsePrecompiledHeader="0"
 				PrecompiledHeaderThrough=""
 				WarningLevel="3"
@@ -347,12 +325,17 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
-				Name="VCLibrarianTool"
-				OutputFile="lib/niflib_static_debug_x64.lib"
+				Name="VCLinkerTool"
+				OutputFile="bin\niflib.dll"
+				Version="0.7.2"
+				ImportLibrary="lib/niflib_dll.lib"
 			/>
 			<Tool
 				Name="VCALinkTool"
 			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
 			<Tool
 				Name="VCXDCMakeTool"
 			/>
@@ -362,15 +345,21 @@
 			<Tool
 				Name="VCFxCopTool"
 			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
 			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - Static|x64"
-			OutputDirectory="$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)"
-			ConfigurationType="4"
+			Name="Release - DLL|x64"
+			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			CharacterSet="2"
 			WholeProgramOptimization="0"
@@ -393,11 +382,10 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="0"
-				WholeProgramOptimization="false"
+				Optimization="3"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="NIFLIB_STATIC_LINK;WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="0"
+				PreprocessorDefinitions="BUILDING_NIFLIB_DLL;WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
 				UsePrecompiledHeader="0"
 				PrecompiledHeaderThrough=""
 				WarningLevel="3"
@@ -413,12 +401,18 @@
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
-				Name="VCLibrarianTool"
-				OutputFile="lib/niflib_static_x64.lib"
+				Name="VCLinkerTool"
+				OutputFile="bin\niflib_x64.dll"
+				Version="0.7.2"
+				ImportLibrary="lib/niflib_dll.lib"
+				TargetMachine="17"
 			/>
 			<Tool
 				Name="VCALinkTool"
 			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
 			<Tool
 				Name="VCXDCMakeTool"
 			/>
@@ -428,18 +422,23 @@
 			<Tool
 				Name="VCFxCopTool"
 			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
 			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release - DLL|x64"
-			OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			Name="Debug - DLL|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
 			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
 			CharacterSet="2"
-			WholeProgramOptimization="0"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -455,14 +454,15 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="3"
+				Optimization="0"
 				AdditionalIncludeDirectories="$(ProjectDir)include"
-				PreprocessorDefinitions="BUILDING_NIFLIB_DLL;WIN32;NDEBUG;_CONSOLE"
-				RuntimeLibrary="2"
+				PreprocessorDefinitions="BUILDING_NIFLIB_DLL;WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
 				UsePrecompiledHeader="0"
 				PrecompiledHeaderThrough=""
 				WarningLevel="3"
@@ -479,10 +479,10 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				OutputFile="bin\niflib_x64.dll"
+				OutputFile="bin\niflib_debug.dll"
 				Version="0.7.2"
-				ImportLibrary="lib/niflib_dll.lib"
-				TargetMachine="17"
+				GenerateDebugInformation="true"
+				ImportLibrary="lib/niflib_dll_debug.lib"
 			/>
 			<Tool
 				Name="VCALinkTool"
@@ -628,7 +628,7 @@
 					/>
 				</FileConfiguration>
 				<FileConfiguration
-					Name="Debug - DLL|Win32"
+					Name="Debug - Static|x64"
 					>
 					<Tool
 						Name="VCCLCompilerTool"
@@ -636,7 +636,7 @@
 					/>
 				</FileConfiguration>
 				<FileConfiguration
-					Name="Debug - Static|x64"
+					Name="Debug - DLL|Win32"
 					>
 					<Tool
 						Name="VCCLCompilerTool"
@@ -1695,6 +1695,10 @@
 					RelativePath=".\src\gen\enums.cpp"
 					>
 				</File>
+				<File
+					RelativePath=".\src\gen\ExportInfo.cpp"
+					>
+				</File>
 				<File
 					RelativePath=".\src\gen\Footer.cpp"
 					>
@@ -2945,6 +2949,10 @@
 					RelativePath=".\include\gen\enums_intl.h"
 					>
 				</File>
+				<File
+					RelativePath=".\include\gen\ExportInfo.h"
+					>
+				</File>
 				<File
 					RelativePath=".\include\gen\Footer.h"
 					>
diff --git a/src/NIF_IO.cpp b/src/NIF_IO.cpp
index 451e89c2..615b1e22 100644
--- a/src/NIF_IO.cpp
+++ b/src/NIF_IO.cpp
@@ -3,6 +3,7 @@ All rights reserved.  Please see niflib.h for license. */
 
 #include "../include/NIF_IO.h"
 #include "../include/niflib.h"
+#include "../include/gen/header.h"
 namespace Niflib {
 
 //--Endian Support Functions--//
@@ -639,7 +640,7 @@ void NifStream( Key<Quaternion> & key, istream& file, const NifInfo & info, KeyT
 	}
 
 	//Read data based on the type of key
-	NifStream( key.data, file );
+	NifStream( key.data, file, info );
 	if ( type == TBC_KEY ) {
 		//Uses TBC interpolation
 		key.tension = ReadFloat( file );
@@ -659,7 +660,7 @@ void NifStream( Key<Quaternion> const & key, ostream& file, const NifInfo & info
 	}
 
 	//Read data based on the type of key
-	NifStream( key.data, file );
+	NifStream( key.data, file, info );
 	if ( type == TBC_KEY ) {
 		//Uses TBC interpolation
 		WriteFloat( key.tension, file);
@@ -668,4 +669,138 @@ void NifStream( Key<Quaternion> const & key, ostream& file, const NifInfo & info
 	}
 }
 
+static void FromIndexString(IndexString const &value, Header* header, unsigned int& idx)
+{
+	if (header == NULL)
+		throw runtime_error("stream not properly configured");
+	if (value.empty()) {
+		idx = 0xffffffff;
+	} else {
+		size_t i = 0;
+		for ( ; i < header->strings.size(); i++) {
+			if (header->strings[i] == value)
+				break;
+		}
+		if (i >= header->numStrings)
+			header->numStrings = i;
+		size_t len = value.length();
+		if (header->maxStringLength < len)
+			header->maxStringLength = len;
+		header->strings.push_back(value);
+		idx = i;
+	}
+}
+
+static void ToIndexString(unsigned int idx, Header* header, IndexString & value)
+{
+	if (header == NULL)
+		throw runtime_error("stream not properly configured");
+	if ( idx == 0xffffffff ) {
+		value.clear();
+	} else if (idx >= 0 && idx <= header->strings.size()) {
+		value = header->strings[idx];
+	} else {
+		throw runtime_error("invalid string index");
+	}
+}
+
+void NifStream( IndexString & val, istream& in, const NifInfo & info ) {
+	if (info.version >= VER_20_1_0_3) {
+		std::streampos pos = in.tellg();
+
+		ToIndexString(ReadUInt(in), hdrInfo::getInfo(in), val);
+	} else {
+		val = ReadString( in );
+	}
+}
+
+void NifStream( IndexString const & val, ostream& out, const NifInfo & info ) {
+	if (info.version >= VER_20_1_0_3) {
+		unsigned idx = 0xffffffff;
+		FromIndexString(val, hdrInfo::getInfo(out), idx);
+		WriteInt(idx, out);
+	} else {
+		WriteString( val, out );
+	}
+}
+
+ostream & operator<<( ostream & out, IndexString const & val ) {
+	out << static_cast<string const &>(val);
+	return out;
 }
+
+template <> void NifStream( Key<IndexString> & key, istream& file, const NifInfo & info, KeyType type )
+{
+	if (info.version >= VER_20_1_0_3) {
+		Key<int> ikey;
+		NifStream(ikey, file, info, type);
+		key.time = ikey.time;
+		ToIndexString(ikey.data, hdrInfo::getInfo(file), key.data);
+		key.tension = ikey.tension;
+		key.bias = ikey.bias;
+		key.continuity = ikey.continuity;
+	} else {
+		Key<string> skey;
+		NifStream(skey, file, info, type);
+		key.time = skey.time;
+		key.data = skey.data;
+		key.tension = skey.tension;
+		key.bias = skey.bias;
+		key.continuity = skey.continuity;
+	}
+}
+
+template <> void NifStream( Key<IndexString> const & key, ostream& file, const NifInfo & info,  KeyType type ) {
+	if (info.version >= VER_20_1_0_3) {
+		Key<unsigned int> ikey;
+		ikey.time = key.time;
+		ikey.tension = key.tension;
+		ikey.bias = key.bias;
+		ikey.continuity = key.continuity;
+		FromIndexString(key.data, hdrInfo::getInfo(file), ikey.data);
+		NifStream(ikey, file, info, type);
+	} else {
+		Key<string> skey;
+		skey.time = key.time;
+		skey.data = key.data;
+		skey.tension = key.tension;
+		skey.bias = key.bias;
+		skey.continuity = key.continuity;
+		NifStream(skey, file, info, type);
+	}
+}
+
+
+const int strInfo::infoIdx = ios_base::xalloc();
+const int hdrInfo::infoIdx = ios_base::xalloc();
+
+std::streamsize NifStreamBuf::xsputn(const char_type *_Ptr, std::streamsize _Count) {
+	pos += _Count;
+	if (size < pos) size = pos;
+	return _Count;
+}
+
+std::streampos NifStreamBuf::seekoff(std::streamoff offset, std::ios_base::seekdir dir, std::ios_base::openmode mode)
+{	// change position by offset, according to way and mode
+	switch (dir)
+	{
+	case std::ios_base::beg:
+		pos = offset;
+		return (pos >= 0 && pos < size) ? (streampos(-1)) : pos;
+	case std::ios_base::cur:
+		pos += offset;
+		return (pos >= 0 && pos < size) ? (streampos(-1)) : pos;
+	case std::ios_base::end:
+		pos = size - offset;
+		return (pos >= 0 && pos < size) ? (streampos(-1)) : pos;		
+	}
+	return streampos(-1);
+}
+
+std::streampos NifStreamBuf::seekpos(std::streampos offset, std::ios_base::openmode mode)
+{	// change to specified position, according to mode
+	pos = offset;
+	return (pos >= 0 && pos < size) ? (streampos(-1)) : pos;
+}
+
+}
\ No newline at end of file
diff --git a/src/gen/Header.cpp b/src/gen/Header.cpp
index 7637ce0d..a1363cda 100644
--- a/src/gen/Header.cpp
+++ b/src/gen/Header.cpp
@@ -6,10 +6,12 @@ All rights reserved.  Please see niflib.h for license. */
 //To change this file, alter the niftools/docsys/gen_niflib.py Python script.
 
 #include "../../include/gen/Header.h"
+#include "../../include/gen/ExportInfo.h"
+#include "../../include/gen/ExportInfo.h"
 using namespace Niflib;
 
 //Constructor
-Header::Header() : version((unsigned int)0x04000002), endianType((EndianType)1), userVersion((unsigned int)0), numBlocks((unsigned int)0), userVersion2((unsigned int)0), numBlockTypes((unsigned short)0), unknownInt2((unsigned int)0) {};
+Header::Header() : version((unsigned int)0x04000002), endianType((EndianType)1), userVersion((unsigned int)0), numBlocks((unsigned int)0), userVersion2((unsigned int)0), numBlockTypes((unsigned short)0), numStrings((unsigned int)0), maxStringLength((unsigned int)0), unknownInt2((unsigned int)0) {};
 
 //Copy Constructor
 Header::Header( const Header & src ) {
@@ -25,12 +27,14 @@ Header & Header::operator=( const Header & src ) {
 	this->userVersion = src.userVersion;
 	this->numBlocks = src.numBlocks;
 	this->userVersion2 = src.userVersion2;
-	this->creator = src.creator;
-	this->exportInfo1 = src.exportInfo1;
-	this->exportInfo2 = src.exportInfo2;
+	this->exportInfo = src.exportInfo;
 	this->numBlockTypes = src.numBlockTypes;
 	this->blockTypes = src.blockTypes;
 	this->blockTypeIndex = src.blockTypeIndex;
+	this->blockSize = src.blockSize;
+	this->numStrings = src.numStrings;
+	this->maxStringLength = src.maxStringLength;
+	this->strings = src.strings;
 	this->unknownInt2 = src.unknownInt2;
 	return *this;
 };
@@ -59,19 +63,27 @@ NifInfo Header::Read( istream& in ) {
 	if ( info.version >= 0x0303000D ) {
 		NifStream( numBlocks, in, info );
 	};
-	if ( ( info.version >= 0x0A000102 ) && ( info.version <= 0x0A000102 ) ) {
-		NifStream( userVersion, in, info );
-	};
 	if ( info.version >= 0x0A010000 ) {
 		if ( (userVersion != 0) ) {
 			NifStream( userVersion2, in, info );
 		};
 	};
-	if ( info.version >= 0x0A000102 ) {
+	if ( ( info.version >= 0x0A000102 ) && ( info.version <= 0x0A000102 ) ) {
+		if ( info.version <= 0x0A000102 ) {
+			NifStream( exportInfo.unknown, in, info );
+		};
+		NifStream( exportInfo.creator, in, info );
+		NifStream( exportInfo.exportInfo1, in, info );
+		NifStream( exportInfo.exportInfo2, in, info );
+	};
+	if ( info.version >= 0x0A010000 ) {
 		if ( (userVersion != 0) ) {
-			NifStream( creator, in, info );
-			NifStream( exportInfo1, in, info );
-			NifStream( exportInfo2, in, info );
+			if ( info.version <= 0x0A000102 ) {
+				NifStream( exportInfo.unknown, in, info );
+			};
+			NifStream( exportInfo.creator, in, info );
+			NifStream( exportInfo.exportInfo1, in, info );
+			NifStream( exportInfo.exportInfo2, in, info );
 		};
 	};
 	if ( info.version >= 0x0A000100 ) {
@@ -84,6 +96,22 @@ NifInfo Header::Read( istream& in ) {
 		for (unsigned int i2 = 0; i2 < blockTypeIndex.size(); i2++) {
 			NifStream( blockTypeIndex[i2], in, info );
 		};
+	};
+	if ( info.version >= 0x14030003 ) {
+		blockSize.resize(numBlocks);
+		for (unsigned int i2 = 0; i2 < blockSize.size(); i2++) {
+			NifStream( blockSize[i2], in, info );
+		};
+	};
+	if ( info.version >= 0x14010003 ) {
+		NifStream( numStrings, in, info );
+		NifStream( maxStringLength, in, info );
+		strings.resize(numStrings);
+		for (unsigned int i2 = 0; i2 < strings.size(); i2++) {
+			NifStream( strings[i2], in, info );
+		};
+	};
+	if ( info.version >= 0x0A000100 ) {
 		NifStream( unknownInt2, in, info );
 	};
 
@@ -93,15 +121,16 @@ NifInfo Header::Read( istream& in ) {
 	//Fill out and return NifInfo structure.
 	info.userVersion = userVersion;
 	info.endian = EndianType(endianType);
-	info.creator = creator.str;
-	info.exportInfo1 = exportInfo1.str;
-	info.exportInfo2 = exportInfo2.str;
+	info.creator = exportInfo.creator.str;
+	info.exportInfo1 = exportInfo.exportInfo1.str;
+	info.exportInfo2 = exportInfo.exportInfo2.str;
 
 	return info;
 
 }
 
 void Header::Write( ostream& out, const NifInfo & info ) const {
+	numStrings = (unsigned int)(strings.size());
 	numBlockTypes = (unsigned short)(blockTypes.size());
 	numBlocks = (unsigned int)(blockTypeIndex.size());
 	NifStream( headerString, out, info );
@@ -122,19 +151,27 @@ void Header::Write( ostream& out, const NifInfo & info ) const {
 	if ( info.version >= 0x0303000D ) {
 		NifStream( numBlocks, out, info );
 	};
-	if ( ( info.version >= 0x0A000102 ) && ( info.version <= 0x0A000102 ) ) {
-		NifStream( userVersion, out, info );
-	};
 	if ( info.version >= 0x0A010000 ) {
 		if ( (userVersion != 0) ) {
 			NifStream( userVersion2, out, info );
 		};
 	};
-	if ( info.version >= 0x0A000102 ) {
+	if ( ( info.version >= 0x0A000102 ) && ( info.version <= 0x0A000102 ) ) {
+		if ( info.version <= 0x0A000102 ) {
+			NifStream( exportInfo.unknown, out, info );
+		};
+		NifStream( exportInfo.creator, out, info );
+		NifStream( exportInfo.exportInfo1, out, info );
+		NifStream( exportInfo.exportInfo2, out, info );
+	};
+	if ( info.version >= 0x0A010000 ) {
 		if ( (userVersion != 0) ) {
-			NifStream( creator, out, info );
-			NifStream( exportInfo1, out, info );
-			NifStream( exportInfo2, out, info );
+			if ( info.version <= 0x0A000102 ) {
+				NifStream( exportInfo.unknown, out, info );
+			};
+			NifStream( exportInfo.creator, out, info );
+			NifStream( exportInfo.exportInfo1, out, info );
+			NifStream( exportInfo.exportInfo2, out, info );
 		};
 	};
 	if ( info.version >= 0x0A000100 ) {
@@ -145,6 +182,20 @@ void Header::Write( ostream& out, const NifInfo & info ) const {
 		for (unsigned int i2 = 0; i2 < blockTypeIndex.size(); i2++) {
 			NifStream( blockTypeIndex[i2], out, info );
 		};
+	};
+	if ( info.version >= 0x14030003 ) {
+		for (unsigned int i2 = 0; i2 < blockSize.size(); i2++) {
+			NifStream( blockSize[i2], out, info );
+		};
+	};
+	if ( info.version >= 0x14010003 ) {
+		NifStream( numStrings, out, info );
+		NifStream( maxStringLength, out, info );
+		for (unsigned int i2 = 0; i2 < strings.size(); i2++) {
+			NifStream( strings[i2], out, info );
+		};
+	};
+	if ( info.version >= 0x0A000100 ) {
 		NifStream( unknownInt2, out, info );
 	};
 }
@@ -152,6 +203,7 @@ void Header::Write( ostream& out, const NifInfo & info ) const {
 string Header::asString( bool verbose ) const {
 	stringstream out;
 	unsigned int array_output_count = 0;
+	numStrings = (unsigned int)(strings.size());
 	numBlockTypes = (unsigned short)(blockTypes.size());
 	numBlocks = (unsigned int)(blockTypeIndex.size());
 	out << "  Header String:  " << headerString << endl;
@@ -173,10 +225,11 @@ string Header::asString( bool verbose ) const {
 	out << "  Num Blocks:  " << numBlocks << endl;
 	if ( (userVersion != 0) ) {
 		out << "    User Version 2:  " << userVersion2 << endl;
-		out << "    Creator:  " << creator << endl;
-		out << "    Export Info 1:  " << exportInfo1 << endl;
-		out << "    Export Info 2:  " << exportInfo2 << endl;
 	};
+	out << "  Unknown:  " << exportInfo.unknown << endl;
+	out << "  Creator:  " << exportInfo.creator << endl;
+	out << "  Export Info 1:  " << exportInfo.exportInfo1 << endl;
+	out << "  Export Info 2:  " << exportInfo.exportInfo2 << endl;
 	out << "  Num Block Types:  " << numBlockTypes << endl;
 	array_output_count = 0;
 	for (unsigned int i1 = 0; i1 < blockTypes.size(); i1++) {
@@ -202,6 +255,32 @@ string Header::asString( bool verbose ) const {
 		out << "    Block Type Index[" << i1 << "]:  " << blockTypeIndex[i1] << endl;
 		array_output_count++;
 	};
+	array_output_count = 0;
+	for (unsigned int i1 = 0; i1 < blockSize.size(); i1++) {
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
+			break;
+		};
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			break;
+		};
+		out << "    Block Size[" << i1 << "]:  " << blockSize[i1] << endl;
+		array_output_count++;
+	};
+	out << "  Num Strings:  " << numStrings << endl;
+	out << "  Max String Length:  " << maxStringLength << endl;
+	array_output_count = 0;
+	for (unsigned int i1 = 0; i1 < strings.size(); i1++) {
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
+			break;
+		};
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			break;
+		};
+		out << "    Strings[" << i1 << "]:  " << strings[i1] << endl;
+		array_output_count++;
+	};
 	out << "  Unknown Int 2:  " << unknownInt2 << endl;
 	return out.str();
 }
diff --git a/src/gen/TexDesc.cpp b/src/gen/TexDesc.cpp
index 39a1921e..be44bb9f 100644
--- a/src/gen/TexDesc.cpp
+++ b/src/gen/TexDesc.cpp
@@ -10,7 +10,7 @@ All rights reserved.  Please see niflib.h for license. */
 using namespace Niflib;
 
 //Constructor
-TexDesc::TexDesc() : source(NULL), clampMode((TexClampMode)WRAP_S_WRAP_T), filterMode((TexFilterMode)FILTER_TRILERP), uvSet((unsigned int)0), ps2L((unsigned short)0), ps2K((unsigned short)0xFFB5), unknown1((unsigned short)0), hasTextureTransform(false), wRotation(0.0f), transformType_((unsigned int)0) {};
+TexDesc::TexDesc() : source(NULL), clampMode((TexClampMode)WRAP_S_WRAP_T), filterMode((TexFilterMode)FILTER_TRILERP), flags((unsigned short)0), uvSet((unsigned int)0), ps2L((unsigned short)0), ps2K((unsigned short)0xFFB5), unknown1((unsigned short)0), hasTextureTransform(false), wRotation(0.0f), transformType_((unsigned int)0) {};
 
 //Copy Constructor
 TexDesc::TexDesc( const TexDesc & src ) {
@@ -22,6 +22,7 @@ TexDesc & TexDesc::operator=( const TexDesc & src ) {
 	this->source = src.source;
 	this->clampMode = src.clampMode;
 	this->filterMode = src.filterMode;
+	this->flags = src.flags;
 	this->uvSet = src.uvSet;
 	this->ps2L = src.ps2L;
 	this->ps2K = src.ps2K;
diff --git a/src/niflib.cpp b/src/niflib.cpp
index f5ee1079..179ea383 100644
--- a/src/niflib.cpp
+++ b/src/niflib.cpp
@@ -128,6 +128,9 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 	//--Read Header--//
 	Header header;
 
+	// set the header pointer in the stream
+	in >> hdrInfo(&header);
+
 	//Create a new NifInfo if one isn't given.
 	bool delete_info = false;
 	if ( info == NULL ) {
@@ -143,9 +146,9 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 	info->userVersion = header.userVersion;
 	info->userVersion2 = header.userVersion2;
 	info->endian = EndianType(header.endianType);
-	info->creator = header.creator.str;
-	info->exportInfo1 = header.exportInfo1.str;
-	info->exportInfo2 = header.exportInfo2.str;
+	info->creator = header.exportInfo.creator.str;
+	info->exportInfo1 = header.exportInfo.exportInfo1.str;
+	info->exportInfo2 = header.exportInfo.exportInfo2.str;
 
 #ifdef DEBUG_HEADER_FOOTER
 	//Print debug output for header
@@ -164,10 +167,25 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 	string objectType;
 	stringstream errStream;
 
+	std::streampos headerpos = in.tellg();
+	std::streampos nextobjpos = headerpos;
+
 	//Loop through all objects in the file
 	unsigned int i = 0;
 	NiObjectRef new_obj;
 	while (true) {
+
+		// Check if the size information matches in version 20.3 and greater
+		if ( header.version >= VER_20_3_0_3 ) {
+			if (nextobjpos != in.tellg()) {
+				// incorrect positioning seek to expected location
+				in.seekg(nextobjpos);				
+			}
+			// update next location
+			nextobjpos += header.blockSize[i];
+		}
+
+
 		//Check for EOF
 		if (in.eof() ) {
 			errStream << "End of file reached prematurely.  This NIF may be corrupt or improperly supported." << endl;
@@ -180,6 +198,9 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 			}
 			throw runtime_error( errStream.str() );
 		}
+
+		// Starting position of block in stream
+		std::streampos startobjpos = in.tellg();
 	
 		//There are two main ways to read objects
 		//One before version 5.0.0.1 and one after
@@ -267,7 +288,7 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 		if ( new_obj == NULL ) {
 			errStream << "Unknown object type encountered during file read:  " << objectType << endl;
 			if ( new_obj != NULL ) {
-				errStream << "Last successfuly read object was:  " << endl;
+				errStream << "Last successfully read object was:  " << endl;
 				errStream << "====[ " << "Object " << i - 1 << " | " << new_obj->GetType().GetTypeName() << " ]====" << endl;
 				errStream << new_obj->asString();
 			} else {
@@ -294,7 +315,22 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 
 		//Add object to list
 		obj_list.push_back(new_obj);
-			
+
+		// Ending position of block in stream
+		std::streampos endobjpos = in.tellg();
+
+		// Check if the size information matches
+		if ( header.version >= VER_20_3_0_3 ) {
+			std::streamsize calcobjsize = endobjpos - startobjpos;
+			unsigned int objsize = header.blockSize[i];
+			if (calcobjsize != objsize) {
+				errStream << "Object size mismatch occurred during file read:" << endl;
+				errStream << "====[ " << "Object " << i << " | " << objectType << " ]====" << endl;
+				errStream << "  Start: " << startobjpos << "  Expected Size: " << objsize << "  Read Size: " << calcobjsize << endl;
+				errStream << endl;
+			}
+		}
+
 #ifdef PRINT_OBJECT_CONTENTS
 		cout << endl << new_obj->asString() << endl;
 #endif
@@ -317,6 +353,11 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 	//Print footer debug output
 	footer.asString();
 #endif
+
+	// Check for accumulated warnings
+	if (errStream.tellp() > 0) {
+		throw runtime_error( errStream.str() );
+	}
 	
 	//This should fail, and trigger the in.eof() flag
 	ReadByte( in ); 
@@ -349,12 +390,16 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 		delete info;
 	}
 
+	// clear the header pointer in the stream.  Should be in try/catch block
+	in >> hdrInfo(NULL);
+
 	//Return completed object list
 	return obj_list;
 }
 
 // Writes a valid Nif File given an ostream, a list to the root objects of a file tree
 void WriteNifTree( ostream & out, list<NiObjectRef> const & roots, const NifInfo & info ) {
+
 	//Enumerate all objects in tree
 	map<Type*,unsigned int> type_map;
 	map<NiObjectRef, unsigned int> link_map;
@@ -383,18 +428,20 @@ void WriteNifTree( ostream & out, list<NiObjectRef> const & roots, const NifInfo
 	header.userVersion = info.userVersion;
 	header.userVersion2 = info.userVersion2;
 	header.endianType = info.endian;
-	header.creator.str = info.creator;
-	header.exportInfo1.str = info.exportInfo1;
-	header.exportInfo2.str = info.exportInfo2;
+	header.exportInfo.creator.str = info.creator;
+	header.exportInfo.exportInfo1.str = info.exportInfo1;
+	header.exportInfo.exportInfo2.str = info.exportInfo2;
 	header.copyright[0].line = "Numerical Design Limited, Chapel Hill, NC 27514";
 	header.copyright[1].line = "Copyright (c) 1996-2000";
 	header.copyright[2].line = "All Rights Reserved";
 	
+	// set the header pointer in the stream
+	out << hdrInfo(&header);
+
 	//Set Type Names
 	header.blockTypes.resize( types.size() );
 	for ( unsigned int i = 0; i < types.size(); ++i ) {
 		header.blockTypes[i] = types[i]->GetTypeName();
-
 	}
 
 	//Set type number of each object
@@ -403,6 +450,26 @@ void WriteNifTree( ostream & out, list<NiObjectRef> const & roots, const NifInfo
 		header.blockTypeIndex[i] = type_map[(Type*)&(objects[i]->GetType())];
 	}
 
+	// Set object sizes and accumulate string types
+	if (header.version >= VER_20_1_0_3)
+	{
+		// Zero string information
+		header.maxStringLength = 0;
+		header.numStrings = 0;
+		header.strings.clear();
+
+		NifSizeStream ostr;
+		ostr << hdrInfo(&header);
+
+		header.blockSize.resize( objects.size() );
+		for ( unsigned int i = 0; i < objects.size(); ++i ) {
+			ostr.reset();
+			objects[i]->Write( ostr, link_map, info );
+			header.blockSize[i] = ostr.tellp();
+		}
+		header.numStrings = header.strings.size();
+	}
+
 	//Write header to file
 	header.Write( out, info );
 
@@ -471,6 +538,9 @@ void WriteNifTree( ostream & out, list<NiObjectRef> const & roots, const NifInfo
 		}
 		footer.Write( out, link_map, info );
 	}
+
+	// clear the header pointer in the stream.  Should be in try/catch block
+	out << hdrInfo(NULL);
 }
 
 // Writes a valid Nif File given a file name, a pointer to the root object of a file tree
@@ -1019,6 +1089,9 @@ bool IsSupportedVersion( unsigned int version ) {
 		case VER_10_2_0_0:
 		case VER_20_0_0_4:
 		case VER_20_0_0_5:
+		case VER_20_1_0_3:
+		case VER_20_3_0_3:
+		case VER_20_3_0_6:
 			return true;
    }
    return false;
diff --git a/src/obj/NiControllerSequence.cpp b/src/obj/NiControllerSequence.cpp
index f2112bb5..15dcc28e 100644
--- a/src/obj/NiControllerSequence.cpp
+++ b/src/obj/NiControllerSequence.cpp
@@ -75,7 +75,7 @@ void NiControllerSequence::Read( istream& in, list<unsigned int> & link_stack, c
 		link_stack.push_back( block_num );
 		NifStream( targetName, in, info );
 	};
-	if ( info.version >= 0x0A020000 ) {
+	if ( ( info.version >= 0x0A020000 ) && ( info.version <= 0x14000005 ) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
 	};
@@ -128,7 +128,7 @@ void NiControllerSequence::Write( ostream& out, const map<NiObjectRef,unsigned i
 		}
 		NifStream( targetName, out, info );
 	};
-	if ( info.version >= 0x0A020000 ) {
+	if ( ( info.version >= 0x0A020000 ) && ( info.version <= 0x14000005 ) ) {
 		if ( info.version < VER_3_3_0_13 ) {
 			NifStream( (unsigned int)&(*stringPalette), out, info );
 		} else {
@@ -178,7 +178,7 @@ void NiControllerSequence::FixLinks( const map<unsigned int,NiObjectRef> & objec
 		textKeys = FixLink<NiTextKeyExtraData>( objects, link_stack, info );
 		manager = FixLink<NiControllerManager>( objects, link_stack, info );
 	};
-	if ( info.version >= 0x0A020000 ) {
+	if ( ( info.version >= 0x0A020000 ) && ( info.version <= 0x14000005 ) ) {
 		stringPalette = FixLink<NiStringPalette>( objects, link_stack, info );
 	};
 
diff --git a/src/obj/NiGeometry.cpp b/src/obj/NiGeometry.cpp
index 4554f06e..5b89c5bd 100644
--- a/src/obj/NiGeometry.cpp
+++ b/src/obj/NiGeometry.cpp
@@ -57,6 +57,13 @@ void NiGeometry::Read( istream& in, list<unsigned int> & link_stack, const NifIn
 	};
 	if ( info.version >= 0x0A000100 ) {
 		NifStream( hasShader, in, info );
+	};
+	if ( info.version >= 0x14030003 ) {
+		for (unsigned int i2 = 0; i2 < 3; i2++) {
+			NifStream( unknownBools[i2], in, info );
+		};
+	};
+	if ( info.version >= 0x0A000100 ) {
 		if ( (hasShader != 0) ) {
 			NifStream( shaderName, in, info );
 			NifStream( block_num, in, info );
@@ -95,6 +102,13 @@ void NiGeometry::Write( ostream& out, const map<NiObjectRef,unsigned int> & link
 	};
 	if ( info.version >= 0x0A000100 ) {
 		NifStream( hasShader, out, info );
+	};
+	if ( info.version >= 0x14030003 ) {
+		for (unsigned int i2 = 0; i2 < 3; i2++) {
+			NifStream( unknownBools[i2], out, info );
+		};
+	};
+	if ( info.version >= 0x0A000100 ) {
 		if ( (hasShader != 0) ) {
 			NifStream( shaderName, out, info );
 			if ( info.version < VER_3_3_0_13 ) {
@@ -123,6 +137,18 @@ std::string NiGeometry::asString( bool verbose ) const {
 	out << "  Data:  " << data << endl;
 	out << "  Skin Instance:  " << skinInstance << endl;
 	out << "  Has Shader:  " << hasShader << endl;
+	array_output_count = 0;
+	for (unsigned int i1 = 0; i1 < 3; i1++) {
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
+			break;
+		};
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			break;
+		};
+		out << "    Unknown Bools[" << i1 << "]:  " << unknownBools[i1] << endl;
+		array_output_count++;
+	};
 	if ( (hasShader != 0) ) {
 		out << "    Shader Name:  " << shaderName << endl;
 		out << "    Unknown Link:  " << unknownLink << endl;
diff --git a/src/obj/NiGeometryData.cpp b/src/obj/NiGeometryData.cpp
index e0a6e5f2..c923194d 100644
--- a/src/obj/NiGeometryData.cpp
+++ b/src/obj/NiGeometryData.cpp
@@ -20,7 +20,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiGeometryData::TYPE("NiGeometryData", &NiObject::TYPE );
 
-NiGeometryData::NiGeometryData() : numVertices((unsigned short)0), unknownShort1((unsigned short)0), hasVertices(1), numUvSets2((byte)0), unknownByte1((byte)0), hasNormals(false), radius(0.0f), hasVertexColors(false), numUvSets((unsigned short)0), hasUv(false), consistencyFlags((ConsistencyType)0), unknownLink1(NULL) {
+NiGeometryData::NiGeometryData() : numVertices((unsigned short)0), unknownShort1((unsigned short)0), hasVertices(1), numUvSets((unsigned short)0), hasNormals(false), radius(0.0f), hasVertexColors(false), hasUv(false), consistencyFlags((ConsistencyType)0), unknownLink1(NULL) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -59,8 +59,7 @@ void NiGeometryData::Read( istream& in, list<unsigned int> & link_stack, const N
 		};
 	};
 	if ( info.version >= 0x0A000100 ) {
-		NifStream( numUvSets2, in, info );
-		NifStream( unknownByte1, in, info );
+		NifStream( numUvSets, in, info );
 	};
 	NifStream( hasNormals, in, info );
 	if ( (hasNormals != 0) ) {
@@ -70,7 +69,7 @@ void NiGeometryData::Read( istream& in, list<unsigned int> & link_stack, const N
 		};
 	};
 	if ( info.version >= 0x0A010000 ) {
-		if ( (((hasNormals != 0)) && ((unknownByte1 & 16))) ) {
+		if ( (((hasNormals != 0)) && ((numUvSets & 4096))) ) {
 			unknownVectors1.resize(numVertices);
 			for (unsigned int i3 = 0; i3 < unknownVectors1.size(); i3++) {
 				NifStream( unknownVectors1[i3], in, info );
@@ -96,23 +95,14 @@ void NiGeometryData::Read( istream& in, list<unsigned int> & link_stack, const N
 	if ( info.version <= 0x04000002 ) {
 		NifStream( hasUv, in, info );
 	};
-	if ( info.version <= 0x04020200 ) {
-		uvSets.resize(numUvSets);
-		for (unsigned int i2 = 0; i2 < uvSets.size(); i2++) {
-			uvSets[i2].resize(numVertices);
-			for (unsigned int i3 = 0; i3 < uvSets[i2].size(); i3++) {
-				NifStream( uvSets[i2][i3], in, info );
-			};
+	uvSets.resize((numUvSets & 63));
+	for (unsigned int i1 = 0; i1 < uvSets.size(); i1++) {
+		uvSets[i1].resize(numVertices);
+		for (unsigned int i2 = 0; i2 < uvSets[i1].size(); i2++) {
+			NifStream( uvSets[i1][i2], in, info );
 		};
 	};
 	if ( info.version >= 0x0A000100 ) {
-		uvSets.resize((numUvSets2 & 63));
-		for (unsigned int i2 = 0; i2 < uvSets.size(); i2++) {
-			uvSets[i2].resize(numVertices);
-			for (unsigned int i3 = 0; i3 < uvSets[i2].size(); i3++) {
-				NifStream( uvSets[i2][i3], in, info );
-			};
-		};
 		NifStream( consistencyFlags, in, info );
 	};
 	if ( info.version >= 0x14000004 ) {
@@ -130,7 +120,6 @@ void NiGeometryData::Write( ostream& out, const map<NiObjectRef,unsigned int> &
 
 	NiObject::Write( out, link_map, info );
 	numUvSets = (unsigned short)(uvSets.size());
-	numUvSets2 = (byte)(uvSets.size());
 	numVertices = (unsigned short)(vertices.size());
 	if ( info.version >= 0x0A020000 ) {
 		NifStream( name, out, info );
@@ -146,8 +135,7 @@ void NiGeometryData::Write( ostream& out, const map<NiObjectRef,unsigned int> &
 		};
 	};
 	if ( info.version >= 0x0A000100 ) {
-		NifStream( numUvSets2, out, info );
-		NifStream( unknownByte1, out, info );
+		NifStream( numUvSets, out, info );
 	};
 	NifStream( hasNormals, out, info );
 	if ( (hasNormals != 0) ) {
@@ -156,7 +144,7 @@ void NiGeometryData::Write( ostream& out, const map<NiObjectRef,unsigned int> &
 		};
 	};
 	if ( info.version >= 0x0A010000 ) {
-		if ( (((hasNormals != 0)) && ((unknownByte1 & 16))) ) {
+		if ( (((hasNormals != 0)) && ((numUvSets & 4096))) ) {
 			for (unsigned int i3 = 0; i3 < unknownVectors1.size(); i3++) {
 				NifStream( unknownVectors1[i3], out, info );
 			};
@@ -179,19 +167,12 @@ void NiGeometryData::Write( ostream& out, const map<NiObjectRef,unsigned int> &
 	if ( info.version <= 0x04000002 ) {
 		NifStream( hasUv, out, info );
 	};
-	if ( info.version <= 0x04020200 ) {
-		for (unsigned int i2 = 0; i2 < uvSets.size(); i2++) {
-			for (unsigned int i3 = 0; i3 < uvSets[i2].size(); i3++) {
-				NifStream( uvSets[i2][i3], out, info );
-			};
+	for (unsigned int i1 = 0; i1 < uvSets.size(); i1++) {
+		for (unsigned int i2 = 0; i2 < uvSets[i1].size(); i2++) {
+			NifStream( uvSets[i1][i2], out, info );
 		};
 	};
 	if ( info.version >= 0x0A000100 ) {
-		for (unsigned int i2 = 0; i2 < uvSets.size(); i2++) {
-			for (unsigned int i3 = 0; i3 < uvSets[i2].size(); i3++) {
-				NifStream( uvSets[i2][i3], out, info );
-			};
-		};
 		NifStream( consistencyFlags, out, info );
 	};
 	if ( info.version >= 0x14000004 ) {
@@ -218,7 +199,6 @@ std::string NiGeometryData::asString( bool verbose ) const {
 	unsigned int array_output_count = 0;
 	out << NiObject::asString();
 	numUvSets = (unsigned short)(uvSets.size());
-	numUvSets2 = (byte)(uvSets.size());
 	numVertices = (unsigned short)(vertices.size());
 	out << "  Name:  " << name << endl;
 	out << "  Num Vertices:  " << numVertices << endl;
@@ -238,8 +218,7 @@ std::string NiGeometryData::asString( bool verbose ) const {
 			array_output_count++;
 		};
 	};
-	out << "  Num UV Sets 2:  " << numUvSets2 << endl;
-	out << "  Unknown Byte 1:  " << unknownByte1 << endl;
+	out << "  Num UV Sets:  " << numUvSets << endl;
 	out << "  Has Normals:  " << hasNormals << endl;
 	if ( (hasNormals != 0) ) {
 		array_output_count = 0;
@@ -255,7 +234,7 @@ std::string NiGeometryData::asString( bool verbose ) const {
 			array_output_count++;
 		};
 	};
-	if ( (((hasNormals != 0)) && ((unknownByte1 & 16))) ) {
+	if ( (((hasNormals != 0)) && ((numUvSets & 4096))) ) {
 		array_output_count = 0;
 		for (unsigned int i2 = 0; i2 < unknownVectors1.size(); i2++) {
 			if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
@@ -298,7 +277,6 @@ std::string NiGeometryData::asString( bool verbose ) const {
 			array_output_count++;
 		};
 	};
-	out << "  Num UV Sets:  " << numUvSets << endl;
 	out << "  Has UV:  " << hasUv << endl;
 	array_output_count = 0;
 	for (unsigned int i1 = 0; i1 < uvSets.size(); i1++) {
diff --git a/src/obj/NiSequence.cpp b/src/obj/NiSequence.cpp
index 3e6765e7..21d65720 100644
--- a/src/obj/NiSequence.cpp
+++ b/src/obj/NiSequence.cpp
@@ -83,7 +83,7 @@ void NiSequence::Read( istream& in, list<unsigned int> & link_stack, const NifIn
 		if ( ( info.version >= 0x0A01006A ) && ( info.userVersion == 11 ) ) {
 			NifStream( controlledBlocks[i1].priority_, in, info );
 		};
-		if ( info.version >= 0x0A020000 ) {
+		if ( ( info.version >= 0x0A020000 ) && ( info.version <= 0x14000005 ) ) {
 			NifStream( block_num, in, info );
 			link_stack.push_back( block_num );
 		};
@@ -197,7 +197,7 @@ void NiSequence::Write( ostream& out, const map<NiObjectRef,unsigned int> & link
 		if ( ( info.version >= 0x0A01006A ) && ( info.userVersion == 11 ) ) {
 			NifStream( controlledBlocks[i1].priority_, out, info );
 		};
-		if ( info.version >= 0x0A020000 ) {
+		if ( ( info.version >= 0x0A020000 ) && ( info.version <= 0x14000005 ) ) {
 			if ( info.version < VER_3_3_0_13 ) {
 				NifStream( (unsigned int)&(*controlledBlocks[i1].stringPalette), out, info );
 			} else {
@@ -306,7 +306,7 @@ void NiSequence::FixLinks( const map<unsigned int,NiObjectRef> & objects, list<u
 		if ( ( info.version >= 0x0A01006A ) && ( info.version <= 0x0A01006A ) ) {
 			controlledBlocks[i1].unknownLink2 = FixLink<NiObject>( objects, link_stack, info );
 		};
-		if ( info.version >= 0x0A020000 ) {
+		if ( ( info.version >= 0x0A020000 ) && ( info.version <= 0x14000005 ) ) {
 			controlledBlocks[i1].stringPalette = FixLink<NiStringPalette>( objects, link_stack, info );
 		};
 	};
diff --git a/src/obj/NiSkinInstance.cpp b/src/obj/NiSkinInstance.cpp
index 38bed632..4633dc91 100644
--- a/src/obj/NiSkinInstance.cpp
+++ b/src/obj/NiSkinInstance.cpp
@@ -32,7 +32,8 @@ NiSkinInstance::~NiSkinInstance() {
 
 	//Unflag any bones that were part of this skin instance
 	for ( unsigned int i = 0; i < bones.size(); ++i ) {
-		bones[i]->SetSkinFlag(false);
+		if (NULL != bones[i])
+			bones[i]->SetSkinFlag(false);
 	}
 
 	//Inform Skeleton Root of detatchment and clear it.
diff --git a/src/obj/NiSourceTexture.cpp b/src/obj/NiSourceTexture.cpp
index 97cc2455..bbb60775 100644
--- a/src/obj/NiSourceTexture.cpp
+++ b/src/obj/NiSourceTexture.cpp
@@ -21,7 +21,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiSourceTexture::TYPE("NiSourceTexture", &NiTexture::TYPE );
 
-NiSourceTexture::NiSourceTexture() : useExternal((byte)1), unknownLink(NULL), unknownByte((byte)0), pixelData(NULL), pixelLayout((PixelLayout)5), useMipmaps((MipMapFormat)2), alphaFormat((AlphaFormat)3), unknownByte2((byte)1) {
+NiSourceTexture::NiSourceTexture() : useExternal((byte)1), unknownLink(NULL), unknownByte((byte)0), pixelData(NULL), pixelLayout((PixelLayout)5), useMipmaps((MipMapFormat)2), alphaFormat((AlphaFormat)3), unknownByte1((byte)1), unknownByte2((byte)1), unknownByte3((byte)0) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -72,10 +72,13 @@ void NiSourceTexture::Read( istream& in, list<unsigned int> & link_stack, const
 	NifStream( pixelLayout, in, info );
 	NifStream( useMipmaps, in, info );
 	NifStream( alphaFormat, in, info );
-	NifStream( unknownByte, in, info );
+	NifStream( unknownByte1, in, info );
 	if ( info.version >= 0x0A01006A ) {
 		NifStream( unknownByte2, in, info );
 	};
+	if ( info.version >= 0x14030003 ) {
+		NifStream( unknownByte3, in, info );
+	};
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -127,10 +130,13 @@ void NiSourceTexture::Write( ostream& out, const map<NiObjectRef,unsigned int> &
 	NifStream( pixelLayout, out, info );
 	NifStream( useMipmaps, out, info );
 	NifStream( alphaFormat, out, info );
-	NifStream( unknownByte, out, info );
+	NifStream( unknownByte1, out, info );
 	if ( info.version >= 0x0A01006A ) {
 		NifStream( unknownByte2, out, info );
 	};
+	if ( info.version >= 0x14030003 ) {
+		NifStream( unknownByte3, out, info );
+	};
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -156,7 +162,9 @@ std::string NiSourceTexture::asString( bool verbose ) const {
 	out << "  Pixel Layout:  " << pixelLayout << endl;
 	out << "  Use Mipmaps:  " << useMipmaps << endl;
 	out << "  Alpha Format:  " << alphaFormat << endl;
+	out << "  Unknown Byte 1:  " << unknownByte1 << endl;
 	out << "  Unknown Byte 2:  " << unknownByte2 << endl;
+	out << "  Unknown Byte 3:  " << unknownByte3 << endl;
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
diff --git a/src/obj/NiStencilProperty.cpp b/src/obj/NiStencilProperty.cpp
index 8e8b192b..2fbe1617 100644
--- a/src/obj/NiStencilProperty.cpp
+++ b/src/obj/NiStencilProperty.cpp
@@ -47,12 +47,19 @@ void NiStencilProperty::Read( istream& in, list<unsigned int> & link_stack, cons
 	};
 	NifStream( stencilEnabled, in, info );
 	NifStream( stencilFunction, in, info );
-	NifStream( stencilRef, in, info );
-	NifStream( stencilMask, in, info );
-	NifStream( failAction, in, info );
-	NifStream( zFailAction, in, info );
-	NifStream( passAction, in, info );
-	NifStream( drawMode, in, info );
+	if ( info.version <= 0x14000005 ) {
+		NifStream( stencilRef, in, info );
+		NifStream( stencilMask, in, info );
+		NifStream( failAction, in, info );
+		NifStream( zFailAction, in, info );
+		NifStream( passAction, in, info );
+		NifStream( drawMode, in, info );
+	};
+	if ( info.version >= 0x14010003 ) {
+		for (unsigned int i2 = 0; i2 < 5; i2++) {
+			NifStream( unknownBytes[i2], in, info );
+		};
+	};
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -68,12 +75,19 @@ void NiStencilProperty::Write( ostream& out, const map<NiObjectRef,unsigned int>
 	};
 	NifStream( stencilEnabled, out, info );
 	NifStream( stencilFunction, out, info );
-	NifStream( stencilRef, out, info );
-	NifStream( stencilMask, out, info );
-	NifStream( failAction, out, info );
-	NifStream( zFailAction, out, info );
-	NifStream( passAction, out, info );
-	NifStream( drawMode, out, info );
+	if ( info.version <= 0x14000005 ) {
+		NifStream( stencilRef, out, info );
+		NifStream( stencilMask, out, info );
+		NifStream( failAction, out, info );
+		NifStream( zFailAction, out, info );
+		NifStream( passAction, out, info );
+		NifStream( drawMode, out, info );
+	};
+	if ( info.version >= 0x14010003 ) {
+		for (unsigned int i2 = 0; i2 < 5; i2++) {
+			NifStream( unknownBytes[i2], out, info );
+		};
+	};
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -95,6 +109,18 @@ std::string NiStencilProperty::asString( bool verbose ) const {
 	out << "  Z Fail Action:  " << zFailAction << endl;
 	out << "  Pass Action:  " << passAction << endl;
 	out << "  Draw Mode:  " << drawMode << endl;
+	array_output_count = 0;
+	for (unsigned int i1 = 0; i1 < 5; i1++) {
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl;
+			break;
+		};
+		if ( !verbose && ( array_output_count > MAXARRAYDUMP ) ) {
+			break;
+		};
+		out << "    Unknown Bytes[" << i1 << "]:  " << unknownBytes[i1] << endl;
+		array_output_count++;
+	};
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
diff --git a/src/obj/NiStringsExtraData.cpp b/src/obj/NiStringsExtraData.cpp
index b0bfcfc2..3a0b1d7d 100644
--- a/src/obj/NiStringsExtraData.cpp
+++ b/src/obj/NiStringsExtraData.cpp
@@ -113,12 +113,17 @@ std::list<NiObjectRef> NiStringsExtraData::GetRefs() const {
 //--BEGIN MISC CUSTOM CODE--//
 
 vector<string> NiStringsExtraData::GetData() const {
-	return data;
+	vector<string> value;
+	value.resize(data.size());
+	std::copy(data.begin(), data.end(), value.begin());
+	return value;
 };
 	
 void NiStringsExtraData::SetData( const vector<string> & n ) {
 	numStrings = (unsigned int)(n.size());
-	data = n;
+	vector<string> value;
+	data.resize(n.size());
+	std::copy(n.begin(), n.end(), data.begin());
 };
 
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiTextKeyExtraData.cpp b/src/obj/NiTextKeyExtraData.cpp
index 417eb650..edb80ba4 100644
--- a/src/obj/NiTextKeyExtraData.cpp
+++ b/src/obj/NiTextKeyExtraData.cpp
@@ -46,9 +46,17 @@ void NiTextKeyExtraData::Read( istream& in, list<unsigned int> & link_stack, con
 		NifStream( unknownInt1, in, info );
 	};
 	NifStream( numTextKeys, in, info );
-	textKeys.resize(numTextKeys);
-	for (unsigned int i1 = 0; i1 < textKeys.size(); i1++) {
-		NifStream( textKeys[i1], in, info, 1 );
+	if ( info.version >= 0x14010003 ) {
+		textKeys.resize(numTextKeys);
+		for (unsigned int i2 = 0; i2 < textKeys.size(); i2++) {
+			NifStream( textKeys[i2], in, info, 1 );
+		};
+	};
+	if ( info.version <= 0x14000005 ) {
+		textKeys.resize(numTextKeys);
+		for (unsigned int i2 = 0; i2 < textKeys.size(); i2++) {
+			NifStream( textKeys[i2], in, info, 1 );
+		};
 	};
 
 	//--BEGIN POST-READ CUSTOM CODE--//
@@ -65,8 +73,15 @@ void NiTextKeyExtraData::Write( ostream& out, const map<NiObjectRef,unsigned int
 		NifStream( unknownInt1, out, info );
 	};
 	NifStream( numTextKeys, out, info );
-	for (unsigned int i1 = 0; i1 < textKeys.size(); i1++) {
-		NifStream( textKeys[i1], out, info, 1 );
+	if ( info.version >= 0x14010003 ) {
+		for (unsigned int i2 = 0; i2 < textKeys.size(); i2++) {
+			NifStream( textKeys[i2], out, info, 1 );
+		};
+	};
+	if ( info.version <= 0x14000005 ) {
+		for (unsigned int i2 = 0; i2 < textKeys.size(); i2++) {
+			NifStream( textKeys[i2], out, info, 1 );
+		};
 	};
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
@@ -120,11 +135,31 @@ std::list<NiObjectRef> NiTextKeyExtraData::GetRefs() const {
 //--BEGIN MISC CUSTOM CODE--//
 
 vector< Key<string> > NiTextKeyExtraData::GetKeys() const {
-	return textKeys;
+	vector< Key<string> > value;
+	for (vector< Key<IndexString> >::const_iterator itr = textKeys.begin(); itr != textKeys.end(); ++itr) {
+		Key<string> key;
+		key.time = (*itr).time;
+		key.data = (*itr).data;
+		key.tension = (*itr).tension;
+		key.bias = (*itr).bias;
+		key.continuity = (*itr).continuity;
+		value.push_back(key);
+	}
+	return value;
 }
 
 void NiTextKeyExtraData::SetKeys( vector< Key<string> > const & keys ) {
-	textKeys = keys;
+	vector< Key<string> > value;
+	textKeys.clear();
+	for (vector< Key<string> >::const_iterator itr = keys.begin(); itr != keys.end(); ++itr) {
+		Key<IndexString> key;
+		key.time = (*itr).time;
+		key.data = (*itr).data;
+		key.tension = (*itr).tension;
+		key.bias = (*itr).bias;
+		key.continuity = (*itr).continuity;
+		textKeys.push_back(key);
+	}
 }
 
 //--END CUSTOM CODE--//
diff --git a/src/obj/NiTexturingProperty.cpp b/src/obj/NiTexturingProperty.cpp
index 84ddeb31..904c3f03 100644
--- a/src/obj/NiTexturingProperty.cpp
+++ b/src/obj/NiTexturingProperty.cpp
@@ -69,15 +69,27 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( info.version <= 0x0A000102 ) {
 		NifStream( flags, in, info );
 	};
-	NifStream( applyMode, in, info );
+	if ( info.version >= 0x14010003 ) {
+		NifStream( flags, in, info );
+	};
+	if ( info.version <= 0x14000005 ) {
+		NifStream( applyMode, in, info );
+	};
 	NifStream( textureCount, in, info );
 	NifStream( hasBaseTexture, in, info );
 	if ( (hasBaseTexture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( baseTexture.clampMode, in, info );
-		NifStream( baseTexture.filterMode, in, info );
-		NifStream( baseTexture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( baseTexture.clampMode, in, info );
+			NifStream( baseTexture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( baseTexture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( baseTexture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( baseTexture.ps2L, in, info );
 			NifStream( baseTexture.ps2K, in, info );
@@ -100,9 +112,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (hasDarkTexture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( darkTexture.clampMode, in, info );
-		NifStream( darkTexture.filterMode, in, info );
-		NifStream( darkTexture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( darkTexture.clampMode, in, info );
+			NifStream( darkTexture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( darkTexture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( darkTexture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( darkTexture.ps2L, in, info );
 			NifStream( darkTexture.ps2K, in, info );
@@ -125,9 +144,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (hasDetailTexture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( detailTexture.clampMode, in, info );
-		NifStream( detailTexture.filterMode, in, info );
-		NifStream( detailTexture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( detailTexture.clampMode, in, info );
+			NifStream( detailTexture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( detailTexture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( detailTexture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( detailTexture.ps2L, in, info );
 			NifStream( detailTexture.ps2K, in, info );
@@ -150,9 +176,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (hasGlossTexture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( glossTexture.clampMode, in, info );
-		NifStream( glossTexture.filterMode, in, info );
-		NifStream( glossTexture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glossTexture.clampMode, in, info );
+			NifStream( glossTexture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( glossTexture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glossTexture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( glossTexture.ps2L, in, info );
 			NifStream( glossTexture.ps2K, in, info );
@@ -175,9 +208,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (hasGlowTexture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( glowTexture.clampMode, in, info );
-		NifStream( glowTexture.filterMode, in, info );
-		NifStream( glowTexture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glowTexture.clampMode, in, info );
+			NifStream( glowTexture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( glowTexture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glowTexture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( glowTexture.ps2L, in, info );
 			NifStream( glowTexture.ps2K, in, info );
@@ -200,9 +240,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (hasBumpMapTexture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( bumpMapTexture.clampMode, in, info );
-		NifStream( bumpMapTexture.filterMode, in, info );
-		NifStream( bumpMapTexture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( bumpMapTexture.clampMode, in, info );
+			NifStream( bumpMapTexture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( bumpMapTexture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( bumpMapTexture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( bumpMapTexture.ps2L, in, info );
 			NifStream( bumpMapTexture.ps2K, in, info );
@@ -228,9 +275,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (hasDecal0Texture != 0) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( decal0Texture.clampMode, in, info );
-		NifStream( decal0Texture.filterMode, in, info );
-		NifStream( decal0Texture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal0Texture.clampMode, in, info );
+			NifStream( decal0Texture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal0Texture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal0Texture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal0Texture.ps2L, in, info );
 			NifStream( decal0Texture.ps2K, in, info );
@@ -255,9 +309,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (((textureCount >= 8)) && ((hasDecal1Texture != 0))) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( decal1Texture.clampMode, in, info );
-		NifStream( decal1Texture.filterMode, in, info );
-		NifStream( decal1Texture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal1Texture.clampMode, in, info );
+			NifStream( decal1Texture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal1Texture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal1Texture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal1Texture.ps2L, in, info );
 			NifStream( decal1Texture.ps2K, in, info );
@@ -282,9 +343,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (((textureCount >= 9)) && ((hasDecal2Texture != 0))) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( decal2Texture.clampMode, in, info );
-		NifStream( decal2Texture.filterMode, in, info );
-		NifStream( decal2Texture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal2Texture.clampMode, in, info );
+			NifStream( decal2Texture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal2Texture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal2Texture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal2Texture.ps2L, in, info );
 			NifStream( decal2Texture.ps2K, in, info );
@@ -309,9 +377,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 	if ( (((textureCount >= 10)) && ((hasDecal3Texture != 0))) ) {
 		NifStream( block_num, in, info );
 		link_stack.push_back( block_num );
-		NifStream( decal3Texture.clampMode, in, info );
-		NifStream( decal3Texture.filterMode, in, info );
-		NifStream( decal3Texture.uvSet, in, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal3Texture.clampMode, in, info );
+			NifStream( decal3Texture.filterMode, in, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal3Texture.flags, in, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal3Texture.uvSet, in, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal3Texture.ps2L, in, info );
 			NifStream( decal3Texture.ps2K, in, info );
@@ -338,9 +413,16 @@ void NiTexturingProperty::Read( istream& in, list<unsigned int> & link_stack, co
 			if ( (shaderTextures[i2].isUsed != 0) ) {
 				NifStream( block_num, in, info );
 				link_stack.push_back( block_num );
-				NifStream( shaderTextures[i2].textureData.clampMode, in, info );
-				NifStream( shaderTextures[i2].textureData.filterMode, in, info );
-				NifStream( shaderTextures[i2].textureData.uvSet, in, info );
+				if ( info.version <= 0x14000005 ) {
+					NifStream( shaderTextures[i2].textureData.clampMode, in, info );
+					NifStream( shaderTextures[i2].textureData.filterMode, in, info );
+				};
+				if ( info.version >= 0x14010003 ) {
+					NifStream( shaderTextures[i2].textureData.flags, in, info );
+				};
+				if ( info.version <= 0x14000005 ) {
+					NifStream( shaderTextures[i2].textureData.uvSet, in, info );
+				};
 				if ( info.version <= 0x0A020000 ) {
 					NifStream( shaderTextures[i2].textureData.ps2L, in, info );
 					NifStream( shaderTextures[i2].textureData.ps2K, in, info );
@@ -376,7 +458,12 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 	if ( info.version <= 0x0A000102 ) {
 		NifStream( flags, out, info );
 	};
-	NifStream( applyMode, out, info );
+	if ( info.version >= 0x14010003 ) {
+		NifStream( flags, out, info );
+	};
+	if ( info.version <= 0x14000005 ) {
+		NifStream( applyMode, out, info );
+	};
 	NifStream( textureCount, out, info );
 	NifStream( hasBaseTexture, out, info );
 	if ( (hasBaseTexture != 0) ) {
@@ -389,9 +476,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( baseTexture.clampMode, out, info );
-		NifStream( baseTexture.filterMode, out, info );
-		NifStream( baseTexture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( baseTexture.clampMode, out, info );
+			NifStream( baseTexture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( baseTexture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( baseTexture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( baseTexture.ps2L, out, info );
 			NifStream( baseTexture.ps2K, out, info );
@@ -421,9 +515,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( darkTexture.clampMode, out, info );
-		NifStream( darkTexture.filterMode, out, info );
-		NifStream( darkTexture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( darkTexture.clampMode, out, info );
+			NifStream( darkTexture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( darkTexture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( darkTexture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( darkTexture.ps2L, out, info );
 			NifStream( darkTexture.ps2K, out, info );
@@ -453,9 +554,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( detailTexture.clampMode, out, info );
-		NifStream( detailTexture.filterMode, out, info );
-		NifStream( detailTexture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( detailTexture.clampMode, out, info );
+			NifStream( detailTexture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( detailTexture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( detailTexture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( detailTexture.ps2L, out, info );
 			NifStream( detailTexture.ps2K, out, info );
@@ -485,9 +593,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( glossTexture.clampMode, out, info );
-		NifStream( glossTexture.filterMode, out, info );
-		NifStream( glossTexture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glossTexture.clampMode, out, info );
+			NifStream( glossTexture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( glossTexture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glossTexture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( glossTexture.ps2L, out, info );
 			NifStream( glossTexture.ps2K, out, info );
@@ -517,9 +632,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( glowTexture.clampMode, out, info );
-		NifStream( glowTexture.filterMode, out, info );
-		NifStream( glowTexture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glowTexture.clampMode, out, info );
+			NifStream( glowTexture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( glowTexture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( glowTexture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( glowTexture.ps2L, out, info );
 			NifStream( glowTexture.ps2K, out, info );
@@ -549,9 +671,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( bumpMapTexture.clampMode, out, info );
-		NifStream( bumpMapTexture.filterMode, out, info );
-		NifStream( bumpMapTexture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( bumpMapTexture.clampMode, out, info );
+			NifStream( bumpMapTexture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( bumpMapTexture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( bumpMapTexture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( bumpMapTexture.ps2L, out, info );
 			NifStream( bumpMapTexture.ps2K, out, info );
@@ -584,9 +713,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( decal0Texture.clampMode, out, info );
-		NifStream( decal0Texture.filterMode, out, info );
-		NifStream( decal0Texture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal0Texture.clampMode, out, info );
+			NifStream( decal0Texture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal0Texture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal0Texture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal0Texture.ps2L, out, info );
 			NifStream( decal0Texture.ps2K, out, info );
@@ -618,9 +754,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( decal1Texture.clampMode, out, info );
-		NifStream( decal1Texture.filterMode, out, info );
-		NifStream( decal1Texture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal1Texture.clampMode, out, info );
+			NifStream( decal1Texture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal1Texture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal1Texture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal1Texture.ps2L, out, info );
 			NifStream( decal1Texture.ps2K, out, info );
@@ -652,9 +795,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( decal2Texture.clampMode, out, info );
-		NifStream( decal2Texture.filterMode, out, info );
-		NifStream( decal2Texture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal2Texture.clampMode, out, info );
+			NifStream( decal2Texture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal2Texture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal2Texture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal2Texture.ps2L, out, info );
 			NifStream( decal2Texture.ps2K, out, info );
@@ -686,9 +836,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 				NifStream( 0xFFFFFFFF, out, info );
 			}
 		}
-		NifStream( decal3Texture.clampMode, out, info );
-		NifStream( decal3Texture.filterMode, out, info );
-		NifStream( decal3Texture.uvSet, out, info );
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal3Texture.clampMode, out, info );
+			NifStream( decal3Texture.filterMode, out, info );
+		};
+		if ( info.version >= 0x14010003 ) {
+			NifStream( decal3Texture.flags, out, info );
+		};
+		if ( info.version <= 0x14000005 ) {
+			NifStream( decal3Texture.uvSet, out, info );
+		};
 		if ( info.version <= 0x0A020000 ) {
 			NifStream( decal3Texture.ps2L, out, info );
 			NifStream( decal3Texture.ps2K, out, info );
@@ -721,9 +878,16 @@ void NiTexturingProperty::Write( ostream& out, const map<NiObjectRef,unsigned in
 						NifStream( 0xFFFFFFFF, out, info );
 					}
 				}
-				NifStream( shaderTextures[i2].textureData.clampMode, out, info );
-				NifStream( shaderTextures[i2].textureData.filterMode, out, info );
-				NifStream( shaderTextures[i2].textureData.uvSet, out, info );
+				if ( info.version <= 0x14000005 ) {
+					NifStream( shaderTextures[i2].textureData.clampMode, out, info );
+					NifStream( shaderTextures[i2].textureData.filterMode, out, info );
+				};
+				if ( info.version >= 0x14010003 ) {
+					NifStream( shaderTextures[i2].textureData.flags, out, info );
+				};
+				if ( info.version <= 0x14000005 ) {
+					NifStream( shaderTextures[i2].textureData.uvSet, out, info );
+				};
 				if ( info.version <= 0x0A020000 ) {
 					NifStream( shaderTextures[i2].textureData.ps2L, out, info );
 					NifStream( shaderTextures[i2].textureData.ps2K, out, info );
@@ -766,6 +930,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << baseTexture.source << endl;
 		out << "    Clamp Mode:  " << baseTexture.clampMode << endl;
 		out << "    Filter Mode:  " << baseTexture.filterMode << endl;
+		out << "    Flags:  " << baseTexture.flags << endl;
 		out << "    UV Set:  " << baseTexture.uvSet << endl;
 		out << "    PS2 L:  " << baseTexture.ps2L << endl;
 		out << "    PS2 K:  " << baseTexture.ps2K << endl;
@@ -784,6 +949,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << darkTexture.source << endl;
 		out << "    Clamp Mode:  " << darkTexture.clampMode << endl;
 		out << "    Filter Mode:  " << darkTexture.filterMode << endl;
+		out << "    Flags:  " << darkTexture.flags << endl;
 		out << "    UV Set:  " << darkTexture.uvSet << endl;
 		out << "    PS2 L:  " << darkTexture.ps2L << endl;
 		out << "    PS2 K:  " << darkTexture.ps2K << endl;
@@ -802,6 +968,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << detailTexture.source << endl;
 		out << "    Clamp Mode:  " << detailTexture.clampMode << endl;
 		out << "    Filter Mode:  " << detailTexture.filterMode << endl;
+		out << "    Flags:  " << detailTexture.flags << endl;
 		out << "    UV Set:  " << detailTexture.uvSet << endl;
 		out << "    PS2 L:  " << detailTexture.ps2L << endl;
 		out << "    PS2 K:  " << detailTexture.ps2K << endl;
@@ -820,6 +987,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << glossTexture.source << endl;
 		out << "    Clamp Mode:  " << glossTexture.clampMode << endl;
 		out << "    Filter Mode:  " << glossTexture.filterMode << endl;
+		out << "    Flags:  " << glossTexture.flags << endl;
 		out << "    UV Set:  " << glossTexture.uvSet << endl;
 		out << "    PS2 L:  " << glossTexture.ps2L << endl;
 		out << "    PS2 K:  " << glossTexture.ps2K << endl;
@@ -838,6 +1006,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << glowTexture.source << endl;
 		out << "    Clamp Mode:  " << glowTexture.clampMode << endl;
 		out << "    Filter Mode:  " << glowTexture.filterMode << endl;
+		out << "    Flags:  " << glowTexture.flags << endl;
 		out << "    UV Set:  " << glowTexture.uvSet << endl;
 		out << "    PS2 L:  " << glowTexture.ps2L << endl;
 		out << "    PS2 K:  " << glowTexture.ps2K << endl;
@@ -856,6 +1025,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << bumpMapTexture.source << endl;
 		out << "    Clamp Mode:  " << bumpMapTexture.clampMode << endl;
 		out << "    Filter Mode:  " << bumpMapTexture.filterMode << endl;
+		out << "    Flags:  " << bumpMapTexture.flags << endl;
 		out << "    UV Set:  " << bumpMapTexture.uvSet << endl;
 		out << "    PS2 L:  " << bumpMapTexture.ps2L << endl;
 		out << "    PS2 K:  " << bumpMapTexture.ps2K << endl;
@@ -877,6 +1047,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << decal0Texture.source << endl;
 		out << "    Clamp Mode:  " << decal0Texture.clampMode << endl;
 		out << "    Filter Mode:  " << decal0Texture.filterMode << endl;
+		out << "    Flags:  " << decal0Texture.flags << endl;
 		out << "    UV Set:  " << decal0Texture.uvSet << endl;
 		out << "    PS2 L:  " << decal0Texture.ps2L << endl;
 		out << "    PS2 K:  " << decal0Texture.ps2K << endl;
@@ -897,6 +1068,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << decal1Texture.source << endl;
 		out << "    Clamp Mode:  " << decal1Texture.clampMode << endl;
 		out << "    Filter Mode:  " << decal1Texture.filterMode << endl;
+		out << "    Flags:  " << decal1Texture.flags << endl;
 		out << "    UV Set:  " << decal1Texture.uvSet << endl;
 		out << "    PS2 L:  " << decal1Texture.ps2L << endl;
 		out << "    PS2 K:  " << decal1Texture.ps2K << endl;
@@ -917,6 +1089,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << decal2Texture.source << endl;
 		out << "    Clamp Mode:  " << decal2Texture.clampMode << endl;
 		out << "    Filter Mode:  " << decal2Texture.filterMode << endl;
+		out << "    Flags:  " << decal2Texture.flags << endl;
 		out << "    UV Set:  " << decal2Texture.uvSet << endl;
 		out << "    PS2 L:  " << decal2Texture.ps2L << endl;
 		out << "    PS2 K:  " << decal2Texture.ps2K << endl;
@@ -937,6 +1110,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 		out << "    Source:  " << decal3Texture.source << endl;
 		out << "    Clamp Mode:  " << decal3Texture.clampMode << endl;
 		out << "    Filter Mode:  " << decal3Texture.filterMode << endl;
+		out << "    Flags:  " << decal3Texture.flags << endl;
 		out << "    UV Set:  " << decal3Texture.uvSet << endl;
 		out << "    PS2 L:  " << decal3Texture.ps2L << endl;
 		out << "    PS2 K:  " << decal3Texture.ps2K << endl;
@@ -962,6 +1136,7 @@ std::string NiTexturingProperty::asString( bool verbose ) const {
 			out << "      Source:  " << shaderTextures[i1].textureData.source << endl;
 			out << "      Clamp Mode:  " << shaderTextures[i1].textureData.clampMode << endl;
 			out << "      Filter Mode:  " << shaderTextures[i1].textureData.filterMode << endl;
+			out << "      Flags:  " << shaderTextures[i1].textureData.flags << endl;
 			out << "      UV Set:  " << shaderTextures[i1].textureData.uvSet << endl;
 			out << "      PS2 L:  " << shaderTextures[i1].textureData.ps2L << endl;
 			out << "      PS2 K:  " << shaderTextures[i1].textureData.ps2K << endl;
diff --git a/src/obj/NiTriShape.cpp b/src/obj/NiTriShape.cpp
index 20d2b632..a97a0aff 100644
--- a/src/obj/NiTriShape.cpp
+++ b/src/obj/NiTriShape.cpp
@@ -19,7 +19,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type NiTriShape::TYPE("NiTriShape", &NiTriBasedGeom::TYPE );
 
-NiTriShape::NiTriShape() {
+NiTriShape::NiTriShape() : unknownInt1((int)0), unknownBoolean1(false) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -42,6 +42,10 @@ void NiTriShape::Read( istream& in, list<unsigned int> & link_stack, const NifIn
 	//--END CUSTOM CODE--//
 
 	NiTriBasedGeom::Read( in, link_stack, info );
+	if ( info.version >= 0x14030003 ) {
+		NifStream( unknownInt1, in, info );
+		NifStream( unknownBoolean1, in, info );
+	};
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -52,6 +56,10 @@ void NiTriShape::Write( ostream& out, const map<NiObjectRef,unsigned int> & link
 	//--END CUSTOM CODE--//
 
 	NiTriBasedGeom::Write( out, link_map, info );
+	if ( info.version >= 0x14030003 ) {
+		NifStream( unknownInt1, out, info );
+		NifStream( unknownBoolean1, out, info );
+	};
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -64,6 +72,8 @@ std::string NiTriShape::asString( bool verbose ) const {
 	stringstream out;
 	unsigned int array_output_count = 0;
 	out << NiTriBasedGeom::asString();
+	out << "  Unknown Int 1:  " << unknownInt1 << endl;
+	out << "  Unknown Boolean 1:  " << unknownBoolean1 << endl;
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
diff --git a/src/obj/NiVertexColorProperty.cpp b/src/obj/NiVertexColorProperty.cpp
index 8828bdde..a85af0f3 100644
--- a/src/obj/NiVertexColorProperty.cpp
+++ b/src/obj/NiVertexColorProperty.cpp
@@ -43,8 +43,10 @@ void NiVertexColorProperty::Read( istream& in, list<unsigned int> & link_stack,
 
 	NiProperty::Read( in, link_stack, info );
 	NifStream( flags, in, info );
-	NifStream( vertexMode, in, info );
-	NifStream( lightingMode, in, info );
+	if ( info.version <= 0x14000005 ) {
+		NifStream( vertexMode, in, info );
+		NifStream( lightingMode, in, info );
+	};
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -56,8 +58,10 @@ void NiVertexColorProperty::Write( ostream& out, const map<NiObjectRef,unsigned
 
 	NiProperty::Write( out, link_map, info );
 	NifStream( flags, out, info );
-	NifStream( vertexMode, out, info );
-	NifStream( lightingMode, out, info );
+	if ( info.version <= 0x14000005 ) {
+		NifStream( vertexMode, out, info );
+		NifStream( lightingMode, out, info );
+	};
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
diff --git a/src/obj/NiZBufferProperty.cpp b/src/obj/NiZBufferProperty.cpp
index f7ecd1e9..5f15a587 100644
--- a/src/obj/NiZBufferProperty.cpp
+++ b/src/obj/NiZBufferProperty.cpp
@@ -43,7 +43,7 @@ void NiZBufferProperty::Read( istream& in, list<unsigned int> & link_stack, cons
 
 	NiProperty::Read( in, link_stack, info );
 	NifStream( flags, in, info );
-	if ( info.version >= 0x0401000C ) {
+	if ( ( info.version >= 0x0401000C ) && ( info.version <= 0x14000005 ) ) {
 		NifStream( function, in, info );
 	};
 
@@ -57,7 +57,7 @@ void NiZBufferProperty::Write( ostream& out, const map<NiObjectRef,unsigned int>
 
 	NiProperty::Write( out, link_map, info );
 	NifStream( flags, out, info );
-	if ( info.version >= 0x0401000C ) {
+	if ( ( info.version >= 0x0401000C ) && ( info.version <= 0x14000005 ) ) {
 		NifStream( function, out, info );
 	};
 
diff --git a/src/obj/bhkBoxShape.cpp b/src/obj/bhkBoxShape.cpp
index 4c7aef22..31624002 100644
--- a/src/obj/bhkBoxShape.cpp
+++ b/src/obj/bhkBoxShape.cpp
@@ -19,7 +19,7 @@ using namespace Niflib;
 //Definition of TYPE constant
 const Type bhkBoxShape::TYPE("bhkBoxShape", &bhkConvexShape::TYPE );
 
-bhkBoxShape::bhkBoxShape() : unknownShort1((unsigned short)0), unknownShort2((unsigned short)0), unknownShort3((unsigned short)0), unknownShort4((unsigned short)0), min_Size(0.0f) {
+bhkBoxShape::bhkBoxShape() : unknownShort1((unsigned short)0), unknownShort2((unsigned short)0), unknownShort3((unsigned short)0), unknownShort4((unsigned short)0), minimumSize(0.0f) {
 	//--BEGIN CONSTRUCTOR CUSTOM CODE--//
 	//--END CUSTOM CODE--//
 }
@@ -47,7 +47,7 @@ void bhkBoxShape::Read( istream& in, list<unsigned int> & link_stack, const NifI
 	NifStream( unknownShort3, in, info );
 	NifStream( unknownShort4, in, info );
 	NifStream( dimensions, in, info );
-	NifStream( min_Size, in, info );
+	NifStream( minimumSize, in, info );
 
 	//--BEGIN POST-READ CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -63,7 +63,7 @@ void bhkBoxShape::Write( ostream& out, const map<NiObjectRef,unsigned int> & lin
 	NifStream( unknownShort3, out, info );
 	NifStream( unknownShort4, out, info );
 	NifStream( dimensions, out, info );
-	NifStream( min_Size, out, info );
+	NifStream( minimumSize, out, info );
 
 	//--BEGIN POST-WRITE CUSTOM CODE--//
 	//--END CUSTOM CODE--//
@@ -81,7 +81,7 @@ std::string bhkBoxShape::asString( bool verbose ) const {
 	out << "  Unknown Short 3:  " << unknownShort3 << endl;
 	out << "  Unknown Short 4:  " << unknownShort4 << endl;
 	out << "  Dimensions:  " << dimensions << endl;
-	out << "  Min. size:  " << min_Size << endl;
+	out << "  Minimum Size:  " << minimumSize << endl;
 	return out.str();
 
 	//--BEGIN POST-STRING CUSTOM CODE--//
-- 
GitLab