1 #include "niffile.hpp"
2 #include "effect.hpp"
3 
4 #include <array>
5 #include <map>
6 #include <sstream>
7 
8 namespace Nif
9 {
10 
11 /// Open a NIF stream. The name is used for error messages.
NIFFile(Files::IStreamPtr stream,const std::string & name)12 NIFFile::NIFFile(Files::IStreamPtr stream, const std::string &name)
13     : filename(name)
14 {
15     parse(stream);
16 }
17 
~NIFFile()18 NIFFile::~NIFFile()
19 {
20     for (Record* record : records)
21         delete record;
22 }
23 
construct()24 template <typename NodeType> static Record* construct() { return new NodeType; }
25 
26 struct RecordFactoryEntry {
27 
28     using create_t = Record* (*)();
29 
30     create_t        mCreate;
31     RecordType      mType;
32 
33 };
34 
35 ///These are all the record types we know how to read.
makeFactory()36 static std::map<std::string,RecordFactoryEntry> makeFactory()
37 {
38     std::map<std::string,RecordFactoryEntry> factory;
39     factory["NiNode"]                       = {&construct <NiNode>                      , RC_NiNode                     };
40     factory["NiSwitchNode"]                 = {&construct <NiSwitchNode>                , RC_NiSwitchNode               };
41     factory["NiLODNode"]                    = {&construct <NiLODNode>                   , RC_NiLODNode                  };
42     factory["AvoidNode"]                    = {&construct <NiNode>                      , RC_AvoidNode                  };
43     factory["NiCollisionSwitch"]            = {&construct <NiNode>                      , RC_NiCollisionSwitch          };
44     factory["NiBSParticleNode"]             = {&construct <NiNode>                      , RC_NiBSParticleNode           };
45     factory["NiBSAnimationNode"]            = {&construct <NiNode>                      , RC_NiBSAnimationNode          };
46     factory["NiBillboardNode"]              = {&construct <NiNode>                      , RC_NiBillboardNode            };
47     factory["NiTriShape"]                   = {&construct <NiTriShape>                  , RC_NiTriShape                 };
48     factory["NiTriStrips"]                  = {&construct <NiTriStrips>                 , RC_NiTriStrips                };
49     factory["NiLines"]                      = {&construct <NiLines>                     , RC_NiLines                    };
50     factory["NiParticles"]                  = {&construct <NiParticles>                 , RC_NiParticles                };
51     factory["NiRotatingParticles"]          = {&construct <NiParticles>                 , RC_NiParticles                };
52     factory["NiAutoNormalParticles"]        = {&construct <NiParticles>                 , RC_NiParticles                };
53     factory["NiCamera"]                     = {&construct <NiCamera>                    , RC_NiCamera                   };
54     factory["RootCollisionNode"]            = {&construct <NiNode>                      , RC_RootCollisionNode          };
55     factory["NiTexturingProperty"]          = {&construct <NiTexturingProperty>         , RC_NiTexturingProperty        };
56     factory["NiFogProperty"]                = {&construct <NiFogProperty>               , RC_NiFogProperty              };
57     factory["NiMaterialProperty"]           = {&construct <NiMaterialProperty>          , RC_NiMaterialProperty         };
58     factory["NiZBufferProperty"]            = {&construct <NiZBufferProperty>           , RC_NiZBufferProperty          };
59     factory["NiAlphaProperty"]              = {&construct <NiAlphaProperty>             , RC_NiAlphaProperty            };
60     factory["NiVertexColorProperty"]        = {&construct <NiVertexColorProperty>       , RC_NiVertexColorProperty      };
61     factory["NiShadeProperty"]              = {&construct <NiShadeProperty>             , RC_NiShadeProperty            };
62     factory["NiDitherProperty"]             = {&construct <NiDitherProperty>            , RC_NiDitherProperty           };
63     factory["NiWireframeProperty"]          = {&construct <NiWireframeProperty>         , RC_NiWireframeProperty        };
64     factory["NiSpecularProperty"]           = {&construct <NiSpecularProperty>          , RC_NiSpecularProperty         };
65     factory["NiStencilProperty"]            = {&construct <NiStencilProperty>           , RC_NiStencilProperty          };
66     factory["NiVisController"]              = {&construct <NiVisController>             , RC_NiVisController            };
67     factory["NiGeomMorpherController"]      = {&construct <NiGeomMorpherController>     , RC_NiGeomMorpherController    };
68     factory["NiKeyframeController"]         = {&construct <NiKeyframeController>        , RC_NiKeyframeController       };
69     factory["NiAlphaController"]            = {&construct <NiAlphaController>           , RC_NiAlphaController          };
70     factory["NiRollController"]             = {&construct <NiRollController>            , RC_NiRollController           };
71     factory["NiUVController"]               = {&construct <NiUVController>              , RC_NiUVController             };
72     factory["NiPathController"]             = {&construct <NiPathController>            , RC_NiPathController           };
73     factory["NiMaterialColorController"]    = {&construct <NiMaterialColorController>   , RC_NiMaterialColorController  };
74     factory["NiBSPArrayController"]         = {&construct <NiBSPArrayController>        , RC_NiBSPArrayController       };
75     factory["NiParticleSystemController"]   = {&construct <NiParticleSystemController>  , RC_NiParticleSystemController };
76     factory["NiFlipController"]             = {&construct <NiFlipController>            , RC_NiFlipController           };
77     factory["NiAmbientLight"]               = {&construct <NiLight>                     , RC_NiLight                    };
78     factory["NiDirectionalLight"]           = {&construct <NiLight>                     , RC_NiLight                    };
79     factory["NiPointLight"]                 = {&construct <NiPointLight>                , RC_NiLight                    };
80     factory["NiSpotLight"]                  = {&construct <NiSpotLight>                 , RC_NiLight                    };
81     factory["NiTextureEffect"]              = {&construct <NiTextureEffect>             , RC_NiTextureEffect            };
82     factory["NiVertWeightsExtraData"]       = {&construct <NiVertWeightsExtraData>      , RC_NiVertWeightsExtraData     };
83     factory["NiTextKeyExtraData"]           = {&construct <NiTextKeyExtraData>          , RC_NiTextKeyExtraData         };
84     factory["NiStringExtraData"]            = {&construct <NiStringExtraData>           , RC_NiStringExtraData          };
85     factory["NiGravity"]                    = {&construct <NiGravity>                   , RC_NiGravity                  };
86     factory["NiPlanarCollider"]             = {&construct <NiPlanarCollider>            , RC_NiPlanarCollider           };
87     factory["NiSphericalCollider"]          = {&construct <NiSphericalCollider>         , RC_NiSphericalCollider        };
88     factory["NiParticleGrowFade"]           = {&construct <NiParticleGrowFade>          , RC_NiParticleGrowFade         };
89     factory["NiParticleColorModifier"]      = {&construct <NiParticleColorModifier>     , RC_NiParticleColorModifier    };
90     factory["NiParticleRotation"]           = {&construct <NiParticleRotation>          , RC_NiParticleRotation         };
91     factory["NiFloatData"]                  = {&construct <NiFloatData>                 , RC_NiFloatData                };
92     factory["NiTriShapeData"]               = {&construct <NiTriShapeData>              , RC_NiTriShapeData             };
93     factory["NiTriStripsData"]              = {&construct <NiTriStripsData>             , RC_NiTriStripsData            };
94     factory["NiLinesData"]                  = {&construct <NiLinesData>                 , RC_NiLinesData                };
95     factory["NiVisData"]                    = {&construct <NiVisData>                   , RC_NiVisData                  };
96     factory["NiColorData"]                  = {&construct <NiColorData>                 , RC_NiColorData                };
97     factory["NiPixelData"]                  = {&construct <NiPixelData>                 , RC_NiPixelData                };
98     factory["NiMorphData"]                  = {&construct <NiMorphData>                 , RC_NiMorphData                };
99     factory["NiKeyframeData"]               = {&construct <NiKeyframeData>              , RC_NiKeyframeData             };
100     factory["NiSkinData"]                   = {&construct <NiSkinData>                  , RC_NiSkinData                 };
101     factory["NiUVData"]                     = {&construct <NiUVData>                    , RC_NiUVData                   };
102     factory["NiPosData"]                    = {&construct <NiPosData>                   , RC_NiPosData                  };
103     factory["NiParticlesData"]              = {&construct <NiParticlesData>             , RC_NiParticlesData            };
104     factory["NiRotatingParticlesData"]      = {&construct <NiRotatingParticlesData>     , RC_NiParticlesData            };
105     factory["NiAutoNormalParticlesData"]    = {&construct <NiParticlesData>             , RC_NiParticlesData            };
106     factory["NiSequenceStreamHelper"]       = {&construct <NiSequenceStreamHelper>      , RC_NiSequenceStreamHelper     };
107     factory["NiSourceTexture"]              = {&construct <NiSourceTexture>             , RC_NiSourceTexture            };
108     factory["NiSkinInstance"]               = {&construct <NiSkinInstance>              , RC_NiSkinInstance             };
109     factory["NiLookAtController"]           = {&construct <NiLookAtController>          , RC_NiLookAtController         };
110     factory["NiPalette"]                    = {&construct <NiPalette>                   , RC_NiPalette                  };
111     factory["NiIntegerExtraData"]           = {&construct <NiIntegerExtraData>          , RC_NiIntegerExtraData         };
112     factory["NiIntegersExtraData"]          = {&construct <NiIntegersExtraData>         , RC_NiIntegersExtraData        };
113     factory["NiBinaryExtraData"]            = {&construct <NiBinaryExtraData>           , RC_NiBinaryExtraData          };
114     factory["NiBooleanExtraData"]           = {&construct <NiBooleanExtraData>          , RC_NiBooleanExtraData         };
115     factory["NiVectorExtraData"]            = {&construct <NiVectorExtraData>           , RC_NiVectorExtraData          };
116     factory["NiColorExtraData"]             = {&construct <NiVectorExtraData>           , RC_NiColorExtraData           };
117     factory["NiFloatExtraData"]             = {&construct <NiFloatExtraData>            , RC_NiFloatExtraData           };
118     factory["NiFloatsExtraData"]            = {&construct <NiFloatsExtraData>           , RC_NiFloatsExtraData          };
119     factory["NiStringPalette"]              = {&construct <NiStringPalette>             , RC_NiStringPalette            };
120     factory["NiBoolData"]                   = {&construct <NiBoolData>                  , RC_NiBoolData                 };
121     factory["NiSkinPartition"]              = {&construct <NiSkinPartition>             , RC_NiSkinPartition            };
122     factory["BSXFlags"]                     = {&construct <NiIntegerExtraData>          , RC_BSXFlags                   };
123     factory["BSBound"]                      = {&construct <BSBound>                     , RC_BSBound                    };
124     factory["NiTransformData"]              = {&construct <NiKeyframeData>              , RC_NiKeyframeData             };
125     factory["BSFadeNode"]                   = {&construct <NiNode>                      , RC_NiNode                     };
126     factory["bhkBlendController"]           = {&construct <bhkBlendController>          , RC_bhkBlendController         };
127     factory["NiFloatInterpolator"]          = {&construct <NiFloatInterpolator>         , RC_NiFloatInterpolator        };
128     factory["NiBoolInterpolator"]           = {&construct <NiBoolInterpolator>          , RC_NiBoolInterpolator         };
129     factory["NiPoint3Interpolator"]         = {&construct <NiPoint3Interpolator>        , RC_NiPoint3Interpolator       };
130     factory["NiTransformController"]        = {&construct <NiKeyframeController>        , RC_NiKeyframeController       };
131     factory["NiTransformInterpolator"]      = {&construct <NiTransformInterpolator>     , RC_NiTransformInterpolator    };
132     factory["NiColorInterpolator"]          = {&construct <NiColorInterpolator>         , RC_NiColorInterpolator        };
133     factory["BSShaderTextureSet"]           = {&construct <BSShaderTextureSet>          , RC_BSShaderTextureSet         };
134     factory["BSLODTriShape"]                = {&construct <BSLODTriShape>               , RC_BSLODTriShape              };
135     factory["BSShaderProperty"]             = {&construct <BSShaderProperty>            , RC_BSShaderProperty           };
136     factory["BSShaderPPLightingProperty"]   = {&construct <BSShaderPPLightingProperty>  , RC_BSShaderPPLightingProperty };
137     factory["BSShaderNoLightingProperty"]   = {&construct <BSShaderNoLightingProperty>  , RC_BSShaderNoLightingProperty };
138     return factory;
139 }
140 
141 ///Make the factory map used for parsing the file
142 static const std::map<std::string,RecordFactoryEntry> factories = makeFactory();
143 
printVersion(unsigned int version)144 std::string NIFFile::printVersion(unsigned int version)
145 {
146     int major = (version >> 24) & 0xFF;
147     int minor = (version >> 16) & 0xFF;
148     int patch = (version >> 8) & 0xFF;
149     int rev = version & 0xFF;
150 
151     std::stringstream stream;
152     stream << major << "." << minor << "." << patch << "." << rev;
153     return stream.str();
154 }
155 
parse(Files::IStreamPtr stream)156 void NIFFile::parse(Files::IStreamPtr stream)
157 {
158     NIFStream nif (this, stream);
159 
160     // Check the header string
161     std::string head = nif.getVersionString();
162     static const std::array<std::string, 2> verStrings =
163     {
164         "NetImmerse File Format",
165         "Gamebryo File Format"
166     };
167     bool supported = false;
168     for (const std::string& verString : verStrings)
169     {
170         supported = (head.compare(0, verString.size(), verString) == 0);
171         if (supported)
172             break;
173     }
174     if (!supported)
175         fail("Invalid NIF header: " + head);
176 
177     supported = false;
178 
179     // Get BCD version
180     ver = nif.getUInt();
181     // 4.0.0.0 is an older, practically identical version of the format.
182     // It's not used by Morrowind assets but Morrowind supports it.
183     static const std::array<uint32_t, 2> supportedVers =
184     {
185         NIFStream::generateVersion(4,0,0,0),
186         VER_MW
187     };
188     for (uint32_t supportedVer : supportedVers)
189     {
190         supported = (ver == supportedVer);
191         if (supported)
192             break;
193     }
194     if (!supported)
195     {
196         if (sLoadUnsupportedFiles)
197             warn("Unsupported NIF version: " + printVersion(ver) + ". Proceed with caution!");
198         else
199             fail("Unsupported NIF version: " + printVersion(ver));
200     }
201 
202     // NIF data endianness
203     if (ver >= NIFStream::generateVersion(20,0,0,4))
204     {
205         unsigned char endianness = nif.getChar();
206         if (endianness == 0)
207             fail("Big endian NIF files are unsupported");
208     }
209 
210     // User version
211     if (ver > NIFStream::generateVersion(10,0,1,8))
212         userVer = nif.getUInt();
213 
214     // Number of records
215     const std::size_t recNum = nif.getUInt();
216     records.resize(recNum);
217 
218     // Bethesda stream header
219     // It contains Bethesda format version and (useless) export information
220     if (ver == VER_OB_OLD ||
221        (userVer >= 3 && ((ver == VER_OB || ver == VER_BGS)
222     || (ver >= NIFStream::generateVersion(10,1,0,0) && ver <= NIFStream::generateVersion(20,0,0,4) && userVer <= 11))))
223     {
224         bethVer = nif.getUInt();
225         nif.getExportString(); // Author
226         if (bethVer > BETHVER_FO4)
227             nif.getUInt(); // Unknown
228         nif.getExportString(); // Process script
229         nif.getExportString(); // Export script
230         if (bethVer == BETHVER_FO4)
231             nif.getExportString(); // Max file path
232     }
233 
234     std::vector<std::string> recTypes;
235     std::vector<unsigned short> recTypeIndices;
236 
237     const bool hasRecTypeListings = ver >= NIFStream::generateVersion(5,0,0,1);
238     if (hasRecTypeListings)
239     {
240         unsigned short recTypeNum = nif.getUShort();
241         if (recTypeNum) // Record type list
242             nif.getSizedStrings(recTypes, recTypeNum);
243         if (recNum) // Record type mapping for each record
244             nif.getUShorts(recTypeIndices, recNum);
245         if (ver >= NIFStream::generateVersion(5,0,0,6)) // Groups
246         {
247             if (ver >= NIFStream::generateVersion(20,1,0,1)) // String table
248             {
249                 if (ver >= NIFStream::generateVersion(20,2,0,5) && recNum) // Record sizes
250                 {
251                     std::vector<unsigned int> recSizes; // Currently unused
252                     nif.getUInts(recSizes, recNum);
253                 }
254                 const std::size_t stringNum = nif.getUInt();
255                 nif.getUInt(); // Max string length
256                 if (stringNum)
257                     nif.getSizedStrings(strings, stringNum);
258             }
259             std::vector<unsigned int> groups; // Currently unused
260             unsigned int groupNum = nif.getUInt();
261             if (groupNum)
262                 nif.getUInts(groups, groupNum);
263         }
264     }
265 
266     const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0);
267     for (std::size_t i = 0; i < recNum; i++)
268     {
269         Record *r = nullptr;
270 
271         std::string rec = hasRecTypeListings ? recTypes[recTypeIndices[i]] : nif.getString();
272         if(rec.empty())
273         {
274             std::stringstream error;
275             error << "Record number " << i << " out of " << recNum << " is blank.";
276             fail(error.str());
277         }
278 
279         // Record separator. Some Havok records in Oblivion do not have it.
280         if (hasRecordSeparators && rec.compare(0, 3, "bhk"))
281         {
282             if (nif.getInt())
283             {
284                 std::stringstream warning;
285                 warning << "Record number " << i << " out of " << recNum << " is preceded by a non-zero separator.";
286                 warn(warning.str());
287             }
288         }
289 
290         std::map<std::string,RecordFactoryEntry>::const_iterator entry = factories.find(rec);
291 
292         if (entry != factories.end())
293         {
294             r = entry->second.mCreate ();
295             r->recType = entry->second.mType;
296         }
297         else
298             fail("Unknown record type " + rec);
299 
300         if (!supported)
301             Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" << filename << ")";
302 
303         assert(r != nullptr);
304         assert(r->recType != RC_MISSING);
305         r->recName = rec;
306         r->recIndex = i;
307         records[i] = r;
308         r->read(&nif);
309     }
310 
311     const std::size_t rootNum = nif.getUInt();
312     roots.resize(rootNum);
313 
314     //Determine which records are roots
315     for (std::size_t i = 0; i < rootNum; i++)
316     {
317         int idx = nif.getInt();
318         if (idx >= 0 && static_cast<std::size_t>(idx) < records.size())
319         {
320             roots[i] = records[idx];
321         }
322         else
323         {
324             roots[i] = nullptr;
325             warn("Root " + std::to_string(i + 1) + " does not point to a record: index " + std::to_string(idx));
326         }
327     }
328 
329     // Once parsing is done, do post-processing.
330     for (Record* record : records)
331         record->post(this);
332 }
333 
setUseSkinning(bool skinning)334 void NIFFile::setUseSkinning(bool skinning)
335 {
336     mUseSkinning = skinning;
337 }
338 
getUseSkinning() const339 bool NIFFile::getUseSkinning() const
340 {
341     return mUseSkinning;
342 }
343 
344 bool NIFFile::sLoadUnsupportedFiles = false;
345 
setLoadUnsupportedFiles(bool load)346 void NIFFile::setLoadUnsupportedFiles(bool load)
347 {
348     sLoadUnsupportedFiles = load;
349 }
350 
351 }
352