diff --git a/NIF_IO.cpp b/NIF_IO.cpp
index 09c4bf5780da50e5265ecea3cf333495dc093f7f..4b03566f5494751a21beefa8458c58927e19d413 100644
--- a/NIF_IO.cpp
+++ b/NIF_IO.cpp
@@ -119,7 +119,7 @@ float ReadFloat( istream &in ){
 string ReadString( istream &in ) {
 	uint len = ReadUInt( in );
 	string out;
-	if ( len > 3000 )
+	if ( len > 4000 )
 	    throw runtime_error("String too long. Not a NIF file or unsupported format?");
 	if ( len > 0 ) {
 	    out.resize(len);
diff --git a/gen/Header.cpp b/gen/Header.cpp
index 91ef3097a8ec9034127e77bc213a75c9d3e22850..2362ff7fb3e8f5bf316b3bc0ed0a919ba9c748cf 100644
--- a/gen/Header.cpp
+++ b/gen/Header.cpp
@@ -12,7 +12,7 @@ Header::Header() : version((uint)0x04000002), endianType((byte)1), userVersion((
 //Destructor
 Header::~Header() {};
 
-void Header::Read( istream& in, list<uint> & link_stack, unsigned int version, unsigned int user_version ) {
+void Header::Read( istream& in ) {
 	NifStream( headerString, in, version );
 	NifStream( version, in, version );
 	if ( version >= 0x14000004 ) {
@@ -63,7 +63,7 @@ void Header::Read( istream& in, list<uint> & link_stack, unsigned int version, u
 	};
 }
 
-void Header::Write( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const {
+void Header::Write( ostream& out ) const {
 	NifStream( headerString, out, version );
 	NifStream( version, out, version );
 	if ( version >= 0x14000004 ) {
diff --git a/gen/Header.h b/gen/Header.h
index 575863cf453d16a81dc15768f6014f4fda0759d4..478edf28b04765cae433b6e17d7cde2f9372cdb6 100644
--- a/gen/Header.h
+++ b/gen/Header.h
@@ -83,8 +83,8 @@ struct NIFLIB_API Header {
 	 * Unknown.
 	 */
 	uint unknownInt2;
-	void Read( istream& in, list<uint> & link_stack, unsigned int version, unsigned int user_version );
-	void Write( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const;
+	void Read( istream& in );
+	void Write( ostream& out ) const;
 	string asString( bool verbose = false ) const;
 };
 
diff --git a/nif_math.cpp b/nif_math.cpp
index 490268ed6f54efdd4c5bc81c32ba052044e795d3..a348a7fd2acbf8a83b5436d8e03f6d21dda60ddc 100644
--- a/nif_math.cpp
+++ b/nif_math.cpp
@@ -354,10 +354,8 @@ Matrix44 Matrix44::Inverse() const {
 	Matrix44 result;
 
 	float det = Determinant();
-	cout << "Determinant:  " << det << endl;
 	for (int r = 0; r < 4; r++) {
 		for (int c = 0; c < 4; c++) {
-			//cout << "Adjoint(" << r << "," << c << "):  " << Adjunct(r, c) << endl;
 			result[c][r] = Adjoint(r, c) / det;
 		}
 	}
diff --git a/niflib.cpp b/niflib.cpp
index 154c544b5cf5ba188bb4d60025a04833c4cedeb5..922db60e92e3b27c7c269d362028e5c83cba7613 100644
--- a/niflib.cpp
+++ b/niflib.cpp
@@ -2,8 +2,9 @@
 All rights reserved.  Please see niflib.h for licence. */
 
 //#define DEBUG // this will produce lots of output
-//#define PRINT_BLOCK_NAMES
-//#define PRINT_BLOCK_CONTENTS
+//#define PRINT_OBJECT_NAMES
+//#define PRINT_OBJECT_CONTENTS
+#define DEBUG_LINK_PHASE
 
 #include "niflib.h"
 #include "obj/NiAVObject.h"
@@ -129,108 +130,113 @@ vector<NiObjectRef> ReadNifList( string const & file_name ) {
 vector<NiObjectRef> ReadNifList( istream & in ) {
 
 	//--Read Header--//
-	char header_string[64];
-	in.getline( header_string, 64 );
-	string headerstr(header_string);
-
-	// make sure this is a NIF file
-	if ( ( headerstr.substr(0, 22) != "NetImmerse File Format" )
-	&& ( headerstr.substr(0, 20) != "Gamebryo File Format" ) )
-		throw runtime_error("Not a NIF file.");
-
-	// detect old versions
-	if ( ( headerstr == "NetImmerse File Format, Version 3.1" )
-	|| ( headerstr == "NetImmerse File Format, Version 3.03" )
-	|| ( headerstr == "NetImmerse File Format, Version 3.0" )
-	|| ( headerstr == "NetImmerse File Format, Version 2.3" ) )
-		throw runtime_error("Unsupported: " + headerstr);
-
-	uint version = ReadUInt( in );
-
-	//There is an unknown Byte here from version 20.0.0.4 on
-	byte endianType;
-	if ( version >= VER_20_0_0_4 ) {
-		endianType = ReadByte( in );
-	}
-
-	//There is an Unknown Int here from version 10.1.0.0 on
-	uint userVersion = 0;
-	if ( version >= VER_10_1_0_0 ) {
-		userVersion = ReadUInt( in );
-	}
-
-	uint numBlocks = ReadUInt( in );
-
-	if ( userVersion != 0 ) {
-		uint len;
-		ReadUInt( in );
-		len = ReadByte( in );
-		for (uint i = 0; i < len; i++) ReadByte( in );
-		len = ReadByte( in );
-		for (uint i = 0; i < len; i++) ReadByte( in );
-		len = ReadByte( in );
-		for (uint i = 0; i < len; i++) ReadByte( in );
-	}
-	
-	vector<string> blockTypes;
-	vector<short> blockTypeIndex;
-	//New header data exists from version 5.0.0.1 on
-	if ( version >= 0x05000001 ) {
-		short numBlockTypes = ReadUShort( in );
-		blockTypes.resize(numBlockTypes);
-		for ( uint i = 0; i < blockTypes.size(); ++i ) {
-			blockTypes[i] = ReadString( in );
-		}
-
-		blockTypeIndex.resize(numBlocks);
-		for ( uint i = 0; i < blockTypeIndex.size(); ++i ) {
-			blockTypeIndex[i] = ReadUShort( in );
-		}
+	Header header;
 
-		uint unknownInt2 =
-		ReadUInt( in );
-
-		//Output
-#ifdef DEBUG
-		cout << endl << endl 
-			 << "====[ " << "File Header ]====" << endl
-			 << "Header:  " << header_string << endl
-			 << "Version:  " << version << endl
-			 << "Endian Type:  " << endianType << endl
-			 << "User Version:  " << userVersion << endl
-			 << "Number of Blocks: " << numBlocks << endl
-			 << "Block Types:  " << uint(blockTypes.size()) << endl;
-
-		for ( uint i = 0; i < blockTypes.size(); ++i ) {
-			cout << "   " << i << ":  " << blockTypes[i] << endl;
-		}
-
-		cout << "Block Type Indices:  " << numBlocks << endl;
-		for ( uint i = 0; i < blockTypeIndex.size(); ++i ) {
-			cout << "   " << i + 1 << ":  " << blockTypeIndex[i] << "(" << blockTypes[blockTypeIndex[i]] << ")" << endl;
-		}
+	//Read header.
+	header.Read( in );
 
-		cout << "Unknown Int 2:  " << unknownInt2 << endl;
-#endif
-	} else {
-#ifdef DEBUG
-		//Output
-		cout << endl << endl 
-			<< "====[ " << "File Header ]====" << endl
-			<< "Header:  " << header_string << endl
-			<< "Version:  " << version << endl
-			<< "Number of Blocks: " << numBlocks << endl;
-#endif
-	}
-
-	//TODO:  Actually read the user_version from the right place
-	uint user_version = 0;
+//	char header_string[64];
+//	in.getline( header_string, 64 );
+//	string headerstr(header_string);
+//
+//	// make sure this is a NIF file
+//	if ( ( headerstr.substr(0, 22) != "NetImmerse File Format" )
+//	&& ( headerstr.substr(0, 20) != "Gamebryo File Format" ) )
+//		throw runtime_error("Not a NIF file.");
+//
+//	// detect old versions
+//	if ( ( headerstr == "NetImmerse File Format, Version 3.1" )
+//	|| ( headerstr == "NetImmerse File Format, Version 3.03" )
+//	|| ( headerstr == "NetImmerse File Format, Version 3.0" )
+//	|| ( headerstr == "NetImmerse File Format, Version 2.3" ) )
+//		throw runtime_error("Unsupported: " + headerstr);
+//
+//	uint version = ReadUInt( in );
+//
+//	//There is an unknown Byte here from version 20.0.0.4 on
+//	byte endianType;
+//	if ( version >= VER_20_0_0_4 ) {
+//		endianType = ReadByte( in );
+//	}
+//
+//	//There is an Unknown Int here from version 10.1.0.0 on
+//	uint userVersion = 0;
+//	if ( version >= VER_10_1_0_0 ) {
+//		userVersion = ReadUInt( in );
+//	}
+//
+//	uint numBlocks = ReadUInt( in );
+//
+//	if ( userVersion != 0 ) {
+//		uint len;
+//		ReadUInt( in );
+//		len = ReadByte( in );
+//		for (uint i = 0; i < len; i++) ReadByte( in );
+//		len = ReadByte( in );
+//		for (uint i = 0; i < len; i++) ReadByte( in );
+//		len = ReadByte( in );
+//		for (uint i = 0; i < len; i++) ReadByte( in );
+//	}
+//	
+//	vector<string> blockTypes;
+//	vector<short> blockTypeIndex;
+//	//New header data exists from version 5.0.0.1 on
+//	if ( version >= 0x05000001 ) {
+//		short numBlockTypes = ReadUShort( in );
+//		blockTypes.resize(numBlockTypes);
+//		for ( uint i = 0; i < blockTypes.size(); ++i ) {
+//			blockTypes[i] = ReadString( in );
+//		}
+//
+//		blockTypeIndex.resize(numBlocks);
+//		for ( uint i = 0; i < blockTypeIndex.size(); ++i ) {
+//			blockTypeIndex[i] = ReadUShort( in );
+//		}
+//
+//		uint unknownInt2 =
+//		ReadUInt( in );
+//
+//		//Output
+//#ifdef DEBUG
+//		cout << endl << endl 
+//			 << "====[ " << "File Header ]====" << endl
+//			 << "Header:  " << header_string << endl
+//			 << "Version:  " << version << endl
+//			 << "Endian Type:  " << endianType << endl
+//			 << "User Version:  " << userVersion << endl
+//			 << "Number of Blocks: " << numBlocks << endl
+//			 << "Block Types:  " << uint(blockTypes.size()) << endl;
+//
+//		for ( uint i = 0; i < blockTypes.size(); ++i ) {
+//			cout << "   " << i << ":  " << blockTypes[i] << endl;
+//		}
+//
+//		cout << "Block Type Indices:  " << numBlocks << endl;
+//		for ( uint i = 0; i < blockTypeIndex.size(); ++i ) {
+//			cout << "   " << i + 1 << ":  " << blockTypeIndex[i] << "(" << blockTypes[blockTypeIndex[i]] << ")" << endl;
+//		}
+//
+//		cout << "Unknown Int 2:  " << unknownInt2 << endl;
+//#endif
+//	} else {
+//#ifdef DEBUG
+//		//Output
+//		cout << endl << endl 
+//			<< "====[ " << "File Header ]====" << endl
+//			<< "Header:  " << header_string << endl
+//			<< "Version:  " << version << endl
+//			<< "Number of Blocks: " << numBlocks << endl;
+//#endif
+//	}
+//
+//	//TODO:  Actually read the user_version from the right place
+//	uint user_version = 0;
 
 	//--Read Blocks--//
-	vector<NiObjectRef> blocks( numBlocks ); //List to hold the blocks
+	vector<NiObjectRef> blocks( header.numBlocks ); //List to hold the blocks
 	list<uint> link_stack; //List to add link values to as they're read in from the file
 	string blockName;
-	for (uint i = 0; i < numBlocks; i++) {
+	for (uint i = 0; i < header.numBlocks; i++) {
 
 		//Check for EOF
 		//if (in.eof() ) {
@@ -238,10 +244,10 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 		//}
 	
 		//There are two ways to read blocks, one before version 5.0.0.1 and one after that
-		if ( version >= 0x05000001 ) {
+		if ( header.version >= 0x05000001 ) {
 			//From version 5.0.0.1 to version 10.0.1.0  there is a zero byte at the begining of each block
 			
-			if ( version <= VER_10_1_0_0 ) {
+			if ( header.version <= VER_10_1_0_0 ) {
 				uint checkValue = ReadUInt( in );
 				if ( checkValue != 0 ) {
 					//Throw an exception if it's not zero
@@ -253,7 +259,7 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 			}
 
 			// Find which block type this is by using the header arrays
-			blockName = blockTypes[ blockTypeIndex[i] ];
+			blockName = header.blockTypes[ header.blockTypeIndex[i] ];
 		} else {
 			// Find which block type this is by reading the string at this location
 			uint blockNameLength = ReadUInt( in );
@@ -276,7 +282,7 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 			}
 		}
 
-#ifdef PRINT_BLOCK_NAMES
+#ifdef PRINT_OBJECT_NAMES
 		cout << endl << i << ":  " << blockName;
 #endif
 
@@ -297,8 +303,8 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 		}
 
 		//blocks[i]->SetBlockNum(i);
-		blocks[i]->Read( in, link_stack, version, user_version );
-#ifdef PRINT_BLOCK_CONTENTS
+		blocks[i]->Read( in, link_stack, header.version, header.userVersion );
+#ifdef PRINT_OBJECT_CONTENTS
 		cout << endl << blocks[i]->asString() << endl;
 #endif
 	}
@@ -316,7 +322,7 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 	if ( ! in.eof() )
 		throw runtime_error("End of file not reached.  This NIF may be corrupt or improperly supported.");
 
-#ifdef DEBUG
+#ifdef DEBUG_LINK_PHASE
 	cout << "Link Stack:" << endl;
 	list<uint>::iterator it;
 	for ( it = link_stack.begin(); it != link_stack.end(); ++it ) {
@@ -324,16 +330,16 @@ vector<NiObjectRef> ReadNifList( istream & in ) {
 	}
 #endif
 	
-#ifdef DEBUG
+#ifdef DEBUG_LINK_PHASE
 	cout << "Fixing Links:"  << endl;
 #endif
 	//--Now that all blocks are read, go back and fix the links--//
 	for (uint i = 0; i < blocks.size(); ++i) {
-#ifdef DEBUG
-		cout << blocks[i]->GetType().GetTypeName() << endl;
+#ifdef DEBUG_LINK_PHASE
+		cout << i << ":  " << blocks[i] << endl;
 #endif
 		//Fix links & other pre-processing
-		blocks[i]->FixLinks( blocks, link_stack, version, user_version );
+		blocks[i]->FixLinks( blocks, link_stack, header.version, header.userVersion );
 	}
 
 
diff --git a/obj/NiNode.cpp b/obj/NiNode.cpp
index c77a97da2945543e60c669580c73c5339f618977..ba9f6d8ac0c9aed4b4f3d730c273ba27448b5557 100644
--- a/obj/NiNode.cpp
+++ b/obj/NiNode.cpp
@@ -101,28 +101,6 @@ bool NiNode::IsSkinInfluence() const {
 }
 
 void NiNode::AddSkin( NiSkinInstance * skin_inst ) {
-	//Ensure that all bones are below this node on the scene graph
-	vector<NiNodeRef> bones = skin_inst->GetBones();
-	for ( uint i = 0; i < bones.size(); ++i ) {
-		bool is_decended = false;
-		NiNodeRef node = bones[i];
-		while ( node != NULL ) {
-			if ( node == this ) {
-				is_decended = true;
-				break;
-			}
-			node = node->GetParent();
-		}
-		if ( is_decended == false ) {
-			throw runtime_error( "All bones must be lower than the skeleton root in the scene graph." );
-		}
-	}
-
-	//Flag any bones that are part of this skin instance
-	for ( uint i = 0; i < bones.size(); ++i ) {
-		bones[i]->SetSkinFlag(true);
-	}
-	
 	skins.push_back( skin_inst );
 }
 
@@ -194,7 +172,7 @@ void NiNode::GoToSkeletonBindPosition() {
 			//Loop through all bones again, checking for any that have this bone as a parent
 			for ( uint j = 0; j < bones.size(); ++j ) {
 				if ( bones[j]->GetParent() == bones[i] ) {
-					cout << "Bone " << bones[j] << " has bone " << bones[i] << " as parent." << endl;
+					//cout << "Bone " << bones[j] << " has bone " << bones[i] << " as parent." << endl;
 					//Node 2 has node 1 as a parent
 
 					//Get child offset Matrix33
diff --git a/obj/NiSkinInstance.cpp b/obj/NiSkinInstance.cpp
index 67f46409b440034dd68cf2abf652ea6268a6dca1..862171f41e4ee033e7943ceb508be600c0a80382 100644
--- a/obj/NiSkinInstance.cpp
+++ b/obj/NiSkinInstance.cpp
@@ -56,13 +56,34 @@ void NiSkinInstance::Bind( Ref<NiNode> skeleton_root, vector< Ref<NiNode> > bone
 	if ( bones.size() != 0 ) {
 		throw runtime_error("You have attempted to re-bind a skin that is already bound.  Unbind it first.");
 	}
-	
+
+	//Ensure that all bones are below the skeleton root node on the scene graph
+	for ( uint i = 0; i < bone_nodes.size(); ++i ) {
+		bool is_decended = false;
+		NiNodeRef node = bone_nodes[i];
+		while ( node != NULL ) {
+			if ( node == skeleton_root ) {
+				is_decended = true;
+				break;
+			}
+			node = node->GetParent();
+		}
+		if ( is_decended == false ) {
+			throw runtime_error( "All bones must be lower than the skeleton root in the scene graph." );
+		}
+	}
+
 	//Add the bones to the internal list
 	bones.resize( bone_nodes.size() );
 	for ( uint i = 0; i < bone_nodes.size(); ++i ) {
 		bones[i] = bone_nodes[i];
 	}
 
+	//Flag any bones that are part of this skin instance
+	for ( uint i = 0; i < bones.size(); ++i ) {
+		bones[i]->SetSkinFlag(true);
+	}
+
 	//Store skeleton root and inform it of this attachment
 	skeletonRoot = skeleton_root;
 	skeletonRoot->AddSkin( this );