xoreos  0.0.5
gff3file.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* See BioWare's own specs released for Neverwinter Nights modding
26  * (<https://github.com/xoreos/xoreos-docs/tree/master/specs/bioware>)
27  */
28 
29 #include <cassert>
30 
31 #include "src/common/error.h"
33 #include "src/common/encoding.h"
34 #include "src/common/ustring.h"
35 #include "src/common/strutil.h"
36 
37 #include "src/aurora/gff3file.h"
38 #include "src/aurora/util.h"
39 #include "src/aurora/locstring.h"
40 #include "src/aurora/resman.h"
41 
42 static const uint32 kVersion32 = MKTAG('V', '3', '.', '2');
43 static const uint32 kVersion33 = MKTAG('V', '3', '.', '3'); // Found in The Witcher, different language table
44 
45 namespace Aurora {
46 
48 }
49 
51  structOffset = gff3.readUint32LE();
52  structCount = gff3.readUint32LE();
53  fieldOffset = gff3.readUint32LE();
54  fieldCount = gff3.readUint32LE();
55  labelOffset = gff3.readUint32LE();
56  labelCount = gff3.readUint32LE();
57  fieldDataOffset = gff3.readUint32LE();
58  fieldDataCount = gff3.readUint32LE();
59  fieldIndicesOffset = gff3.readUint32LE();
60  fieldIndicesCount = gff3.readUint32LE();
61  listIndicesOffset = gff3.readUint32LE();
62  listIndicesCount = gff3.readUint32LE();
63 }
64 
65 
66 GFF3File::GFF3File(Common::SeekableReadStream *gff3, uint32 id, bool repairNWNPremium) :
67  _stream(gff3), _repairNWNPremium(repairNWNPremium), _offsetCorrection(0) {
68 
69  assert(_stream);
70 
71  load(id);
72 }
73 
74 GFF3File::GFF3File(const Common::UString &gff3, FileType type, uint32 id, bool repairNWNPremium) :
75  _repairNWNPremium(repairNWNPremium), _offsetCorrection(0) {
76 
77  _stream.reset(ResMan.getResource(gff3, type));
78  if (!_stream)
79  throw Common::Exception("No such GFF3 \"%s\"", TypeMan.setFileType(gff3, type).c_str());
80 
81  load(id);
82 }
83 
85 }
86 
88  return _id;
89 }
90 
92  return getStruct(0);
93 }
94 
95 // --- Loader ---
96 
98  try {
99 
100  loadHeader(id);
101  loadStructs();
102  loadLists();
103 
104  } catch (Common::Exception &e) {
105  e.add("Failed reading GFF3 file");
106  throw;
107  }
108 }
109 
111  if (_repairNWNPremium) {
112  /* The GFF3 files in the encrypted premium module archive for Neverwinter
113  * nights are deliberately broken: the file type and version have been
114  * removed, and the offsets to the individual sections are increased
115  * by a certain amount.
116  *
117  * This offset difference is calculated from the MD5 checksum of the
118  * NWM file of the premium module. But since the first offset is a
119  * known value, we can calculate the difference from there and don't
120  * need to know the MD5 of the NWM file.
121  */
122 
123  uint32 firstOffset = _stream->readUint32LE();
124  uint32 maybeVersion = _stream->readUint32BE();
125 
126  if ((maybeVersion != kVersion32) && (maybeVersion != kVersion33)) {
127  if ((firstOffset >= 0x30) && (firstOffset <= 0x12F)) {
128  // Yes, this looks like a messed-with GFF3 found in an NWN premium module
130  id = _id = 0xFFFFFFFF;
131 
132  _offsetCorrection = firstOffset - 0x30;
133 
134  } else
135  // File is broken in a different way. The later checks will throw
136  _repairNWNPremium = false;
137 
138  } else
139  // This is not a GFF3 file that needs repairing
140  _repairNWNPremium = false;
141 
142  _stream->seek(0);
143  }
144 
145  if (!_repairNWNPremium)
147 
148  if ((id != 0xFFFFFFFF) && (_id != id))
149  throw Common::Exception("GFF3 has invalid ID (want %s, got %s)",
150  Common::debugTag(id).c_str(), Common::debugTag(_id).c_str());
151 
152  if ((_version != kVersion32) && (_version != kVersion33))
153  throw Common::Exception("Unsupported GFF3 file version %s", Common::debugTag(_version).c_str());
154 
155  _header.read(*_stream);
156 
157  // Fix offsets in the header, and check for consistency
158 
165  throw Common::Exception("GFF3 header broken: section offset smaller than offset correction");
166 
173 
174  if ((_header.structOffset > _stream->size()) ||
175  (_header.fieldOffset > _stream->size()) ||
176  (_header.labelOffset > _stream->size()) ||
177  (_header.fieldDataOffset > _stream->size()) ||
178  (_header.fieldIndicesOffset > _stream->size()) ||
179  (_header.listIndicesOffset > _stream->size()))
180  throw Common::Exception("GFF3 header broken: section offset points outside stream");
181 }
182 
184  static const uint32 kStructSize = 12;
185 
186  _structs.reserve(_header.structCount);
187  for (uint32 i = 0; i < _header.structCount; i++)
188  _structs.push_back(new GFF3Struct(*this, _header.structOffset + i * kStructSize));
189 }
190 
192  /* Read in the lists section of the GFF3.
193  *
194  * GFF3s store lists in a linear fashion, with the indices prefixes by
195  * the number of indices to follow. For example, with the indices counts
196  * highlighted for better readability:
197  * [3] 0 1 2 [5] 3 4 5 6 7 [1] 8 [2] 9 10
198  * This specifies 4 lists, with 3, 5, 1 and 2 entries, respectively.
199  * The first list contains struct indices 0 to 2, the second 3 to 7, the
200  * third 8 and the fourth 9 and 10.
201  *
202  * For easy handling, we convert this list into an array of struct
203  * pointer arrays, and a small array to convert from an index into this
204  * list of lists into a list index.
205  */
206 
208 
209  // Read list array
210  std::vector<uint32> rawLists;
211  rawLists.resize(_header.listIndicesCount / 4);
212  for (std::vector<uint32>::iterator it = rawLists.begin(); it != rawLists.end(); ++it)
213  *it = _stream->readUint32LE();
214 
215  // Counting the actual amount of lists
216  uint32 listCount = 0;
217  for (size_t i = 0; i < rawLists.size(); i++) {
218  uint32 n = rawLists[i];
219 
220  if ((i + n) > rawLists.size())
221  throw Common::Exception("GFF3: List indices broken during counting");
222 
223  i += n;
224  listCount++;
225  }
226 
227  _lists.resize(listCount);
228  _listOffsetToIndex.resize(rawLists.size(), 0xFFFFFFFF);
229 
230  // Converting the raw list array into real, usable lists
231  uint32 listIndex = 0;
232  for (size_t i = 0; i < rawLists.size(); listIndex++) {
233  _listOffsetToIndex[i] = listIndex;
234 
235  const uint32 n = rawLists[i++];
236  if ((i + n) > rawLists.size())
237  throw Common::Exception("GFF3: List indices broken during conversion");
238 
239  _lists[listIndex].resize(n);
240  for (uint32 j = 0; j < n; j++, i++) {
241  const size_t structIndex = rawLists[i];
242  if (structIndex >= _structs.size())
243  throw Common::Exception("GFF3: List struct index out of range (%u >= %u)",
244  (uint) structIndex, (uint) _structs.size());
245 
246  _lists[listIndex][j] = _structs[structIndex];
247  }
248  }
249 }
250 
251 // --- Helpers for GFF3Struct ---
252 
254  if (i >= _structs.size())
255  throw Common::Exception("GFF3: Struct index out of range (%u >= %u)", i, (uint) _structs.size());
256 
257  return *_structs[i];
258 }
259 
261  if (i >= _listOffsetToIndex.size())
262  throw Common::Exception("GFF3: List offset index out of range (%u >= %u)",
263  i, (uint) _listOffsetToIndex.size());
264 
265  const uint32 listIndex = _listOffsetToIndex[i];
266 
267  if (listIndex == 0xFFFFFFFF)
268  throw Common::Exception("GFF3: Empty list index at %u", i);
269 
270  assert(listIndex < _lists.size());
271 
272  return _lists[listIndex];
273 }
274 
276  _stream->seek(offset);
277 
278  return *_stream;
279 }
280 
283 }
284 
285 
286 GFF3Struct::Field::Field() : type(kFieldTypeNone), data(0), extended(false) {
287 }
288 
289 GFF3Struct::Field::Field(FieldType t, uint32 d) : type(t), data(d) {
290  // These field types need extended field data
291  extended = (type == kFieldTypeUint64 ) ||
292  (type == kFieldTypeSint64 ) ||
293  (type == kFieldTypeDouble ) ||
294  (type == kFieldTypeExoString ) ||
295  (type == kFieldTypeResRef ) ||
296  (type == kFieldTypeLocString ) ||
297  (type == kFieldTypeVoid ) ||
299  (type == kFieldTypeVector ) ||
300  (type == kFieldTypeStrRef );
301 }
302 
303 
304 GFF3Struct::GFF3Struct(const GFF3File &parent, uint32 offset) : _parent(&parent) {
305  load(offset);
306 }
307 
309 }
310 
312  return _id;
313 }
314 
315 // --- Loader ---
316 
317 void GFF3Struct::load(uint32 offset) {
319 
320  _id = data.readUint32LE();
321  _fieldIndex = data.readUint32LE();
322  _fieldCount = data.readUint32LE();
323 
324  // Read the field(s)
325  if (_fieldCount == 1)
326  readField (data, _fieldIndex);
327  else if (_fieldCount > 1)
329 }
330 
332  // Sanity check
333  if (index > _parent->_header.fieldCount)
334  throw Common::Exception("GFF3: Field index out of range (%d/%d)",
335  index, _parent->_header.fieldCount);
336 
337  // Seek
338  data.seek(_parent->_header.fieldOffset + index * 12);
339 
340  // Read the field data
341  const uint32 fieldType = data.readUint32LE();
342  const uint32 fieldLabel = data.readUint32LE();
343  const uint32 fieldData = data.readUint32LE();
344 
345  // Read the name
346  Common::UString fieldName = readLabel(data, fieldLabel);
347 
348  // And add the field to the map and name list
349  _fields[fieldName] = Field((FieldType) fieldType, fieldData);
350 
351  _fieldNames.push_back(fieldName);
352 }
353 
355  // Sanity check
356  if (index > _parent->_header.fieldIndicesCount)
357  throw Common::Exception("GFF3: Field indices index out of range (%d/%d)",
359 
360  // Seek
361  data.seek(_parent->_header.fieldIndicesOffset + index);
362 
363  // Read the field indices
364  std::vector<uint32> indices;
365  readIndices(data, indices, count);
366 
367  // Read the fields
368  for (std::vector<uint32>::const_iterator i = indices.begin(); i != indices.end(); ++i)
369  readField(data, *i);
370 }
371 
373  std::vector<uint32> &indices, uint32 count) const {
374  indices.reserve(count);
375  while (count-- > 0)
376  indices.push_back(data.readUint32LE());
377 }
378 
380  data.seek(_parent->_header.labelOffset + index * 16);
381 
383 }
384 
386  assert(field.extended);
387 
389  data.skip(field.data);
390 
391  return data;
392 }
393 
394 // --- Field properties ---
395 
397  return _fields.size();
398 }
399 
400 bool GFF3Struct::hasField(const Common::UString &field) const {
401  return getField(field) != 0;
402 }
403 
404 const std::vector<Common::UString> &GFF3Struct::getFieldNames() const {
405  return _fieldNames;
406 }
407 
409  const Field *f = getField(field);
410  if (!f)
411  return kFieldTypeNone;
412 
413  return f->type;
414 }
415 
416 // --- Field value reader helpers ---
417 
419  FieldMap::const_iterator field = _fields.find(name);
420  if (field == _fields.end())
421  return 0;
422 
423  return &field->second;
424 }
425 
426 char GFF3Struct::getChar(const Common::UString &field, char def) const {
427  const Field *f = getField(field);
428  if (!f)
429  return def;
430  if (f->type != kFieldTypeChar)
431  throw Common::Exception("GFF3: Field is not a char type");
432 
433  return (char) f->data;
434 }
435 
437  const Field *f = getField(field);
438  if (!f)
439  return def;
440 
441  // Int types
442  if (f->type == kFieldTypeByte)
443  return (uint64) ((uint8 ) f->data);
444  if (f->type == kFieldTypeUint16)
445  return (uint64) ((uint16) f->data);
446  if (f->type == kFieldTypeUint32)
447  return (uint64) ((uint32) f->data);
448  if (f->type == kFieldTypeChar)
449  return (uint64) ((int64) ((int8 ) ((uint8 ) f->data)));
450  if (f->type == kFieldTypeSint16)
451  return (uint64) ((int64) ((int16) ((uint16) f->data)));
452  if (f->type == kFieldTypeSint32)
453  return (uint64) ((int64) ((int32) ((uint32) f->data)));
454  if (f->type == kFieldTypeUint64)
455  return (uint64) getData(*f).readUint64LE();
456  if (f->type == kFieldTypeSint64)
457  return ( int64) getData(*f).readUint64LE();
458 
459  // StrRef, a numerical reference to a string in a talk table
460  if (f->type == kFieldTypeStrRef) {
462 
463  const uint32 size = data.readUint32LE();
464  if (size != 4)
465  Common::Exception("StrRef field with invalid size (%d)", size);
466 
467  return (uint64) data.readUint32LE();
468  }
469 
470  throw Common::Exception("GFF3: Field is not an int type");
471 }
472 
473 int64 GFF3Struct::getSint(const Common::UString &field, int64 def) const {
474  const Field *f = getField(field);
475  if (!f)
476  return def;
477 
478  // Int types
479  if (f->type == kFieldTypeByte)
480  return (int64) ((int8 ) ((uint8 ) f->data));
481  if (f->type == kFieldTypeUint16)
482  return (int64) ((int16) ((uint16) f->data));
483  if (f->type == kFieldTypeUint32)
484  return (int64) ((int32) ((uint32) f->data));
485  if (f->type == kFieldTypeChar)
486  return (int64) ((int8 ) ((uint8 ) f->data));
487  if (f->type == kFieldTypeSint16)
488  return (int64) ((int16) ((uint16) f->data));
489  if (f->type == kFieldTypeSint32)
490  return (int64) ((int32) ((uint32) f->data));
491  if (f->type == kFieldTypeUint64)
492  return (int64) getData(*f).readUint64LE();
493  if (f->type == kFieldTypeSint64)
494  return (int64) getData(*f).readUint64LE();
495 
496  // StrRef, a numerical reference to a string in a talk table
497  if (f->type == kFieldTypeStrRef) {
499 
500  const uint32 size = data.readUint32LE();
501  if (size != 4)
502  Common::Exception("GFF3: StrRef field with invalid size (%d)", size);
503 
504  return (int64) ((uint64) data.readUint32LE());
505  }
506 
507  throw Common::Exception("GFF3: Field is not an int type");
508 }
509 
510 bool GFF3Struct::getBool(const Common::UString &field, bool def) const {
511  return getUint(field, def) != 0;
512 }
513 
514 double GFF3Struct::getDouble(const Common::UString &field, double def) const {
515  const Field *f = getField(field);
516  if (!f)
517  return def;
518 
519  if (f->type == kFieldTypeFloat)
520  return convertIEEEFloat(f->data);
521  if (f->type == kFieldTypeDouble)
522  return getData(*f).readIEEEDoubleLE();
523 
524  throw Common::Exception("GFF3: Field is not a double type");
525 }
526 
528  const Common::UString &def) const {
529 
530  const Field *f = getField(field);
531  if (!f)
532  return def;
533 
534  // Direct string
535  if (f->type == kFieldTypeExoString) {
537 
538  const uint32 length = data.readUint32LE();
539  return Common::readStringFixed(data, Common::kEncodingASCII, length);
540  }
541 
542  // ResRef, resource reference, a shorter string
543  if (f->type == kFieldTypeResRef) {
544  /* In most games, this field has a limit of 16 characters, because
545  * resource filenames were limited to 16 characters (without extension)
546  * inside the archives. In Dragon Age: Origins and Dragon Age II,
547  * however, this limit has been lifted, and a full 255 characters
548  * are available in ResRef string fields. */
549 
551 
552  const uint32 length = data.readByte();
553  return Common::readStringFixed(data, Common::kEncodingASCII, length);
554  }
555 
556  // LocString, a localized string
557  if (f->type == kFieldTypeLocString) {
558  LocString locString;
559  getLocString(field, locString);
560 
561  return locString.getString();
562  }
563 
564  // Unsigned integer type, compose a string representation
565  if ((f->type == kFieldTypeByte ) ||
566  (f->type == kFieldTypeUint16) ||
567  (f->type == kFieldTypeUint32) ||
568  (f->type == kFieldTypeUint64) ||
569  (f->type == kFieldTypeStrRef)) {
570 
571  return Common::composeString(getUint(field));
572  }
573 
574  // Signed integer type, compose a string representation
575  if ((f->type == kFieldTypeChar ) ||
576  (f->type == kFieldTypeSint16) ||
577  (f->type == kFieldTypeSint32) ||
578  (f->type == kFieldTypeSint64)) {
579 
580  return Common::composeString(getSint(field));
581  }
582 
583  // Floating point type, compose a string representation
584  if ((f->type == kFieldTypeFloat) ||
585  (f->type == kFieldTypeDouble)) {
586 
587  return Common::composeString(getDouble(field));
588  }
589 
590  // Vector, consisting of 3 floats
591  if (f->type == kFieldTypeVector) {
592  float x = 0.0, y = 0.0, z = 0.0;
593 
594  getVector(field, x, y, z);
595  return Common::composeString(x) + "/" +
596  Common::composeString(y) + "/" +
598  }
599 
600  // Orientation, consisting of 4 floats
601  if (f->type == kFieldTypeOrientation) {
602  float a = 0.0, b = 0.0, c = 0.0, d = 0.0;
603 
604  getOrientation(field, a, b, c, d);
605  return Common::composeString(a) + "/" +
606  Common::composeString(b) + "/" +
607  Common::composeString(c) + "/" +
609  }
610 
611  throw Common::Exception("GFF3: Field is not a string(able) type");
612 }
613 
614 bool GFF3Struct::getLocString(const Common::UString &field, LocString &str) const {
615  const Field *f = getField(field);
616  if (!f || (f->type != kFieldTypeLocString))
617  return false;
618 
619  LocString locString;
620 
621  try {
622 
624 
625  const uint32 size = data.readUint32LE();
626  Common::SeekableSubReadStream locStringData(&data, data.pos(), data.pos() + size);
627 
628  locString.readLocString(locStringData);
629 
630  } catch (...) {
631  return false;
632  }
633 
634  str.swap(locString);
635  return true;
636 }
637 
639  const Field *f = getField(field);
640  if (!f)
641  return 0;
642  if ((f->type != kFieldTypeVoid) &&
643  (f->type != kFieldTypeExoString) &&
644  (f->type != kFieldTypeResRef))
645  throw Common::Exception("GFF3: Field is not a data type");
646 
648 
649  uint32 size = 0;
650  if ((f->type == kFieldTypeVoid) || (f->type == kFieldTypeExoString))
651  size = data.readUint32LE();
652  else if ( f->type == kFieldTypeResRef)
653  size = data.readByte();
654  else
655  throw Common::Exception("GFF3: Field is not a data type");
656 
657  return data.readStream(size);
658 }
659 
661  float &x, float &y, float &z) const {
662 
663  const Field *f = getField(field);
664  if (!f)
665  return;
666  if (f->type != kFieldTypeVector)
667  throw Common::Exception("GFF3: Field is not a vector type");
668 
670 
671  x = data.readIEEEFloatLE();
672  y = data.readIEEEFloatLE();
673  z = data.readIEEEFloatLE();
674 }
675 
677  float &a, float &b, float &c, float &d) const {
678 
679  const Field *f = getField(field);
680  if (!f)
681  return;
682  if (f->type != kFieldTypeOrientation)
683  throw Common::Exception("GFF3: Field is not an orientation type");
684 
686 
687  a = data.readIEEEFloatLE();
688  b = data.readIEEEFloatLE();
689  c = data.readIEEEFloatLE();
690  d = data.readIEEEFloatLE();
691 }
692 
694  double &x, double &y, double &z) const {
695 
696  const Field *f = getField(field);
697  if (!f)
698  return;
699  if (f->type != kFieldTypeVector)
700  throw Common::Exception("GFF3: Field is not a vector type");
701 
703 
704  x = data.readIEEEFloatLE();
705  y = data.readIEEEFloatLE();
706  z = data.readIEEEFloatLE();
707 }
708 
710  double &a, double &b, double &c, double &d) const {
711 
712  const Field *f = getField(field);
713  if (!f)
714  return;
715  if (f->type != kFieldTypeOrientation)
716  throw Common::Exception("GFF3: Field is not an orientation type");
717 
719 
720  a = data.readIEEEFloatLE();
721  b = data.readIEEEFloatLE();
722  c = data.readIEEEFloatLE();
723  d = data.readIEEEFloatLE();
724 }
725 
726 // --- Struct reader ---
727 
729  const Field *f = getField(field);
730  if (!f)
731  throw Common::Exception("GFF3: No such field");
732  if (f->type != kFieldTypeStruct)
733  throw Common::Exception("GFF3: Field is not a struct type");
734 
735  // Direct index into the struct array
736  return _parent->getStruct(f->data);
737 }
738 
739 // --- Struct list reader ---
740 
741 const GFF3List &GFF3Struct::getList(const Common::UString &field) const {
742  const Field *f = getField(field);
743  if (!f)
744  throw Common::Exception("GFF3: No such field");
745  if (f->type != kFieldTypeList)
746  throw Common::Exception("GFF3: Field is not a list type");
747 
748  // Byte offset into the list area, all 32bit values.
749  return _parent->getList(f->data / 4);
750 }
751 
752 } // End of namespace Aurora
Header _header
The GFF3&#39;s header.
Definition: gff3file.h:127
int64 getSint(const Common::UString &field, int64 def=0) const
Definition: gff3file.cpp:473
Handling version V3.2/V3.3 of BioWare&#39;s GFFs (generic file format).
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
A single character.
Definition: gff3file.h:170
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
bool _repairNWNPremium
Should we try to read GFF3 files found in Neverwinter Nights premium modules?
Definition: gff3file.h:130
#define TypeMan
Shortcut for accessing the file type manager.
Definition: util.h:85
std::vector< uint32 > _listOffsetToIndex
To convert list offsets found in GFF3 to real indices.
Definition: gff3file.h:138
const GFF3List & getList(uint32 i) const
Return a list within the GFF3.
Definition: gff3file.cpp:260
bool getBool(const Common::UString &field, bool def=false) const
Definition: gff3file.cpp:510
uint32 fieldOffset
Offset to the field definitions.
Definition: gff3file.h:105
bool getLocString(const Common::UString &field, LocString &str) const
Definition: gff3file.cpp:614
void readFields(Common::SeekableReadStream &data, uint32 index, uint32 count)
Definition: gff3file.cpp:354
A class holding an UTF-8 string.
Definition: ustring.h:48
void loadHeader(uint32 id)
Definition: gff3file.cpp:110
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
A localized string.
Definition: locstring.h:43
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
const GFF3Struct & getStruct(uint32 i) const
Return a struct within the GFF3.
Definition: gff3file.cpp:253
MemoryReadStream * readStream(size_t dataSize)
Read the specified amount of data into a new[]&#39;ed buffer which then is wrapped into a MemoryReadStrea...
Definition: readstream.cpp:67
uint32 _fieldIndex
Field / Field indices index.
Definition: gff3file.h:261
void readLocString(Common::SeekableReadStream &stream, uint32 id, uint32 count)
Read a LocString out of a stream.
Definition: locstring.cpp:165
UString composeString(T value)
Convert any POD integer, float/double or bool type into a string.
Definition: strutil.cpp:276
uint64_t uint64
Definition: types.h:206
uint8_t uint8
Definition: types.h:200
uint32 structOffset
Offset to the struct definitions.
Definition: gff3file.h:103
uint32 labelOffset
Offset to the field labels.
Definition: gff3file.h:107
uint32 getID() const
Return the struct&#39;s ID.
Definition: gff3file.cpp:311
const GFF3File * _parent
The parent GFF3.
Definition: gff3file.h:258
Unsigned 16bit integer.
Definition: gff3file.h:171
bool hasField(const Common::UString &field) const
Does this specific field exist?
Definition: gff3file.cpp:400
String reference, index into a talk table.
Definition: gff3file.h:187
void getOrientation(const Common::UString &field, float &a, float &b, float &c, float &d) const
Definition: gff3file.cpp:676
Implementing the reading stream interfaces for plain memory blocks.
Utility functions to handle files used in BioWare&#39;s Aurora engine.
StructArray _structs
Our structs.
Definition: gff3file.h:134
char getChar(const Common::UString &field, char def='\0') const
Definition: gff3file.cpp:426
const GFF3Struct & getTopLevel() const
Returns the top-level struct.
Definition: gff3file.cpp:91
void read(Common::SeekableReadStream &gff3)
Definition: gff3file.cpp:50
uint64 getUint(const Common::UString &field, uint64 def=0) const
Definition: gff3file.cpp:436
FieldType getFieldType(const Common::UString &field) const
Return the type of this field, or kFieldTypeNone if such a field doesn&#39;t exist.
Definition: gff3file.cpp:408
static const uint32 kVersion32
Definition: gff3file.cpp:42
uint32 structCount
Number of structs.
Definition: gff3file.h:104
FieldType type
Type of the field.
Definition: gff3file.h:247
Utility templates and functions for working with strings and streams.
FieldMap _fields
The fields, indexed by their label.
Definition: gff3file.h:264
int16_t int16
Definition: types.h:201
const Common::UString & getString(Language language, LanguageGender gender=kLanguageGenderCurrent) const
Get the string of that language.
Definition: locstring.cpp:82
uint32 data
Data of the field.
Definition: gff3file.h:248
Exception that provides a stack of explanations.
Definition: error.h:36
void load(uint32 id)
Definition: gff3file.cpp:97
FieldType
The type of a GFF3 field.
Definition: gff3file.h:167
static void readHeader(Common::ReadStream &stream, uint32 &id, uint32 &version, bool &utf16le)
Read the header out of a stream.
Definition: aurorafile.cpp:53
Common::SeekableReadStream & getStream(uint32 offset) const
Return the GFF3 stream.
Definition: gff3file.cpp:275
A vector of 3 floats.
Definition: gff3file.h:186
uint32 fieldCount
Number of fields.
Definition: gff3file.h:106
uint32 listIndicesOffset
Offset to the list indices.
Definition: gff3file.h:113
Basic exceptions to throw.
void getVector(const Common::UString &field, float &x, float &y, float &z) const
Definition: gff3file.cpp:660
uint16_t uint16
Definition: types.h:202
Unsigned 64bit integer.
Definition: gff3file.h:175
Random data of variable length.
Definition: gff3file.h:182
double getDouble(const Common::UString &field, double def=0.0) const
Definition: gff3file.cpp:514
void swap(LocString &str)
Swap the contents of the LocString with this LocString&#39;s.
Definition: locstring.cpp:56
A GFF (generic file format) V3.2/V3.3 file, found in all Aurora games except Sonic Chronicles: The Da...
Definition: gff3file.h:85
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
Definition: readstream.h:317
Signed 16bit integer.
Definition: gff3file.h:172
Signed 64bit integer.
Definition: gff3file.h:176
Utility functions for working with differing string encodings.
uint32 fieldIndicesCount
Number of field indices.
Definition: gff3file.h:112
uint32 _id
The file&#39;s ID.
Definition: aurorafile.h:77
StackException Exception
Definition: error.h:59
uint32 _version
The file&#39;s version.
Definition: aurorafile.h:78
uint32 _fieldCount
Field count.
Definition: gff3file.h:262
uint32 fieldDataOffset
Offset to the field data.
Definition: gff3file.h:109
Handling BioWare&#39;s localized strings.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
uint32 getType() const
Return the GFF3&#39;s specific type.
Definition: gff3file.cpp:87
uint64 readUint64LE()
Read an unsigned 64-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:144
std::vector< const GFF3Struct * > GFF3List
Definition: types.h:449
uint32 _id
The struct&#39;s ID.
Definition: gff3file.h:260
uint32 _offsetCorrection
The correctional value for offsets to repair Neverwinter Nights premium modules.
Definition: gff3file.h:132
int64_t int64
Definition: types.h:205
FORCEINLINE float readIEEEFloatLE()
Read a 32-bit IEEE float stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:230
Unicode string handling.
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
ListArray _lists
Our lists.
Definition: gff3file.h:135
const GFF3List & getList(const Common::UString &field) const
Definition: gff3file.cpp:741
Unsigned 32bit integer.
Definition: gff3file.h:173
Common::SeekableReadStream & getFieldData() const
Return the GFF3 stream seeked to the start of the field data.
Definition: gff3file.cpp:281
Signed 32bit integer.
Definition: gff3file.h:174
virtual ~GFF3File()
Definition: gff3file.cpp:84
A field in the GFF3 struct.
Definition: gff3file.h:246
static const uint32 kVersion33
Definition: gff3file.cpp:43
int8_t int8
Definition: types.h:199
float convertIEEEFloat(uint32 data)
Convert a uint32 holding the bit pattern of a 32-bit IEEE 754 single precision floating point value i...
Definition: util.cpp:116
std::vector< Common::UString > _fieldNames
The names of all fields in this struct.
Definition: gff3file.h:267
A struct within a GFF3.
Definition: gff3file.h:164
Resource reference, string.
Definition: gff3file.h:180
uint32_t uint32
Definition: types.h:204
const GFF3Struct & getStruct(const Common::UString &field) const
Definition: gff3file.cpp:728
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
Definition: strutil.cpp:117
size_t getFieldCount() const
Return the number of fields in this struct.
Definition: gff3file.cpp:396
uint32 listIndicesCount
Number of list indices.
Definition: gff3file.h:114
FORCEINLINE double readIEEEDoubleLE()
Read a 64-bit IEEE double stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:244
FileType
Various file types used by the Aurora engine and found in archives.
Definition: types.h:56
Common::SeekableReadStream * getData(const Common::UString &field) const
Definition: gff3file.cpp:638
GFF3Struct(const GFF3File &parent, uint32 offset)
Definition: gff3file.cpp:304
Common::ScopedPtr< Common::SeekableReadStream > _stream
Definition: gff3file.h:125
List containing a number of structs.
Definition: gff3file.h:184
Common::UString getString(const Common::UString &field, const Common::UString &def="") const
Definition: gff3file.cpp:527
Struct containing a number of fields.
Definition: gff3file.h:183
UString readStringFixed(SeekableReadStream &stream, Encoding encoding, size_t length)
Read length bytes as a string with the given encoding out of a stream.
Definition: encoding.cpp:297
void loadStructs()
Definition: gff3file.cpp:183
void readIndices(Common::SeekableReadStream &data, std::vector< uint32 > &indices, uint32 count) const
Definition: gff3file.cpp:372
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
GFF3File(Common::SeekableReadStream *gff3, uint32 id=0xFFFFFFFF, bool repairNWNPremium=false)
Take over this stream and read a GFF3 file out of it.
Definition: gff3file.cpp:66
void readField(Common::SeekableReadStream &data, uint32 index)
Definition: gff3file.cpp:331
bool extended
Does this field need extended data?
Definition: gff3file.h:249
Interface for a seekable & readable data stream.
Definition: readstream.h:265
const Field * getField(const Common::UString &name) const
Returns the field with this tag.
Definition: gff3file.cpp:418
void load(uint32 offset)
Definition: gff3file.cpp:317
byte readByte()
Read an unsigned byte from the stream and return it.
Definition: readstream.h:92
const std::vector< Common::UString > & getFieldNames() const
Return a list of all field names in this struct.
Definition: gff3file.cpp:404
The global resource manager for Aurora resources.
uint32 fieldIndicesOffset
Offset to the field indices.
Definition: gff3file.h:111
unsigned int uint
Definition: types.h:211
int32_t int32
Definition: types.h:203
Common::UString readLabel(Common::SeekableReadStream &data, uint32 index) const
Definition: gff3file.cpp:379