diff --git a/NvTriStrip/NvTriStripObjects.cpp b/NvTriStrip/NvTriStripObjects.cpp
index d2c3247866136ad12afe48606656896b72b3b3db..6428bf4f520478f9897b838fa017fa5353f96fb5 100644
--- a/NvTriStrip/NvTriStripObjects.cpp
+++ b/NvTriStrip/NvTriStripObjects.cpp
@@ -1,5 +1,5 @@
 
-#pragma warning( disable : 4786 )  
+//#pragma warning( disable : 4786 )  
 
 #include <assert.h>
 #include <set>
diff --git a/SConstruct b/SConstruct
index ea454ee40d264ca3588a2e3901b20a75c688b83e..708b24e70022ec74a26a9f3659543be2a3cabe74 100644
--- a/SConstruct
+++ b/SConstruct
@@ -11,94 +11,79 @@ Help("""
 
 ##Global Vars, should add cc, cxx, build, etc eventually...
 ##May want to turn Jobs down, we will try and detect an appropriate JOB rate for linux
-JOBS ='1'
-DETECT_JOBS = 'yes'  #Set this to no, if you are setting JOBS!!
-DEBUG ='no'
-TUNE ='yes'
-CFFLAGS_EXTRA_WARNING ='no'
-PYWRAP = True               # set to False if you do not want to build the python wrapper
+JOBS = 1                      # default number of jobs, if detection fails
+DETECT_JOBS = True            # set this to False, if you are setting JOBS
+DEBUG = True                  # turn on debugging info?
+CFFLAGS_EXTRA_WARNING = False # extra compiler warnings
+PYWRAP = True                 # build the python wrapper?
+TEST = True                   # build test scripts?
 
 # Setting up a basic default environment
 # Theory is it can be expanded for versatility, like swig doesn't seem to like jobs of 4
 
 env = Environment(ENV = os.environ)
 
-
-# detect platform
-if sys.platform == 'linux2' or sys.platform == 'linux-i386':
-    OS = 'linux'
-    python_lib = ['python%d.%d' % sys.version_info[0:2]]
-    python_libpath = [sysconfig.get_python_lib (0, 1) + '/config']
-    python_include = [sysconfig.get_python_inc ()]
-    env.Append(CCFLAGS = ' -Iinclude -fPIC -Wall -pipe')
-elif sys.platform == 'cygwin':
-    OS = 'linux'
+# linux platform
+if sys.platform in ['linux2', 'linux-i386', 'cygwin']:
+    # set python environment
     python_lib = ['python%d.%d' % sys.version_info[0:2]]
     python_libpath = [sysconfig.get_python_lib (0, 1) + '/config']
     python_include = [sysconfig.get_python_inc ()]
+    # set compiler flags
     env.Append(CCFLAGS = ' -Wall')
+    if CFFLAGS_EXTRA_WARNING:
+         env.Append(CCFLAGS = ' -Wextra')
+    if sys.platform != 'cygwin':
+        env.Append(CCFLAGS = ' -fPIC -pipe')
+    # flags for debugging info
+    if DEBUG:
+         env.Append(CCFLAGS = ' -O0 -g3 -ggdb')
+    # flags for tuning (only if DEBUG is False)
+    else:
+       env.Append(CCFLAGS = ' -O3')
+       # architecture specific tuning
+       # x86, x86_64, or what? (better way?)
+       proc = commands.getoutput('uname -m')
+       if proc == 'x86_64':
+           arch = 'x86_64'
+       #elif exp.match(proc): # broken
+       elif proc in ['x86', 'i386', 'i486', 'i586', 'i686']:
+           arch = 'x86'
+       elif proc in ['Power Macintosh', 'ppc']:
+           arch = 'ppc'
+       else:
+           arch = None
+       # needs to be cleaned up and expanded to include Intel
+       if arch == 'x86_64':
+           if commands.getoutput('uname -i') == 'AuthenticAMD':
+               env.Append(CCFLAGS = ' -mtune=k8')
+           #elif commands.getoutput('uname -i') == 'GenuineIntel':
+           #    env.Append(CCFLAGS = ' -mtune=nocona')
+    # detect the number of jobs
+    if DETECT_JOBS:
+        detected_jobs = int(commands.getoutput('cat /proc/cpuinfo | grep -c "^processor"'))
+        if detected_jobs >= 2:
+            JOBS = detected_jobs
+
+# windows platform
 elif sys.platform == 'win32':
-    OS = 'windows'
     python_include = [sysconfig.get_python_inc()]
     python_libpath = [sysconfig.get_python_lib(1, 1) + '/../libs']
     python_lib = ['python24']
-    env.Append(CCFLAGS = '/EHsc /O2 /GS /Zi /TP')
+    env.Append(CCFLAGS = '/EHsc /GS /TP')
+    if DEBUG:
+        env.Append(CCFLAGS = ' /Zi')
+    else:
+        env.Append(CCFLAGS = ' /O2')
+
+# other platforms
 else:
     print "Error: Platform %s not supported."%sys.platform
     Exit(1)
 
-
-
-#Debug, Extra, 02 checks
-if (sys.platform == 'linux2' or sys.platform == 'linux-i386') or sys.platform == 'cygwin':
-    if DEBUG == 'yes':
-         env.Append(CCFLAGS = ' -g3')
-    if CFFLAGS_EXTRA_WARNING == 'yes':
-         env.Append(CCFLAGS = ' -Wextra')
-    if TUNE == 'yes':
-       env.Append(CCFLAGS = ' -O2')
-    if TUNE == 'yes' and DEBUG == 'yes' :
-	print "TUNE and DEBUG may conflict!!"
-
-
-
-# Proc x86, x86_64, or what? Better way?
-proc = commands.getoutput('uname -m')
-if proc == 'x86_64':
-  arch = 'x86_64'
-#elif exp.match(proc): # broken
-elif proc == 'x86':
-  arch = 'x86'
-elif proc == 'Power Macintosh' or proc == 'ppc':
-  arch = 'ppc'
-else:
-  arch = 'cpu'
-
-#This is ugly, needs to be cleaned up and expanded to include Intel.
-#
-if arch == 'x86_64' and TUNE == 'yes':
-   if commands.getoutput('uname -i') == 'AuthenticAMD':
-      env.Append(CCFLAGS = ' -mtune=k8')
-#   if commands.getoutput('uname -i') == 'GenuineIntel':
-#	env.Append(CCFLAGS = ' -mtune=nocona')
-#Should cover 64 bit versions of Intel chips, but don't have one and never bothered to look into it
-
-
-
-#We want to detect the number of jobs! Although some folks depending on sys load may want to set it more aggressively.
-if DETECT_JOBS == 'yes' and OS == 'linux':
-	detected_jobs = commands.getoutput('cat /proc/cpuinfo | grep -c "^processor"')
-	if detected_jobs >= '1':
-		print "Detected Jobs: %s"%detected_jobs
-		JOBS = detected_jobs
-		print "Detected Jobs changing to %s"%JOBS
-	else:
-		print "Error Detecting jobs!"
-
-
+# set number of jobs
 env.SetOption('num_jobs', JOBS)
 
-
 # detect SWIG
 try:
     env['SWIG']
@@ -111,6 +96,7 @@ Please install SWIG to build the python wrapper."""
     print "You can download SWIG from http://www.swig.org/\n"
 
 
+
 gen_objfiles = Split("""
 src/gen/ByteArray.cpp
 src/gen/Footer.cpp
@@ -401,10 +387,9 @@ niflib = env.StaticLibrary('niflib', [core_objfiles, gen_objfiles, obj_objfiles,
 
 # build Python wrapper
 if PYWRAP:
-    SConscript('swig/SConscript' , exports=['env', 'python_lib', 'python_libpath', 'python_include', 'niflib'])
-
-# Here's how to compile niflyze:
-#env.Program('niflyze', 'niflyze.cpp', LIBS=[niflib], LIBPATH=['.'])
+    SConscript('swig/SConscript' , exports=['env', 'python_lib', 'python_libpath', 'python_include', 'niflib', 'TEST'])
 
 # A test program:
-#env.Program('test', 'test.cpp', LIBS=[niflib], LIBPATH=['.']) 
+if TEST:
+    env.Program('niflib_test', 'niflib_test.cpp', LIBS=[niflib], LIBPATH=['.'])
+
diff --git a/include/gen/Header.h b/include/gen/Header.h
index efe36b960c343dfc6204ea87973d92ae805399d1..8fef87f7de6a38625887dcedc53d24b2cf04838d 100644
--- a/include/gen/Header.h
+++ b/include/gen/Header.h
@@ -31,7 +31,7 @@ struct NIFLIB_API Header {
 	/*!
 	 * Unknown.
 	 */
-	array<3,LineString > copyright;
+	vector<LineString> copyright;
 	/*!
 	 * The NIF version, in hexadecimal notation: 0x04000002, 0x0401000C,
 	 * 0x04020002, 0x04020100, 0x04020200, 0x0A000100, 0x0A010000,
diff --git a/niflib_test.cpp b/niflib_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eecee5a2e41c612e3e45bfd5122c9ec6a5e15363
--- /dev/null
+++ b/niflib_test.cpp
@@ -0,0 +1,38 @@
+#include <cassert>
+
+#include "include/niflib.h"
+#include "include/obj/NiNode.h"
+
+using namespace Niflib;
+using namespace std;
+
+void CreateSimpleNif() {
+  NiNodeRef root(new NiNode);
+  Matrix44 x(Vector3(2,3,4),Matrix33(0,0,1,0,1,0,-1,0,0),0.123);
+  root->SetLocalTransform(x);
+  NifInfo nifinfo(0x14000005);
+  nifinfo.userVersion = 11;
+  nifinfo.creator = "amorilia";
+  WriteNifTree("test.nif", root, nifinfo);
+};
+
+void CheckSimpleNif() {
+  NifInfo nifinfo;
+  NiObjectRef root_obj = ReadNifTree("test.nif", &nifinfo);
+  NiNodeRef root = DynamicCast<NiNode>(root_obj);
+  assert(nifinfo.version == 0x14000005);
+  assert(nifinfo.userVersion == 11);
+  assert(nifinfo.creator == "amorilia");
+  assert(root != NULL);
+  Matrix44 x(Vector3(2,3,4),Matrix33(0,0,1,0,1,0,-1,0,0),0.123);
+  Matrix44 y = root->GetLocalTransform();
+  for (int i=0; i<4; i++)
+    for (int j=0; j<4; j++)
+      assert(abs(x[i][j]-y[i][j]) < 0.0001);
+};
+
+int main() {
+  CreateSimpleNif();
+  CheckSimpleNif();
+  return 0;
+}
diff --git a/src/gen/Header.cpp b/src/gen/Header.cpp
index a861387d0c9c963de5640a248fe92052474fcf5e..28c13690cef908877ee868b1d6dcedc2760f5f97 100644
--- a/src/gen/Header.cpp
+++ b/src/gen/Header.cpp
@@ -5,7 +5,7 @@ All rights reserved.  Please see niflib.h for licence. */
 using namespace Niflib;
 
 //Constructor
-Header::Header() : version((unsigned int)0x04000002), endianType((byte)1), userVersion((unsigned int)0), numBlocks((unsigned int)0), userVersion2((unsigned int)0), numBlockTypes((unsigned short)0), unknownInt2((unsigned int)0) {};
+Header::Header() : copyright(3), version((unsigned int)0x04000002), endianType((byte)1), userVersion((unsigned int)0), numBlocks((unsigned int)0), userVersion2((unsigned int)0), numBlockTypes((unsigned short)0), unknownInt2((unsigned int)0) {};
 
 //Copy Constructor
 Header::Header( const Header & src ) {
diff --git a/src/niflib.cpp b/src/niflib.cpp
index c4b5a82d52ce176d67f80234d2801b9a54498a1e..273f9a57bbec6993de50d90909d0b5ad3e6b65e3 100644
--- a/src/niflib.cpp
+++ b/src/niflib.cpp
@@ -138,10 +138,9 @@ vector<NiObjectRef> ReadNifList( string const & file_name, NifInfo * info ) {
 
 	//--Open File--//
 	ifstream in( file_name.c_str(), ifstream::binary );
-
-	return ReadNifList( in, info );
-
+	vector<NiObjectRef> ret = ReadNifList( in, info );
 	in.close();
+	return ret;
 }
 
 vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
@@ -354,7 +353,7 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) {
 
 	for ( map<unsigned,NiObjectRef>::iterator it = objects.begin(); it != objects.end(); ++it ) {
 #ifdef DEBUG_LINK_PHASE
-		cout << i << ":  " << blocks[i] << endl;
+		cout << it->first << ":  " << it->second << endl;
 #endif
 		//Fix links & other pre-processing
 		it->second->FixLinks( objects, link_stack, header.version, header.userVersion );
@@ -505,7 +504,8 @@ void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<
 	//Add this object type to the map if it isn't there already
 	if ( type_map.find( (Type*)&(root->GetType()) ) == type_map.end() ) {
 		//The type has not yet been registered, so register it
-		type_map[ (Type*)&(root->GetType()) ] = (unsigned int)(type_map.size());
+		unsigned int n = type_map.size();
+		type_map[ (Type*)&(root->GetType()) ] = n;
 	}
 
    // Oblivion has very rigid requirements about block ordering and the bhkRigidBody 
@@ -522,7 +522,8 @@ void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<
 
    // If reverse is set then add the link after children otherwise add it before
    if (!reverse) {
-      link_map[root] = (unsigned int)(link_map.size());
+      unsigned int n = link_map.size();
+      link_map[root] = n;
    }
 
    //Call this function on all links of this object	
@@ -534,7 +535,8 @@ void EnumerateObjects( NiObject * root, map<Type*,unsigned int> & type_map, map<
    }
 
    if (reverse) {
-      link_map[root] = (unsigned int)(link_map.size());
+      unsigned int n = link_map.size();
+      link_map[root] = n;
    }
 }
 
diff --git a/swig/SConscript b/swig/SConscript
index 095959e3345e426937d6fcd6ecbca86b0c1aad93..18550b79e7c1ef358d9d501a5839303ed3212b2f 100644
--- a/swig/SConscript
+++ b/swig/SConscript
@@ -1,3 +1,9 @@
 Import('*')
 
 niflib_python = env.SharedLibrary('_niflib', 'pyniflib.i', LIBS=[niflib] + python_lib, LIBPATH = python_libpath, SWIGFLAGS = '-c++ -python', CPPPATH = ['.'] + python_include, SHLIBPREFIX='')
+
+if TEST:
+    import unittest
+    import niflib_test
+    unittest.main(niflib_test)
+
diff --git a/swig/niflib_test.py b/swig/niflib_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..30fb606dd8e746f4c3363bf92a9a2441f7fdaa69
--- /dev/null
+++ b/swig/niflib_test.py
@@ -0,0 +1,41 @@
+# quick test of the niflib library in python
+
+import unittest
+import os
+from niflib import *
+
+class TestNiNode(unittest.TestCase):
+    def setUp(self):
+        # (TODO: use python's temporary file creation method)
+
+        # create nif file
+        root = CreateNiNode()
+        self.x = Matrix44(Vector3(2,3,4),Matrix33(0,0,1,0,1,0,-1,0,0),0.123)
+        root.SetLocalTransform(self.x)
+        self.nifinfo = NifInfo()
+        self.nifinfo.version = 0x14000005
+        self.nifinfo.creator = "amorilia"
+        self.nifinfo.userVersion = 11
+        WriteNifTree("test.nif", root.Ptr(), self.nifinfo)
+
+        # read nif file
+        self.nifinfo_in = NifInfo()
+        root_obj = ReadNifFile("test.nif", self.nifinfo_in)
+        root_in = DynamicCastToNiNode(root_obj.Ptr())
+
+        self.x_in = root_in.GetLocalTransform()
+
+        # delete nif file
+        os.remove("test.nif")
+
+    def test(self):
+        self.failIf(self.nifinfo.version != self.nifinfo_in.version)
+        self.failIf(self.nifinfo.userVersion != self.nifinfo_in.userVersion)
+        self.failIf(self.nifinfo.creator != self.nifinfo_in.creator)
+        for i in range(4):
+            for j in range(4):
+                self.assertAlmostEqual(self.x[i][j], self.x_in[i][j], 5)
+
+if __name__ == '__main__':
+    unittest.main()
+
diff --git a/swig/pyniflib.h b/swig/pyniflib.h
index c6e5e53f66a8cb80b0711e7a50a1601a8e265131..3dbd281b3c16d912a84edccc5d452de3f562cec9 100644
--- a/swig/pyniflib.h
+++ b/swig/pyniflib.h
@@ -1,6 +1,8 @@
 #ifndef _PYNIFLIB_H_
 #define _PYNIFLIB_H_
 
+#include "../include/niflib.h"
+#include "../include/obj/NiObject.h"
 #include "../include/obj/NiNode.h"
 
 namespace Niflib {
@@ -9,6 +11,10 @@ using namespace std;
 
 Niflib::NiNodeRef CreateNiNode() { return Niflib::NiNodeRef(new Niflib::NiNode); }
 
+// SWIG does not like ReadNifTree; so far I have no idea why.
+// As a workaround, you can use this wrapper function.
+Niflib::NiObjectRef ReadNifFile( string name, Niflib::NifInfo * nifinfo) { return Niflib::ReadNifTree(name, nifinfo);}
+
 };
 
 #endif
diff --git a/swig/pyniflib.i b/swig/pyniflib.i
index c11d15e866ffe86badb064bfb55de3d506456279..0f7a60a3e4dd65ec09e8943033b7899a60474f9d 100644
--- a/swig/pyniflib.i
+++ b/swig/pyniflib.i
@@ -76,20 +76,21 @@ POSSIBILITY OF SUCH DAMAGE. */
 // essential for NIF exporting and importing scripts.
 // This will reduce the size of the wrapper file.
 
-/*
-
 // various function ignores (might be put pack in final version)
 %ignore asString;
 %ignore FixLinks;
 %ignore Read;
 %ignore Write;
 %ignore operator=;
+%ignore operator[];
 %ignore TypeConst;
 %ignore GetIDString;
 %ignore IsSameType;
 %ignore IsDerivedType;
 %ignore NumObjectsInMemory;
 
+/*
+
 // vector ignores (will be unignored again once wrapper is functional)
 %ignore iterator;
 %ignore pop;
@@ -117,7 +118,9 @@ POSSIBILITY OF SUCH DAMAGE. */
 */
 
 // ignores objects python does not need to know of anyway
-//ignore Ptr;
+//%ignore Ptr;
+
+/*
 
 // ignore all base objects: we only need access via the Ref objects
 %ignore NiObject;
@@ -343,6 +346,8 @@ POSSIBILITY OF SUCH DAMAGE. */
 %ignore NiZBufferProperty;
 %ignore RootCollisionNode;
 
+*/
+
 // Import the symbols from these but do not include them in the wrapper
 %import "../include/gen/obj_defines.h"
 %import "../include/NIF_IO.h"
@@ -359,10 +364,18 @@ POSSIBILITY OF SUCH DAMAGE. */
 
 %{
 #include "../include/niflib.h"
+%}
+
+// SWIG is very picky about namespaces. Using namespace Niflib throughout
+// ensures that SWIG wraps all types in the right way.
+%{
+using namespace Niflib;
+%}
+
+%{
 #include "../include/Ref.h"
 #include "../include/Type.h"
 #include "../include/nif_math.h"
-
 #include "../include/obj/NiObject.h"
 #include "../include/obj/AKeyedData.h"
 #include "../include/obj/AParticleModifier.h"
@@ -617,11 +630,6 @@ POSSIBILITY OF SUCH DAMAGE. */
 #include "../include/gen/LimitedHingeDescriptor.h"
 %}
 
-// This resolves an issue with SWIG and namespace?
-%{
-using namespace Niflib;
-%}
-
 // Extra Python interface functions are defined next
 %include "pyniflib.h"
 %{
@@ -630,7 +638,7 @@ using namespace Niflib;
 %}
 
 // Data structures
-
+/*
 %include "../include/gen/ByteArray.h"
 %include "../include/gen/Footer.h"
 %include "../include/gen/LODRange.h"
@@ -693,18 +701,20 @@ using namespace Niflib;
 %template(vector_MatchGroup) std::vector<Niflib::MatchGroup>;
 %template(pair_int_float) std::pair<int, float>;
 %template(map_int_float) std::map<int, float>;
+*/
 
 // NIF file blocks
 
 %include "../include/obj/NiObject.h"
-//%ignore NiObjectRef;
+%template(NiObjectRef) Niflib::Ref<Niflib::NiObject>;
 %include "../include/obj/NiObjectNET.h";
-//%ignore NiObjectNetRef;
-//template(NiObjectNETRef) Niflib::Ref<Niflib::NiObjectNET>;
-//template(DynamicCastToNiObjectNET) Niflib::DynamicCast<Niflib::NiObjectNET>;
-//template(StaticCastToNiObjectNET) Niflib::StaticCast<Niflib::NiObjectNET>;
+%template(NiObjectNETRef) Niflib::Ref<Niflib::NiObjectNET>;
+%template(DynamicCastToNiObjectNET) Niflib::DynamicCast<Niflib::NiObjectNET>;
+%template(StaticCastToNiObjectNET) Niflib::StaticCast<Niflib::NiObjectNET>;
 %include "../include/obj/NiAVObject.h";
-//%ignore NiAVObjectRef;
+%template(NiAVObjectRef) Niflib::Ref<Niflib::NiAVObject>;
+%template(DynamicCastToNiAVObject) Niflib::DynamicCast<Niflib::NiAVObject>;
+%template(StaticCastToNiAVObject) Niflib::StaticCast<Niflib::NiAVObject>;
 %include "../include/obj/NiNode.h"
 %template(NiNodeRef) Niflib::Ref<Niflib::NiNode>;
 %template(DynamicCastToNiNode) Niflib::DynamicCast<Niflib::NiNode>;
diff --git a/swig/pyniflib_test.py b/swig/pyniflib_test.py
deleted file mode 100644
index 225190fa23453c183934d0cfe33722631ce1de64..0000000000000000000000000000000000000000
--- a/swig/pyniflib_test.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# quick test of the niflib library in python
-
-from niflib import *
-
-root = CreateNiNode()
-x = Matrix44(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
-root.SetLocalTransform(x)
-
-nifinfo = NifInfo()
-nifinfo.version = 0x14000005
-nifinfo.creator = "amorilia"
-WriteNifTree( "test.nif", root.Ptr(), nifinfo )
-