diff --git a/NIF_IO.cpp b/NIF_IO.cpp index f74e1438d97e4cab981f05b51a9fb70f9d3bbc5f..a02bf437b0cb864efc4338d7dc2e3e48763ac863 100644 --- a/NIF_IO.cpp +++ b/NIF_IO.cpp @@ -236,6 +236,18 @@ void NifStream( HeaderString & val, istream& in, uint version ) { char tmp[64]; in.getline( tmp, 64 ); val.header = tmp; + + // make sure this is a NIF file + if ( ( val.header.substr(0, 22) != "NetImmerse File Format" ) + && ( val.header.substr(0, 20) != "Gamebryo File Format" ) ) + throw runtime_error("Not a NIF file."); + + // detect old versions + if ( ( val.header == "NetImmerse File Format, Version 3.1" ) + || ( val.header == "NetImmerse File Format, Version 3.03" ) + || ( val.header == "NetImmerse File Format, Version 3.0" ) + || ( val.header == "NetImmerse File Format, Version 2.3" ) ) + throw runtime_error("Unsupported: " + val.header); }; void NifStream( HeaderString const & val, ostream& out, uint version ) { @@ -251,7 +263,7 @@ void NifStream( HeaderString const & val, ostream& out, uint version ) { header_string << int_ver[0] << "." << int_ver[1] << "." << int_ver[2] << "." << int_ver[3]; - out << header_string.str(); + out << header_string.str() << "\n"; }; ostream & operator<<( ostream & out, HeaderString const & val ) { diff --git a/NIF_IO.h b/NIF_IO.h index df54f33d314f2f730f1948c1a5e8216094c15af0..263c63d2dd96023c912c2b8c76a389eb04fc860a 100644 --- a/NIF_IO.h +++ b/NIF_IO.h @@ -367,6 +367,11 @@ void NifStream( LightMode & val, istream& in, uint version = 0 ); void NifStream( LightMode const & val, ostream& out, uint version = 0 ); ostream & operator<<( ostream & out, LightMode const & val ); +//HeaderString +void NifStream( HeaderString & val, istream& in, uint version = 0 ); +void NifStream( HeaderString const & val, ostream& out, uint version = 0 ); +ostream & operator<<( ostream & out, HeaderString const & val ); + //--Templates--// //Key<T> diff --git a/gen/Footer.cpp b/gen/Footer.cpp index 1324f6285ff74b38c370ff9da53510f72adf4d3e..7b013df35dfb45a7625db73daea13935a07310c3 100644 --- a/gen/Footer.cpp +++ b/gen/Footer.cpp @@ -9,3 +9,33 @@ Footer::Footer() : numRoots((uint)0) {}; //Destructor Footer::~Footer() {}; + +void Footer::Read( istream& in, list<uint> & link_stack, unsigned int version, unsigned int user_version ) { + uint block_num; + NifStream( numRoots, in, version ); + roots.resize(numRoots); + for (uint i1 = 0; i1 < roots.size(); i1++) { + NifStream( block_num, in, version ); + link_stack.push_back( block_num ); + }; +} + +void Footer::Write( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const { + NifStream( numRoots, out, version ); + for (uint i1 = 0; i1 < roots.size(); i1++) { + NifStream( link_map[StaticCast<NiObject>(roots[i1])], out, version ); + }; +} + +string Footer::asString( bool verbose ) const { + stringstream out; + out << " Num Roots: " << numRoots << endl; + for (uint i1 = 0; i1 < roots.size(); i1++) { + if ( !verbose && ( i1 > MAXARRAYDUMP ) ) { + out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; + break; + }; + out << " Roots[" << i1 << "]: " << roots[i1] << endl; + }; + return out.str(); +} diff --git a/gen/Footer.h b/gen/Footer.h index 0a20591d52df47a2ffb3f8cab9bae8741a9bb162..bfc14dacc5fccb368e43287b1d96d70d023b618f 100644 --- a/gen/Footer.h +++ b/gen/Footer.h @@ -9,6 +9,7 @@ All rights reserved. Please see niflib.h for licence. */ // Forward define of referenced blocks #include "Ref.h" class NiAVObject; +#include "obj/NiObject.h" /*! * The NIF file footer. @@ -29,6 +30,9 @@ struct Footer { * node). */ vector<Ref<NiAVObject > > roots; + 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; + string asString( bool verbose = false ) const; }; #endif diff --git a/gen/Header.cpp b/gen/Header.cpp index cdc6e0b3c0d15f9bf16dcaaec1fb7a9c179caca2..ba59c6733a2d83cfe55e7fd5fb85d203418e64cd 100644 --- a/gen/Header.cpp +++ b/gen/Header.cpp @@ -11,3 +11,154 @@ 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 ) { + NifStream( headerString, in, version ); + NifStream( version, in, version ); + if ( version >= 0x14000004 ) { + NifStream( endianType, in, version ); + }; + if ( version >= 0x0A010000 ) { + NifStream( userVersion, in, version ); + }; + NifStream( numBlocks, in, version ); + if ( ( version >= 0x0A000102 ) && ( version <= 0x0A000102 ) ) { + NifStream( unknownInt1, in, version ); + }; + if ( version >= 0x0A010000 ) { + if ( (userVersion != 0) ) { + NifStream( unknownInt3, in, version ); + }; + }; + if ( version >= 0x0A000102 ) { + if ( (userVersion != 0) ) { + NifStream( creator_.length, in, version ); + creator_.value.resize(creator_.length); + for (uint i3 = 0; i3 < creator_.value.size(); i3++) { + NifStream( creator_.value[i3], in, version ); + }; + NifStream( exportType_.length, in, version ); + exportType_.value.resize(exportType_.length); + for (uint i3 = 0; i3 < exportType_.value.size(); i3++) { + NifStream( exportType_.value[i3], in, version ); + }; + NifStream( exportScript_.length, in, version ); + exportScript_.value.resize(exportScript_.length); + for (uint i3 = 0; i3 < exportScript_.value.size(); i3++) { + NifStream( exportScript_.value[i3], in, version ); + }; + }; + }; + if ( version >= 0x0A000100 ) { + NifStream( numBlockTypes, in, version ); + blockTypes.resize(numBlockTypes); + for (uint i2 = 0; i2 < blockTypes.size(); i2++) { + NifStream( blockTypes[i2], in, version ); + }; + blockTypeIndex.resize(numBlocks); + for (uint i2 = 0; i2 < blockTypeIndex.size(); i2++) { + NifStream( blockTypeIndex[i2], in, version ); + }; + NifStream( unknownInt2, in, version ); + }; +} + +void Header::Write( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const { + NifStream( headerString, out, version ); + NifStream( version, out, version ); + if ( version >= 0x14000004 ) { + NifStream( endianType, out, version ); + }; + if ( version >= 0x0A010000 ) { + NifStream( userVersion, out, version ); + }; + NifStream( numBlocks, out, version ); + if ( ( version >= 0x0A000102 ) && ( version <= 0x0A000102 ) ) { + NifStream( unknownInt1, out, version ); + }; + if ( version >= 0x0A010000 ) { + if ( (userVersion != 0) ) { + NifStream( unknownInt3, out, version ); + }; + }; + if ( version >= 0x0A000102 ) { + if ( (userVersion != 0) ) { + NifStream( creator_.length, out, version ); + for (uint i3 = 0; i3 < creator_.value.size(); i3++) { + NifStream( creator_.value[i3], out, version ); + }; + NifStream( exportType_.length, out, version ); + for (uint i3 = 0; i3 < exportType_.value.size(); i3++) { + NifStream( exportType_.value[i3], out, version ); + }; + NifStream( exportScript_.length, out, version ); + for (uint i3 = 0; i3 < exportScript_.value.size(); i3++) { + NifStream( exportScript_.value[i3], out, version ); + }; + }; + }; + if ( version >= 0x0A000100 ) { + NifStream( numBlockTypes, out, version ); + for (uint i2 = 0; i2 < blockTypes.size(); i2++) { + NifStream( blockTypes[i2], out, version ); + }; + for (uint i2 = 0; i2 < blockTypeIndex.size(); i2++) { + NifStream( blockTypeIndex[i2], out, version ); + }; + NifStream( unknownInt2, out, version ); + }; +} + +string Header::asString( bool verbose ) const { + stringstream out; + out << " Header String: " << headerString << endl; + out << " Version: " << version << endl; + out << " Endian Type: " << endianType << endl; + out << " User Version: " << userVersion << endl; + out << " Num Blocks: " << numBlocks << endl; + out << " Unknown Int 1: " << unknownInt1 << endl; + if ( (userVersion != 0) ) { + out << " Unknown Int 3: " << unknownInt3 << endl; + out << " Length: " << creator_.length << endl; + for (uint i2 = 0; i2 < creator_.value.size(); i2++) { + if ( !verbose && ( i2 > MAXARRAYDUMP ) ) { + out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; + break; + }; + out << " Value[" << i2 << "]: " << creator_.value[i2] << endl; + }; + out << " Length: " << exportType_.length << endl; + for (uint i2 = 0; i2 < exportType_.value.size(); i2++) { + if ( !verbose && ( i2 > MAXARRAYDUMP ) ) { + out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; + break; + }; + out << " Value[" << i2 << "]: " << exportType_.value[i2] << endl; + }; + out << " Length: " << exportScript_.length << endl; + for (uint i2 = 0; i2 < exportScript_.value.size(); i2++) { + if ( !verbose && ( i2 > MAXARRAYDUMP ) ) { + out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; + break; + }; + out << " Value[" << i2 << "]: " << exportScript_.value[i2] << endl; + }; + }; + out << " Num Block Types: " << numBlockTypes << endl; + for (uint i1 = 0; i1 < blockTypes.size(); i1++) { + if ( !verbose && ( i1 > MAXARRAYDUMP ) ) { + out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; + break; + }; + out << " Block Types[" << i1 << "]: " << blockTypes[i1] << endl; + }; + for (uint i1 = 0; i1 < blockTypeIndex.size(); i1++) { + if ( !verbose && ( i1 > MAXARRAYDUMP ) ) { + out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; + break; + }; + out << " Block Type Index[" << i1 << "]: " << blockTypeIndex[i1] << endl; + }; + out << " Unknown Int 2: " << unknownInt2 << endl; + return out.str(); +} diff --git a/gen/Header.h b/gen/Header.h index 2e6d2442f77797177226776237f8226e6ec41ead..35235f5e9869cfe43b12ef9f20e5cedcd9380a0b 100644 --- a/gen/Header.h +++ b/gen/Header.h @@ -7,6 +7,7 @@ All rights reserved. Please see niflib.h for licence. */ #include "NIF_IO.h" // Include structures #include "gen/ShortString.h" +#include "obj/NiObject.h" /*! * The NIF file header. @@ -81,6 +82,9 @@ struct 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; + string asString( bool verbose = false ) const; }; #endif diff --git a/gen/obj_defines.h b/gen/obj_defines.h index 8fb40a0c9998277869834d5e88a566a8449d0dd3..4e327a0e41816cc7cffbf1e3b1715f9fef28d6c5 100644 --- a/gen/obj_defines.h +++ b/gen/obj_defines.h @@ -14056,174 +14056,4 @@ list<Ref<NiObject> > refs; \ refs = NiNode::GetRefs(); \ return refs; \ -#define HEADER_READ \ -NifStream( headerString, in, version ); \ -NifStream( version, in, version ); \ -if ( version >= 0x14000004 ) { \ - NifStream( endianType, in, version ); \ -}; \ -if ( version >= 0x0A010000 ) { \ - NifStream( userVersion, in, version ); \ -}; \ -NifStream( numBlocks, in, version ); \ -if ( ( version >= 0x0A000102 ) && ( version <= 0x0A000102 ) ) { \ - NifStream( unknownInt1, in, version ); \ -}; \ -if ( version >= 0x0A010000 ) { \ - if ( (userVersion != 0) ) { \ - NifStream( unknownInt3, in, version ); \ - }; \ -}; \ -if ( version >= 0x0A000102 ) { \ - if ( (userVersion != 0) ) { \ - NifStream( creator_.length, in, version ); \ - creator_.value.resize(creator_.length); \ - for (uint i2 = 0; i2 < creator_.value.size(); i2++) { \ - NifStream( creator_.value[i2], in, version ); \ - }; \ - NifStream( exportType_.length, in, version ); \ - exportType_.value.resize(exportType_.length); \ - for (uint i2 = 0; i2 < exportType_.value.size(); i2++) { \ - NifStream( exportType_.value[i2], in, version ); \ - }; \ - NifStream( exportScript_.length, in, version ); \ - exportScript_.value.resize(exportScript_.length); \ - for (uint i2 = 0; i2 < exportScript_.value.size(); i2++) { \ - NifStream( exportScript_.value[i2], in, version ); \ - }; \ - }; \ -}; \ -if ( version >= 0x0A000100 ) { \ - NifStream( numBlockTypes, in, version ); \ - blockTypes.resize(numBlockTypes); \ - for (uint i1 = 0; i1 < blockTypes.size(); i1++) { \ - NifStream( blockTypes[i1], in, version ); \ - }; \ - blockTypeIndex.resize(numBlocks); \ - for (uint i1 = 0; i1 < blockTypeIndex.size(); i1++) { \ - NifStream( blockTypeIndex[i1], in, version ); \ - }; \ - NifStream( unknownInt2, in, version ); \ -}; \ - -#define HEADER_WRITE \ -NifStream( headerString, out, version ); \ -NifStream( version, out, version ); \ -if ( version >= 0x14000004 ) { \ - NifStream( endianType, out, version ); \ -}; \ -if ( version >= 0x0A010000 ) { \ - NifStream( userVersion, out, version ); \ -}; \ -NifStream( numBlocks, out, version ); \ -if ( ( version >= 0x0A000102 ) && ( version <= 0x0A000102 ) ) { \ - NifStream( unknownInt1, out, version ); \ -}; \ -if ( version >= 0x0A010000 ) { \ - if ( (userVersion != 0) ) { \ - NifStream( unknownInt3, out, version ); \ - }; \ -}; \ -if ( version >= 0x0A000102 ) { \ - if ( (userVersion != 0) ) { \ - NifStream( creator_.length, out, version ); \ - for (uint i2 = 0; i2 < creator_.value.size(); i2++) { \ - NifStream( creator_.value[i2], out, version ); \ - }; \ - NifStream( exportType_.length, out, version ); \ - for (uint i2 = 0; i2 < exportType_.value.size(); i2++) { \ - NifStream( exportType_.value[i2], out, version ); \ - }; \ - NifStream( exportScript_.length, out, version ); \ - for (uint i2 = 0; i2 < exportScript_.value.size(); i2++) { \ - NifStream( exportScript_.value[i2], out, version ); \ - }; \ - }; \ -}; \ -if ( version >= 0x0A000100 ) { \ - NifStream( numBlockTypes, out, version ); \ - for (uint i1 = 0; i1 < blockTypes.size(); i1++) { \ - NifStream( blockTypes[i1], out, version ); \ - }; \ - for (uint i1 = 0; i1 < blockTypeIndex.size(); i1++) { \ - NifStream( blockTypeIndex[i1], out, version ); \ - }; \ - NifStream( unknownInt2, out, version ); \ -}; \ - -#define HEADER_STRING \ -out << "Header String: " << headerString << endl; \ -out << "Version: " << version << endl; \ -out << "Endian Type: " << endianType << endl; \ -out << "User Version: " << userVersion << endl; \ -out << "Num Blocks: " << numBlocks << endl; \ -out << "Unknown Int 1: " << unknownInt1 << endl; \ -if ( (userVersion != 0) ) { \ - out << " Unknown Int 3: " << unknownInt3 << endl; \ - out << " Length: " << creator_.length << endl; \ - for (uint i1 = 0; i1 < creator_.value.size(); i1++) { \ - if ( !verbose && ( i1 > MAXARRAYDUMP ) ) { \ - out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; \ - break; \ - }; \ - out << " Value[" << i1 << "]: " << creator_.value[i1] << endl; \ - }; \ - out << " Length: " << exportType_.length << endl; \ - for (uint i1 = 0; i1 < exportType_.value.size(); i1++) { \ - if ( !verbose && ( i1 > MAXARRAYDUMP ) ) { \ - out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; \ - break; \ - }; \ - out << " Value[" << i1 << "]: " << exportType_.value[i1] << endl; \ - }; \ - out << " Length: " << exportScript_.length << endl; \ - for (uint i1 = 0; i1 < exportScript_.value.size(); i1++) { \ - if ( !verbose && ( i1 > MAXARRAYDUMP ) ) { \ - out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; \ - break; \ - }; \ - out << " Value[" << i1 << "]: " << exportScript_.value[i1] << endl; \ - }; \ -}; \ -out << "Num Block Types: " << numBlockTypes << endl; \ -for (uint i0 = 0; i0 < blockTypes.size(); i0++) { \ - if ( !verbose && ( i0 > MAXARRAYDUMP ) ) { \ - out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; \ - break; \ - }; \ - out << " Block Types[" << i0 << "]: " << blockTypes[i0] << endl; \ -}; \ -for (uint i0 = 0; i0 < blockTypeIndex.size(); i0++) { \ - if ( !verbose && ( i0 > MAXARRAYDUMP ) ) { \ - out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; \ - break; \ - }; \ - out << " Block Type Index[" << i0 << "]: " << blockTypeIndex[i0] << endl; \ -}; \ -out << "Unknown Int 2: " << unknownInt2 << endl; \ - -#define FOOTER_READ \ -NifStream( numRoots, in, version ); \ -roots.resize(numRoots); \ -for (uint i0 = 0; i0 < roots.size(); i0++) { \ - NifStream( block_num, in, version ); \ - link_stack.push_back( block_num ); \ -}; \ - -#define FOOTER_WRITE \ -NifStream( numRoots, out, version ); \ -for (uint i0 = 0; i0 < roots.size(); i0++) { \ - NifStream( link_map[StaticCast<NiObject>(roots[i0])], out, version ); \ -}; \ - -#define FOOTER_STRING \ -out << "Num Roots: " << numRoots << endl; \ -for (uint i0 = 0; i0 < roots.size(); i0++) { \ - if ( !verbose && ( i0 > MAXARRAYDUMP ) ) { \ - out << "<Data Truncated. Use verbose mode to see complete listing.>" << endl; \ - break; \ - }; \ - out << " Roots[" << i0 << "]: " << roots[i0] << endl; \ -}; \ - #endif