From df4989715e137ad07445418042941b227bd11c54 Mon Sep 17 00:00:00 2001 From: Shon Ferguson <shonferg@users.sourceforge.net> Date: Fri, 22 Sep 2006 07:45:21 +0000 Subject: [PATCH] Several fixes to XML and Niflib to enable all my files from Freedom Force (except with NiClodData), Oblivion, CivIV, Morrowind, Zoo Tycoon 2, and DAoC to load in Niflib and NifSkope. Includes the two strange Oblivion files with version 3.3.0.13 and version 10.0.1.2. --- include/gen/Header.h | 4 -- include/gen/obj_defines.h | 4 +- include/nif_versions.h | 4 +- src/NIF_IO.cpp | 138 +++++++++++++++++++------------------- src/gen/Header.cpp | 15 ++--- src/gen/obj_impl.cpp | 4 +- src/niflib.cpp | 27 ++++---- 7 files changed, 98 insertions(+), 98 deletions(-) diff --git a/include/gen/Header.h b/include/gen/Header.h index 1aceda4b..378bebb7 100644 --- a/include/gen/Header.h +++ b/include/gen/Header.h @@ -44,10 +44,6 @@ struct NIFLIB_API Header { * Number of file objects. */ mutable uint numBlocks; - /*! - * Unknown. - */ - uint unknownInt1; /*! * This also appears to be the extra user version number and must be set * in some circumstances. diff --git a/include/gen/obj_defines.h b/include/gen/obj_defines.h index 5bdd4a43..ba1efdfe 100644 --- a/include/gen/obj_defines.h +++ b/include/gen/obj_defines.h @@ -3071,10 +3071,10 @@ vector< array<4,float> > unknownFloats3; \ vector< array<10,float> > unknownFloats4; \ vector< array<12,float> > unknownFloats5; \ uint unknownInt1; \ -Ref<NiPSysModifier > modifier; \ +Ref<NiObject > modifier; \ byte unknownByte2; \ mutable uint numUnknownLinks; \ -vector<Ref<NiPSysModifier > > unknownLinks; \ +vector<Ref<NiObject > > unknownLinks; \ ushort unknownShort4; \ uint unknownInt2; \ byte unknownByte12; \ diff --git a/include/nif_versions.h b/include/nif_versions.h index 6d77e155..30833a6f 100644 --- a/include/nif_versions.h +++ b/include/nif_versions.h @@ -5,7 +5,9 @@ All rights reserved. Please see niflib.h for licence. */ #define _NIF_VERSIONS_H_ //NIF Version Constants -const unsigned VER_4_0_0_0 = 0X04000000; /*!< NIF Version 4.0.0.0 */ + +const unsigned VER_3_3_0_13 = 0x0303000D; /*!< NIF Version 3.3.0.13 */ +const unsigned VER_4_0_0_0 = 0x04000000; /*!< NIF Version 4.0.0.0 */ const unsigned VER_4_0_0_2 = 0x04000002; /*!< NIF Version 4.0.0.2 */ const unsigned VER_4_1_0_12 = 0x0401000C; /*!< NIF Version 4.1.0.12 */ const unsigned VER_4_2_0_2 = 0x04020002; /*!< NIF Version 4.2.0.2 */ diff --git a/src/NIF_IO.cpp b/src/NIF_IO.cpp index 53222bad..90b0dc5d 100644 --- a/src/NIF_IO.cpp +++ b/src/NIF_IO.cpp @@ -5,74 +5,74 @@ All rights reserved. Please see niflib.h for licence. */ #include "../include/niflib.h" namespace Niflib { -int BlockSearch( istream& in ) { - - //Get current file pos - int data_start = in.tellg(); - - //cout << "Current File Pos: " << data_start << endl; - //cout << "Searching for next block..." << endl; - - //Find Next Block - char tmp1 = 0, tmp2 = 0; - uint next_name_len = 0; - while (!in.eof()) { - while (!in.eof() && !((tmp1 == 'N' && tmp2 == 'i') || (tmp1 == 'R' && tmp2 == 'o') || (tmp1 == 'A' && tmp2 == 'v')) ) { - tmp1 = tmp2; - in.read(&tmp2, 1); - } - if (in.eof()) - break; - - //Move back to before the uint that holds the length of the string - in.seekg(-6, ios_base::cur); - - //Read the length of the string - next_name_len = ReadUInt( in ); - - //cout << "Matching Data: " << tmp1 << tmp2 << endl; - - //if name length is > 40, then this is unlikley to be a real node. - if (next_name_len <= 40 && next_name_len >= 5) { - //Read the string - char* next_name = new char[next_name_len]; - in.read( next_name, next_name_len ); - - //cout << "Found Match: " << Str(next_name, next_name_len) << endl; - - //Move back to where we were before we read anything - in.seekg( -(int(next_name_len) - 2), ios_base::cur); - - break; - } - else { - //Move back to where we were before we read anything - in.seekg(2, ios_base::cur); - - tmp1 = tmp2 = 0; - //cout << "Found possible block at: " << int(in.tellg()) - 6 << endl; - } - } - - //Note length of data - int data_length = 0; - if (in.eof()) { - //cout << "Reached End of File. Assuming no more blocks to find." << endl; - in.clear(); - in.seekg(-8, ios_base::end); - data_length = int(in.tellg()) - data_start; - in.seekg(data_start, ios_base::beg); - } - else { - in.seekg(-6, ios_base::cur); - data_length = int(in.tellg()) - data_start; - in.seekg(data_start, ios_base::beg); - } - - //cout << "Unknown area (" << data_length << " bytes):" << endl; - - return data_length; -} +//int BlockSearch( istream& in ) { +// +// //Get current file pos +// int data_start = in.tellg(); +// +// //cout << "Current File Pos: " << data_start << endl; +// //cout << "Searching for next block..." << endl; +// +// //Find Next Block +// char tmp1 = 0, tmp2 = 0; +// uint next_name_len = 0; +// while (!in.eof()) { +// while (!in.eof() && !((tmp1 == 'N' && tmp2 == 'i') || (tmp1 == 'R' && tmp2 == 'o') || (tmp1 == 'A' && tmp2 == 'v')) ) { +// tmp1 = tmp2; +// in.read(&tmp2, 1); +// } +// if (in.eof()) +// break; +// +// //Move back to before the uint that holds the length of the string +// in.seekg(-6, ios_base::cur); +// +// //Read the length of the string +// next_name_len = ReadUInt( in ); +// +// //cout << "Matching Data: " << tmp1 << tmp2 << endl; +// +// //if name length is > 40, then this is unlikley to be a real node. +// if (next_name_len <= 40 && next_name_len >= 5) { +// //Read the string +// char* next_name = new char[next_name_len]; +// in.read( next_name, next_name_len ); +// +// //cout << "Found Match: " << Str(next_name, next_name_len) << endl; +// +// //Move back to where we were before we read anything +// in.seekg( -(int(next_name_len) - 2), ios_base::cur); +// +// break; +// } +// else { +// //Move back to where we were before we read anything +// in.seekg(2, ios_base::cur); +// +// tmp1 = tmp2 = 0; +// //cout << "Found possible block at: " << int(in.tellg()) - 6 << endl; +// } +// } +// +// //Note length of data +// int data_length = 0; +// if (in.eof()) { +// //cout << "Reached End of File. Assuming no more blocks to find." << endl; +// in.clear(); +// in.seekg(-8, ios_base::end); +// data_length = int(in.tellg()) - data_start; +// in.seekg(data_start, ios_base::beg); +// } +// else { +// in.seekg(-6, ios_base::cur); +// data_length = int(in.tellg()) - data_start; +// in.seekg(data_start, ios_base::beg); +// } +// +// //cout << "Unknown area (" << data_length << " bytes):" << endl; +// +// return data_length; +//} /** * Read utility functions @@ -254,7 +254,7 @@ void NifStream( HeaderString & val, istream& in, uint & version ) { version = ParseVersionString( val.header.substr( ver_start ) ); //Temporarily read the next 3 strings if this is a < 4 file - if ( version < VER_4_0_0_0 ) { + if ( version < VER_3_3_0_13 ) { in.getline( tmp, 256 ); in.getline( tmp, 256 ); in.getline( tmp, 256 ); diff --git a/src/gen/Header.cpp b/src/gen/Header.cpp index 6a192a85..db066cab 100644 --- a/src/gen/Header.cpp +++ b/src/gen/Header.cpp @@ -5,13 +5,13 @@ All rights reserved. Please see niflib.h for licence. */ using namespace Niflib; //Constructor -Header::Header() : version((uint)0x04000002), endianType((byte)1), userVersion((uint)0), numBlocks((uint)0), unknownInt1((uint)1), userVersion2((uint)0), numBlockTypes((ushort)0), unknownInt2((uint)0) {}; +Header::Header() : version((uint)0x04000002), endianType((byte)1), userVersion((uint)0), numBlocks((uint)0), userVersion2((uint)0), numBlockTypes((ushort)0), unknownInt2((uint)0) {}; //Destructor Header::~Header() {}; void Header::Read( istream& in ) { NifStream( headerString, in, version ); - if ( version >= 0x04000000 ) { + if ( version >= 0x0303000D ) { NifStream( version, in, version ); }; if ( version >= 0x14000004 ) { @@ -20,11 +20,11 @@ void Header::Read( istream& in ) { if ( version >= 0x0A010000 ) { NifStream( userVersion, in, version ); }; - if ( version >= 0x04000000 ) { + if ( version >= 0x0303000D ) { NifStream( numBlocks, in, version ); }; if ( ( version >= 0x0A000102 ) && ( version <= 0x0A000102 ) ) { - NifStream( unknownInt1, in, version ); + NifStream( userVersion, in, version ); }; if ( version >= 0x0A010000 ) { if ( (userVersion != 0) ) { @@ -56,7 +56,7 @@ void Header::Write( ostream& out ) const { numBlockTypes = ushort(blockTypes.size()); numBlocks = uint(blockTypeIndex.size()); NifStream( headerString, out, version ); - if ( version >= 0x04000000 ) { + if ( version >= 0x0303000D ) { NifStream( version, out, version ); }; if ( version >= 0x14000004 ) { @@ -65,11 +65,11 @@ void Header::Write( ostream& out ) const { if ( version >= 0x0A010000 ) { NifStream( userVersion, out, version ); }; - if ( version >= 0x04000000 ) { + if ( version >= 0x0303000D ) { NifStream( numBlocks, out, version ); }; if ( ( version >= 0x0A000102 ) && ( version <= 0x0A000102 ) ) { - NifStream( unknownInt1, out, version ); + NifStream( userVersion, out, version ); }; if ( version >= 0x0A010000 ) { if ( (userVersion != 0) ) { @@ -104,7 +104,6 @@ string Header::asString( bool verbose ) const { 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 << " User Version 2: " << userVersion2 << endl; out << " Creator: " << creator << endl; diff --git a/src/gen/obj_impl.cpp b/src/gen/obj_impl.cpp index 64610f96..c1cead69 100644 --- a/src/gen/obj_impl.cpp +++ b/src/gen/obj_impl.cpp @@ -6385,11 +6385,11 @@ std::string NiMeshPSysData::InternalAsString( bool verbose ) const { void NiMeshPSysData::InternalFixLinks( const map<unsigned,NiObjectRef> & objects, list<uint> & link_stack, unsigned int version, unsigned int user_version ) { APSysData::FixLinks( objects, link_stack, version, user_version ); if ( version <= 0x14000004 ) { - modifier = FixLink<NiPSysModifier>( objects, link_stack, version ); + modifier = FixLink<NiObject>( objects, link_stack, version ); }; if ( ( version >= 0x0A020000 ) && ( version <= 0x14000004 ) ) { for (uint i2 = 0; i2 < unknownLinks.size(); i2++) { - unknownLinks[i2] = FixLink<NiPSysModifier>( objects, link_stack, version ); + unknownLinks[i2] = FixLink<NiObject>( objects, link_stack, version ); }; }; if ( version >= 0x0A020000 ) { diff --git a/src/niflib.cpp b/src/niflib.cpp index 389f2668..ef9d8bc3 100644 --- a/src/niflib.cpp +++ b/src/niflib.cpp @@ -133,6 +133,8 @@ vector<NiObjectRef> ReadNifList( string const & file_name, NifInfo * info ) { ifstream in( file_name.c_str(), ifstream::binary ); return ReadNifList( in ); + + in.close(); } //Reads the given input stream and returns a vector of block references @@ -195,9 +197,9 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) { //There are two main ways to read objects //One before version 5.0.0.1 and one after 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 object + //From version 5.0.0.1 to version 10.0.1.106 there is a zero byte at the begining of each object - if ( header.version <= VER_10_1_0_0 ) { + if ( header.version <= VER_10_1_0_106 ) { uint checkValue = ReadUInt( in ); if ( checkValue != 0 ) { //Throw an exception if it's not zero @@ -215,6 +217,10 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) { // Find which block type this is by using the header arrays objectType = header.blockTypes[ header.blockTypeIndex[i] ]; + +#ifdef PRINT_OBJECT_NAMES + cout << endl << i << ": " << objectType; +#endif } else { // Find which object type this is by reading the string at this location uint objectTypeLength = ReadUInt( in ); @@ -239,7 +245,7 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) { cout << endl << i << ": " << objectType; #endif - if ( header.version < VER_4_0_0_0 ) { + if ( header.version < VER_3_3_0_13 ) { //There can be special commands instead of object names //in these versions @@ -284,7 +290,7 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) { } uint index; - if ( header.version < VER_4_0_0_0 ) { + if ( header.version < VER_3_3_0_13 ) { //These old versions have a pointer value after the name //which is used as the index index = ReadUInt(in); @@ -301,7 +307,7 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) { cout << endl << new_obj->asString() << endl; #endif - if ( header.version >= VER_4_0_0_0 ) { + if ( header.version >= VER_3_3_0_13 ) { //We know the number of objects, so increment the count //and break if we've finished ++i; @@ -340,10 +346,6 @@ vector<NiObjectRef> ReadNifList( istream & in, NifInfo * info ) { cout << "Fixing Links:" << endl; #endif //--Now that all blocks are read, go back and fix the links--// - if ( header.version < VER_4_0_0_0 ) { - //First wen - } - vector<NiObjectRef> obj_list; for ( map<unsigned,NiObjectRef>::iterator it = objects.begin(); it != objects.end(); ++it ) { @@ -1069,6 +1071,7 @@ void MergeNifTrees( const Ref<NiNode> & target, const Ref<NiSequenceStreamHelper bool IsSupportedVersion( unsigned int version ) { switch (version) { + case VER_3_3_0_13: case VER_4_0_0_0: case VER_4_0_0_2: case VER_4_1_0_12: @@ -1130,11 +1133,11 @@ string FormatVersionString(unsigned version) { //Format the version string and return it stringstream out; - if ( int_ver[0] >= 4 ) { - //Version 4+ is in x.x.x.x format. + if ( version >= VER_3_3_0_13 ) { + //Version 3.3.0.13+ is in x.x.x.x format. out << int_ver[0] << "." << int_ver[1] << "." << int_ver[2] << "." << int_ver[3]; } else { - //Versions before 4 are in x.x format. + //Versions before 3.3.0.13 are in x.x format. out << int_ver[0] << "." << int_ver[1]; } -- GitLab