xoreos  0.0.5
gff4file.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 the GFF description on the Dragon Age toolset wiki
26  * (<http://social.bioware.com/wiki/datoolset/index.php/GFF>).
27  */
28 
29 #include <cassert>
30 
31 #include "glm/gtc/type_ptr.hpp"
32 
33 #include "src/common/error.h"
34 #include "src/common/readstream.h"
35 #include "src/common/encoding.h"
36 #include "src/common/strutil.h"
37 
38 #include "src/aurora/gff4file.h"
39 #include "src/aurora/util.h"
40 #include "src/aurora/resman.h"
41 
42 static const uint32 kGFFID = MKTAG('G', 'F', 'F', ' ');
43 static const uint32 kVersion40 = MKTAG('V', '4', '.', '0');
44 static const uint32 kVersion41 = MKTAG('V', '4', '.', '1');
45 
46 namespace Aurora {
47 
49  platformID = gff4.readUint32BE();
50 
51  const size_t pos = gff4.pos();
52  Common::SeekableSubReadStreamEndian gff4Endian(&gff4, 0, gff4.size(), isBigEndian());
53  gff4Endian.seek(pos);
54 
55  type = gff4Endian.readUint32BE();
56  typeVersion = gff4Endian.readUint32BE();
57  structCount = gff4Endian.readUint32();
58 
59  stringCount = 0;
60  stringOffset = 0xFFFFFFFF;
61 
62  // Only V4.1 has the global string table
63  if (version == kVersion41) {
64  stringCount = gff4Endian.readUint32();
65  stringOffset = gff4Endian.readUint32();
66  }
67 
68  hasSharedStrings = (stringCount > 0) || (stringOffset != 0xFFFFFFFF);
69 
70  dataOffset = gff4Endian.readUint32();
71  gff4.seek(gff4Endian.pos());
72 }
73 
75  return (platformID == kPlatformPS3) || (platformID == kPlatformXbox360);
76 }
77 
78 
80  _origStream(gff4), _topLevelStruct(0) {
81 
82  assert(_origStream);
83 
84  load(type);
85 }
86 
87 GFF4File::GFF4File(const Common::UString &gff4, FileType fileType, uint32 type) :
88  _topLevelStruct(0) {
89 
90  _origStream.reset(ResMan.getResource(gff4, fileType));
91  if (!_origStream)
92  throw Common::Exception("No such GFF4 \"%s\"", TypeMan.setFileType(gff4, fileType).c_str());
93 
94  load(type);
95 }
96 
98  clear();
99 }
100 
102  _origStream.reset();
103  _stream.reset();
104 
105  for (StructMap::iterator s = _structs.begin(); s != _structs.end(); ++s)
106  delete s->second;
107 
108  _structs.clear();
109  _topLevelStruct = 0;
110 }
111 
113  return _header.type;
114 }
115 
117  return _header.typeVersion;
118 }
119 
121  return _header.platformID;
122 }
123 
124 bool GFF4File::isBigEndian() const {
125  return _header.isBigEndian();
126 }
127 
129  if (_header.isBigEndian())
131 
133 }
134 
136  assert(_topLevelStruct);
137 
138  return *_topLevelStruct;
139 }
140 
141 // --- Loader ---
142 
143 void GFF4File::load(uint32 type) {
144  try {
145 
146  loadHeader(type);
147  loadStructs();
148  loadStrings();
149 
150  } catch (Common::Exception &e) {
151  clear();
152 
153  e.add("Failed reading GFF4 file");
154  throw;
155  }
156 }
157 
160 
161  if (_id != kGFFID)
162  throw Common::Exception("Not a GFF4 file");
163 
164  if ((_version != kVersion40) && (_version != kVersion41))
165  throw Common::Exception("Unsupported GFF4 file version %s", Common::debugTag(_version).c_str());
166 
168 
169  const size_t pos = _origStream->pos();
171  _header.isBigEndian(), false));
172  _stream->seek(pos);
173 
174  if ((type != 0xFFFFFFFF) && (_header.type != type))
175  throw Common::Exception("GFF4 has invalid type (want %s, got %s)",
177 
178  if (_header.structCount == 0)
179  throw Common::Exception("GFF4 has no structs");
180 }
181 
183  /* Load the struct templates.
184  *
185  * The struct template defines the structure of a struct, i.e. how
186  * many fields there are and of what type. Each field of a struct type
187  * references one of these templates. When two structs contain the same
188  * structure (but not necessarily the same field *values*), they can
189  * both reference the same struct template.
190  *
191  * So while in a GFF3, each individual struct said how its fields
192  * looked, in a GFF4 this has been sourced out into these templates. */
193 
194  static const uint32 kStructTemplateSize = 16;
195  const uint32 structTemplateStart = _stream->pos();
196 
198  for (uint32 i = 0; i < _header.structCount; i++) {
199  _stream->seek(structTemplateStart + i * kStructTemplateSize);
200 
201  StructTemplate &strct = _structTemplates[i];
202 
203  // Read struct properties
204 
205  strct.index = i;
206  strct.label = _stream->readUint32BE();
207 
208  const uint32 fieldCount = _stream->readUint32();
209  const uint32 fieldOffset = _stream->readUint32();
210 
211  strct.size = _stream->readUint32();
212 
213  // Check if we need to read fields
214  if (fieldOffset == 0xFFFFFFFF) {
215  if (fieldCount != 0)
216  throw Common::Exception("GFF4: fieldOffset NULL, but fieldCount %u", fieldCount);
217 
218  continue;
219  }
220 
221  _stream->seek(fieldOffset);
222 
223  // Read the field declarations
224 
225  strct.fields.resize(fieldCount);
226  for (uint32 j = 0; j < fieldCount; j++) {
227  StructTemplate::Field &field = strct.fields[j];
228 
229  field.label = _stream->readUint32();
230 
231  const uint32 typeAndFlags = _stream->readUint32();
232  field.type = (typeAndFlags & 0x0000FFFF);
233  field.flags = (typeAndFlags & 0xFFFF0000) >> 16;
234 
235  field.offset = _stream->readUint32();
236  }
237  }
238 
239  /* And load the top level struct, which itself recurses into field structs.
240  * The top level struct is always constructed using the first template. */
243 }
244 
246  /* Load the global, shared string table.
247  *
248  * If this GFF4 file has such a table (which is only supported in V4.1),
249  * each individual string field in a struct doesn't provide its own data.
250  * Instead, they then reference this shared string table. */
251 
253  return;
254 
256 
258  for (uint32 i = 0; i < _header.stringCount; i++)
260 }
261 
262 // --- Helpers for GFF4Struct ---
263 
265  /* Each struct, on creation, registers itself to the GFF4 files it
266  * belongs in.
267  *
268  * This is especially necessary for finding reference duplicates:
269  * a struct can be referenced by multiple struct type fields. For
270  * example, let there be structs A, B, C, and D. Structs, A, B and C
271  * can each contain a field "x" of type struct, each linking to
272  * struct D. Moreover, D can even contain field "y" of type struct,
273  * linking back to A, thus creating a loop. */
274 
275  std::pair<StructMap::iterator, bool> result;
276 
277  result = _structs.insert(std::make_pair(id, strct));
278  if (!result.second)
279  throw Common::Exception("GFF4: Duplicate struct");
280 }
281 
283  _structs.erase(id);
284 }
285 
287  StructMap::iterator s = _structs.find(id);
288  if (s == _structs.end())
289  return 0;
290 
291  return s->second;
292 }
293 
295  _stream->seek(offset);
296 
297  return *_stream;
298 }
299 
301  return _header.dataOffset;
302 }
303 
305  if (i >= _structTemplates.size())
306  throw Common::Exception("GFF4: Struct template out of range (%u >= %u)",
307  i, (uint) _structTemplates.size());
308 
309  return _structTemplates[i];
310 }
311 
313  return _header.hasSharedStrings;
314 }
315 
317  if (i == 0xFFFFFFFF)
318  return "";
319 
320  if (i >= _sharedStrings.size())
321  throw Common::Exception("GFF4: Shared string index out of range (%u >= %u)",
322  i, (uint) _sharedStrings.size());
323 
324  return _sharedStrings[i];
325 }
326 
327 
328 GFF4Struct::Field::Field() : label(0), type(kFieldTypeNone), offset(0xFFFFFFFF),
329  isList(false), isReference(false), isGeneric(false), structIndex(0) {
330 
331 }
332 
334  label(l), offset(o), isGeneric(g) {
335 
336  isList = (f & 0x8000) != 0;
337  isReference = (f & 0x2000) != 0;
338 
339  // Map the struct flag to the struct type and index, if necessary
340  const bool isStruct = (f & 0x4000) != 0;
341  if (isStruct) {
343  structIndex = t;
344  } else {
345  type = (FieldType) t;
346  structIndex = 0;
347  }
348 
349  // A string is always read by reference. An extra reference flag is superfluous.
350  if (type == kFieldTypeString)
351  isReference = false;
352 
353  bool supportedConfig = true;
354 
355  // We don't know how any of these work
356  if (isList && (type == kFieldTypeASCIIString))
357  supportedConfig = false;
358  if (isList && (type == kFieldTypeTlkString))
359  supportedConfig = false;
361  supportedConfig = false;
362  if (isList && !isReference && (type == kFieldTypeGeneric))
363  supportedConfig = false;
364 
365  if (!supportedConfig)
366  throw Common::Exception("GFF4: TODO: Field type %d, isList %d, isReference %d",
367  (int) type, isList, isReference);
368 }
369 
371 }
372 
373 
375  _parent(&parent), _label(tmplt.label), _refCount(0), _fieldCount(0) {
376 
377  // Constructor for a real struct, from a template
378 
379  _id = generateID(offset, &tmplt);
380  parent.registerStruct(_id, this);
381 
382  try {
383  load(parent, offset, tmplt);
384  } catch (...) {
385  parent.unregisterStruct(_id);
386  throw;
387  }
388 }
389 
390 GFF4Struct::GFF4Struct(GFF4File &parent, const Field &genericParent) :
391  _parent(&parent), _label(0), _refCount(0), _fieldCount(0) {
392 
393  // Constructor for a generic, converted into a struct
394 
395  _id = generateID(genericParent.offset);
396  parent.registerStruct(_id, this);
397 
398  try {
399  load(parent, genericParent);
400  } catch (...) {
401  parent.unregisterStruct(_id);
402  throw;
403  }
404 }
405 
407 }
408 
410  return _id;
411 }
412 
414  return _refCount;
415 }
416 
418  return _label;
419 }
420 
421 // --- Loader ---
422 
423 void GFF4Struct::load(GFF4File &parent, uint32 offset, const GFF4File::StructTemplate &tmplt) {
424  /* Loader for a real struct, from a template.
425  *
426  * Go through all the fields in the template and create field
427  * instances within this struct instance. If the field is itself
428  * a struct, recursively create a new struct instance for it. If
429  * the field is a generic, create a struct for it as well. */
430 
431  for (size_t i = 0; i < tmplt.fields.size(); i++) {
432  const GFF4File::StructTemplate::Field &field = tmplt.fields[i];
433 
434  _fieldLabels.push_back(field.label);
435 
436  // Calculate the offset for the field data, but guard against NULL pointers
437  uint32 fieldOffset = offset + field.offset;
438  if ((offset == 0xFFFFFFFF) || (field.offset == 0xFFFFFFFF))
439  fieldOffset = 0xFFFFFFFF;
440 
441  // Load the field and its struct(s), if any
442  Field &f = _fields[field.label] = Field(field.label, field.type, field.flags, fieldOffset);
443  if (f.type == kFieldTypeStruct)
444  loadStructs(parent, f);
445  if (f.type == kFieldTypeGeneric)
446  loadGeneric(parent, f);
447 
448  if ((f.type == kFieldTypeASCIIString) && parent.hasSharedStrings())
449  throw Common::Exception("GFF4: TODO: ASCII string field in a file with shared strings");
450  }
451 
452  _fieldCount = _fields.size();
453 }
454 
455 void GFF4Struct::loadStructs(GFF4File &parent, Field &field) {
456  if (field.offset == 0xFFFFFFFF)
457  return;
458 
459  /* Loader for fields of struct type.
460  *
461  * This field can be
462  * a) a list of structs
463  * b) a reference (pointer) to a struct
464  * c) both
465  *
466  * We figure out how many structs there are (1 if not a list),
467  * where the offset is (dependent on whether it's a reference)
468  * and then we load every single one of them. However, we also
469  * ask the parent GFF4 if we already have loaded the struct in
470  * question (which can happen, because more than one reference
471  * can point to the same struct). If that is the case, we don't
472  * need to load it again. */
473 
474  const GFF4File::StructTemplate &tmplt = parent.getStructTemplate(field.structIndex);
475 
477 
478  const uint32 structCount = getListCount(data, field);
479  const uint32 structSize = field.isReference ? 4 : tmplt.size;
480  const uint32 structStart = data.pos();
481 
482  field.structs.resize(structCount, 0);
483  for (uint32 i = 0; i < structCount; i++) {
484  const uint32 offset = getDataOffset(field.isReference, structStart + i * structSize);
485  if (offset == 0xFFFFFFFF)
486  continue;
487 
488  GFF4Struct *strct = parent.findStruct(generateID(offset, &tmplt));
489  if (!strct)
490  strct = new GFF4Struct(parent, offset, tmplt);
491 
492  strct->_refCount++;
493 
494  field.structs[i] = strct;
495  }
496 }
497 
498 void GFF4Struct::loadGeneric(GFF4File &parent, Field &field) {
499  field.offset = getDataOffset(field.isList, field.offset);
500  if (field.offset == 0xFFFFFFFF)
501  return;
502 
503  // Loader for fields of generic type. We map the generic to a struct.
504 
505  GFF4Struct *strct = parent.findStruct(generateID(field.offset));
506  if (!strct)
507  strct = new GFF4Struct(parent, field);
508 
509  strct->_refCount++;
510 
511  field.structs.push_back(strct);
512 }
513 
514 void GFF4Struct::load(GFF4File &parent, const Field &genericParent) {
515  /* Loader for generic, converting it into a struct.
516  *
517  * Go through all the elements of the generic and create fields
518  * for them in this struct instance. If the element itself is a
519  * struct, recursively create a new struct instance for it. */
520 
521  static const uint32 kGenericSize = 8;
522 
523  Common::SeekableSubReadStreamEndian &data = parent.getStream(genericParent.offset);
524 
525  const uint32 genericCount = genericParent.isList ? data.readUint32() : 1;
526  const uint32 genericStart = data.pos();
527 
528  for (uint32 i = 0; i < genericCount; i++) {
529  data.seek(genericStart + i * kGenericSize);
530 
531  const uint32 typeAndFlags = data.readUint32();
532  const uint16 fieldType = (typeAndFlags & 0x0000FFFF);
533  const uint16 fieldFlags = (typeAndFlags & 0xFFFF0000) >> 16;
534 
535  const uint32 fieldOffset = getDataOffset(genericParent.isReference, data.pos());
536 
537  if (fieldOffset == 0xFFFFFFFF)
538  continue;
539 
540  _fieldLabels.push_back(i);
541 
542  // Load the field and its struct(s), if any
543  Field &f = _fields[i] = Field(i, fieldType, fieldFlags, fieldOffset, true);
544  if (f.type == kFieldTypeStruct)
545  loadStructs(parent, f);
546  if (f.type == kFieldTypeGeneric)
547  throw Common::Exception("GFF4: Found a generic with type generic?");
548 
549  if ((f.type == kFieldTypeASCIIString) && parent.hasSharedStrings())
550  throw Common::Exception("GFF4: TODO: ASCII string field in a file with shared strings");
551  }
552 
553  _fieldCount = genericCount;
554 }
555 
557  /* Generate a unique ID identifying this struct within the GFF4 file.
558  * The offset is an obvious choice. We also add the template index,
559  * just to make sure.
560  *
561  * (However, if this struct is actually a mapped generic, there is
562  * no template index). */
563 
564  return (((uint64) offset) << 32) | (tmplt ? tmplt->index : 0xFFFFFFFF);
565 }
566 
567 // --- Field properties ---
568 
570  return _fieldCount;
571 }
572 
573 bool GFF4Struct::hasField(uint32 field) const {
574  return getField(field) != 0;
575 }
576 
577 const std::vector<uint32> &GFF4Struct::getFieldLabels() const {
578  return _fieldLabels;
579 }
580 
582  bool isList;
583  return getFieldType(field, isList);
584 }
585 
587  const Field *f = getField(field);
588  if (!f)
589  return kFieldTypeNone;
590 
591  isList = f->isList;
592 
593  return f->type;
594 }
595 
596 bool GFF4Struct::getFieldProperties(uint32 field, FieldType &type, uint32 &label, bool &isList) const {
597  const Field *f = getField(field);
598  if (!f)
599  return false;
600 
601  type = f->type;
602  label = f->label;
603  isList = f->isList;
604 
605  return true;
606 }
607 
608 // --- Field value reader helpers ---
609 
611  FieldMap::const_iterator f = _fields.find(field);
612  if (f == _fields.end())
613  return 0;
614 
615  return &f->second;
616 }
617 
618 uint32 GFF4Struct::getDataOffset(bool isReference, uint32 offset) const {
619  if (!isReference || (offset == 0xFFFFFFFF))
620  return offset;
621 
623 
624  offset = data.readUint32();
625  if (offset == 0xFFFFFFFF)
626  return offset;
627 
628  return _parent->getDataOffset() + offset;
629 }
630 
632  if (field.type == kFieldTypeStruct)
633  return 0xFFFFFFFF;
634 
635  return getDataOffset(field.isReference, field.offset);
636 }
637 
639  const uint32 offset = getDataOffset(field);
640  if (offset == 0xFFFFFFFF)
641  return 0;
642 
643  return &_parent->getStream(offset);
644 }
645 
647  if (!(field = getField(fieldID)))
648  return 0;
649 
650  return getData(*field);
651 }
652 
653 uint32 GFF4Struct::getVectorMatrixLength(const Field &field, uint32 minLength, uint32 maxLength) const {
654  uint32 length;
655  if (field.type == kFieldTypeVector3f)
656  length = 3;
657  else if ((field.type == kFieldTypeVector4f) ||
658  (field.type == kFieldTypeQuaternionf) ||
659  (field.type == kFieldTypeColor4f))
660  length = 4;
661  else if (field.type == kFieldTypeMatrix4x4f)
662  length = 16;
663  else
664  throw Common::Exception("GFF4: Field is not of Vector/Matrix type");
665 
666  if (length < minLength)
667  throw Common::Exception("GFF4: Vector/Matrix type is too short (%d < %d)", length, minLength);
668  if (length > maxLength)
669  throw Common::Exception("GFF4: Vector/Matrix type is too long (%d > %d)", length, maxLength);
670 
671  return length;
672 }
673 
675  if (!field.isList)
676  return 1;
677 
678  const uint32 listOffset = data.readUint32();
679  if (listOffset == 0xFFFFFFFF)
680  return 0;
681 
682  data.seek(_parent->getDataOffset() + listOffset);
683 
684  return data.readUint32();
685 }
686 
688  switch (type) {
689  case kFieldTypeUint8:
690  case kFieldTypeSint8:
691  return 1;
692 
693  case kFieldTypeUint16:
694  case kFieldTypeSint16:
695  return 2;
696 
697  case kFieldTypeUint32:
698  case kFieldTypeSint32:
699  case kFieldTypeFloat32:
700  return 4;
701 
702  case kFieldTypeUint64:
703  case kFieldTypeSint64:
704  case kFieldTypeFloat64:
705  return 8;
706 
707  case kFieldTypeVector3f:
708  return 3 * 4;
709 
710  case kFieldTypeVector4f:
712  case kFieldTypeColor4f:
713  return 4 * 4;
714 
716  return 16 * 4;
717 
718  case kFieldTypeTlkString:
719  return 2 * 4;
720 
721  case kFieldTypeString:
722  // The raw form is a pointer...
723  return 4;
724 
726  // Actually depending on the content...
727  return 4;
728 
729  default:
730  break;
731  }
732 
733  return 0;
734 }
735 
736 // --- Low-level value readers ---
737 
739  switch (type) {
740  case kFieldTypeUint8:
741  return (uint64) data.readByte();
742 
743  case kFieldTypeSint8:
744  return (uint64) ((int64) data.readSByte());
745 
746  case kFieldTypeUint16:
747  return (uint64) data.readUint16();
748 
749  case kFieldTypeSint16:
750  return (uint64) ((int64) data.readSint16());
751 
752  case kFieldTypeUint32:
753  return (uint64) data.readUint32();
754 
755  case kFieldTypeSint32:
756  return (uint64) ((int64) data.readSint32());
757 
758  case kFieldTypeUint64:
759  return (uint64) data.readUint64();
760 
761  case kFieldTypeSint64:
762  return (uint64) ((int64) data.readSint64());
763 
764  default:
765  break;
766  }
767 
768  throw Common::Exception("GFF4: Field is not an int type");
769 }
770 
772  switch (type) {
773  case kFieldTypeUint8:
774  return (int64) ((uint64) data.readByte());
775 
776  case kFieldTypeSint8:
777  return (int64) data.readSByte();
778 
779  case kFieldTypeUint16:
780  return (int64) ((uint64) data.readUint16());
781 
782  case kFieldTypeSint16:
783  return (int64) data.readSint16();
784 
785  case kFieldTypeUint32:
786  return (int64) ((uint64) data.readUint32());
787 
788  case kFieldTypeSint32:
789  return (int64) data.readSint32();
790 
791  case kFieldTypeUint64:
792  return (int64) ((uint64) data.readUint64());
793 
794  case kFieldTypeSint64:
795  return (int64) data.readSint64();
796 
797  default:
798  break;
799  }
800 
801  throw Common::Exception("GFF4: Field is not an int type");
802 }
803 
805  switch (type) {
806  case kFieldTypeFloat32:
807  return (double) data.readIEEEFloat();
808 
809  case kFieldTypeFloat64:
810  return (double) data.readIEEEDouble();
811 
812  case kFieldTypeNDSFixed:
813  return readNintendoFixedPoint(data.readUint32(), true, 19, 12);
814 
815  default:
816  break;
817  }
818 
819  throw Common::Exception("GFF4: Field is not a float type");
820 }
821 
823  switch (type) {
824  case kFieldTypeFloat32:
825  return (float) data.readIEEEFloat();
826 
827  case kFieldTypeFloat64:
828  return (float) data.readIEEEDouble();
829 
830  case kFieldTypeNDSFixed:
831  return (float) readNintendoFixedPoint(data.readUint32(), true, 19, 12);
832 
833  default:
834  break;
835  }
836 
837  throw Common::Exception("GFF4: Field is not a float type");
838 }
839 
841  /* When the string is encoded in UTF-8, then length field specifies the length in bytes.
842  * Otherwise, it's the length in characters. */
843  const size_t lengthMult = encoding == Common::kEncodingUTF8 ? 1 : Common::getBytesPerCodepoint(encoding);
844 
845  const size_t offset = data.pos();
846 
847  const uint32 length = data.readUint32();
848  const size_t size = length * lengthMult;
849 
850  try {
851  return Common::readStringFixed(data, encoding, size);
852  } catch (...) {
853  }
854 
855  return Common::UString::format("GFF4: Invalid string encoding (0x%08X)", (uint) offset);
856 }
857 
859  uint32 offset) const {
860 
861  const uint32 pos = data.seek(offset);
862 
863  Common::UString str = getString(data, encoding);
864 
865  data.seek(pos);
866 
867  return str;
868 }
869 
871  Common::Encoding encoding) const {
872 
873  if (field.type == kFieldTypeString) {
874  if (_parent->hasSharedStrings())
875  return _parent->getSharedString(data.readUint32());
876 
877  uint32 offset = data.pos();
878  if (!field.isGeneric) {
879  offset = data.readUint32();
880  if (offset == 0xFFFFFFFF)
881  return "";
882 
883  offset += _parent->getDataOffset();
884  }
885 
886  return getString(data, encoding, offset);
887  }
888 
889  if (field.type == kFieldTypeASCIIString)
890  return getString(data, Common::kEncodingASCII, data.pos());
891 
892  throw Common::Exception("GFF4: Field is not a string type");
893 }
894 
895 // --- Single value readers ---
896 
898  const Field *f;
900  if (!data)
901  return def;
902 
903  if (f->isList)
904  throw Common::Exception("GFF4: Tried reading list as singular value");
905 
906  return getUint(*data, f->type);
907 }
908 
910  const Field *f;
912  if (!data)
913  return def;
914 
915  if (f->isList)
916  throw Common::Exception("GFF4: Tried reading list as singular value");
917 
918  return getSint(*data, f->type);
919 }
920 
921 bool GFF4Struct::getBool(uint32 field, bool def) const {
922  return getUint(field, def) != 0;
923 }
924 
925 double GFF4Struct::getDouble(uint32 field, double def) const {
926  const Field *f;
928  if (!data)
929  return def;
930 
931  if (f->isList)
932  throw Common::Exception("GFF4: Tried reading list as singular value");
933 
934  return getDouble(*data, f->type);
935 }
936 
937 float GFF4Struct::getFloat(uint32 field, float def) const {
938  const Field *f;
940  if (!data)
941  return def;
942 
943  if (f->isList)
944  throw Common::Exception("GFF4: Tried reading list as singular value");
945 
946  return getFloat(*data, f->type);
947 }
948 
950  const Common::UString &def) const {
951 
952  const Field *f;
954  if (!data)
955  return def;
956 
957  if (f->isList)
958  throw Common::Exception("GFF4: Tried reading list as singular value");
959 
960  return getString(*data, *f, encoding);
961 }
962 
964  return getString(field, _parent->getNativeEncoding(), def);
965 }
966 
968  uint32 &strRef, Common::UString &str) const {
969 
970  const Field *f;
972  if (!data)
973  return false;
974 
975  if (f->type != kFieldTypeTlkString)
976  throw Common::Exception("GFF4: Field is not of TalkString type");
977  if (f->isList)
978  throw Common::Exception("GFF4: Tried reading list as singular value");
979 
980  strRef = getUint(*data, kFieldTypeUint32);
981 
982  const uint32 offset = getUint(*data, kFieldTypeUint32);
983 
984  str.clear();
985  if (offset != 0xFFFFFFFF) {
986  if (_parent->hasSharedStrings())
987  str = _parent->getSharedString(offset);
988  else if (offset != 0)
989  str = getString(*data, encoding, _parent->getDataOffset() + offset);
990  }
991 
992  return true;
993 }
994 
995 bool GFF4Struct::getTalkString(uint32 field, uint32 &strRef, Common::UString &str) const {
996  return getTalkString(field, _parent->getNativeEncoding(), strRef, str);
997 }
998 
999 bool GFF4Struct::getVector3(uint32 field, double &v1, double &v2, double &v3) const {
1000  const Field *f;
1002  if (!data)
1003  return false;
1004 
1005  if (f->isList)
1006  throw Common::Exception("GFF4: Tried reading list as singular value");
1007 
1008  getVectorMatrixLength(*f, 3, 3);
1009 
1010  v1 = getDouble(*data, kFieldTypeFloat32);
1011  v2 = getDouble(*data, kFieldTypeFloat32);
1012  v3 = getDouble(*data, kFieldTypeFloat32);
1013 
1014  return true;
1015 }
1016 
1017 bool GFF4Struct::getVector3(uint32 field, float &v1, float &v2, float &v3) const {
1018  const Field *f;
1020  if (!data)
1021  return false;
1022 
1023  if (f->isList)
1024  throw Common::Exception("GFF4: Tried reading list as singular value");
1025 
1026  getVectorMatrixLength(*f, 3, 3);
1027 
1028  v1 = getFloat(*data, kFieldTypeFloat32);
1029  v2 = getFloat(*data, kFieldTypeFloat32);
1030  v3 = getFloat(*data, kFieldTypeFloat32);
1031 
1032  return true;
1033 }
1034 
1035 bool GFF4Struct::getVector4(uint32 field, double &v1, double &v2, double &v3, double &v4) const {
1036  const Field *f;
1038  if (!data)
1039  return false;
1040 
1041  if (f->isList)
1042  throw Common::Exception("GFF4: Tried reading list as singular value");
1043 
1044  getVectorMatrixLength(*f, 4, 4);
1045 
1046  v1 = getDouble(*data, kFieldTypeFloat32);
1047  v2 = getDouble(*data, kFieldTypeFloat32);
1048  v3 = getDouble(*data, kFieldTypeFloat32);
1049  v4 = getDouble(*data, kFieldTypeFloat32);
1050 
1051  return true;
1052 }
1053 
1054 bool GFF4Struct::getVector4(uint32 field, float &v1, float &v2, float &v3, float &v4) const {
1055  const Field *f;
1057  if (!data)
1058  return false;
1059 
1060  if (f->isList)
1061  throw Common::Exception("GFF4: Tried reading list as singular value");
1062 
1063  getVectorMatrixLength(*f, 4, 4);
1064 
1065  v1 = getFloat(*data, kFieldTypeFloat32);
1066  v2 = getFloat(*data, kFieldTypeFloat32);
1067  v3 = getFloat(*data, kFieldTypeFloat32);
1068  v4 = getFloat(*data, kFieldTypeFloat32);
1069 
1070  return true;
1071 }
1072 
1073 bool GFF4Struct::getMatrix4x4(uint32 field, double (&m)[16]) const {
1074  const Field *f;
1076  if (!data)
1077  return false;
1078 
1079  if (f->isList)
1080  throw Common::Exception("GFF4: Tried reading list as singular value");
1081 
1082  const uint32 length = getVectorMatrixLength(*f, 16, 16);
1083  for (uint32 i = 0; i < length; i++)
1084  m[i] = getDouble(*data, kFieldTypeFloat32);
1085 
1086  return true;
1087 }
1088 
1089 bool GFF4Struct::getMatrix4x4(uint32 field, float (&m)[16]) const {
1090  const Field *f;
1092  if (!data)
1093  return false;
1094 
1095  if (f->isList)
1096  throw Common::Exception("GFF4: Tried reading list as singular value");
1097 
1098  const uint32 length = getVectorMatrixLength(*f, 16, 16);
1099  for (uint32 i = 0; i < length; i++)
1100  m[i] = getFloat(*data, kFieldTypeFloat32);
1101 
1102  return true;
1103 }
1104 
1105 bool GFF4Struct::getMatrix4x4(uint32 field, glm::mat4 &m) const {
1106  float f[16];
1107  if (!getMatrix4x4(field, f))
1108  return false;
1109 
1110  m = glm::make_mat4(f);
1111  return true;
1112 }
1113 
1114 bool GFF4Struct::getVectorMatrix(uint32 field, std::vector<double> &vectorMatrix) const {
1115  const Field *f;
1117  if (!data)
1118  return false;
1119 
1120  if (f->isList)
1121  throw Common::Exception("GFF4: Tried reading list as singular value");
1122 
1123  const uint32 length = getVectorMatrixLength(*f, 0, 16);
1124 
1125  vectorMatrix.resize(length);
1126  for (uint32 i = 0; i < length; i++)
1127  vectorMatrix[i] = getDouble(*data, kFieldTypeFloat32);
1128 
1129  return true;
1130 }
1131 
1132 bool GFF4Struct::getVectorMatrix(uint32 field, std::vector<float> &vectorMatrix) const {
1133  const Field *f;
1135  if (!data)
1136  return false;
1137 
1138  if (f->isList)
1139  throw Common::Exception("GFF4: Tried reading list as singular value");
1140 
1141  const uint32 length = getVectorMatrixLength(*f, 0, 16);
1142 
1143  vectorMatrix.resize(length);
1144  for (uint32 i = 0; i < length; i++)
1145  vectorMatrix[i] = getFloat(*data, kFieldTypeFloat32);
1146 
1147  return true;
1148 }
1149 
1150 // --- List value readers ---
1151 
1152 bool GFF4Struct::getUint(uint32 field, std::vector<uint64> &list) const {
1153  const Field *f;
1155  if (!data)
1156  return false;
1157 
1158  const uint32 count = getListCount(*data, *f);
1159 
1160  list.resize(count);
1161  for (uint32 i = 0; i < count; i++)
1162  list[i] = getUint(*data, f->type);
1163 
1164  return true;
1165 }
1166 
1167 bool GFF4Struct::getSint(uint32 field, std::vector<int64> &list) const {
1168  const Field *f;
1170  if (!data)
1171  return false;
1172 
1173  const uint32 count = getListCount(*data, *f);
1174 
1175  list.resize(count);
1176  for (uint32 i = 0; i < count; i++)
1177  list[i] = getSint(*data, f->type);
1178 
1179  return true;
1180 }
1181 
1182 bool GFF4Struct::getBool(uint32 field, std::vector<bool> &list) const {
1183  const Field *f;
1185  if (!data)
1186  return false;
1187 
1188  const uint32 count = getListCount(*data, *f);
1189 
1190  list.resize(count);
1191  for (uint32 i = 0; i < count; i++)
1192  list[i] = getUint(*data, f->type) != 0;
1193 
1194  return true;
1195 }
1196 
1197 bool GFF4Struct::getDouble(uint32 field, std::vector<double> &list) const {
1198  const Field *f;
1200  if (!data)
1201  return false;
1202 
1203  const uint32 count = getListCount(*data, *f);
1204 
1205  list.resize(count);
1206  for (uint32 i = 0; i < count; i++)
1207  list[i] = getDouble(*data, f->type);
1208 
1209  return true;
1210 }
1211 
1212 bool GFF4Struct::getFloat(uint32 field, std::vector<float> &list) const {
1213  const Field *f;
1215  if (!data)
1216  return false;
1217 
1218  const uint32 count = getListCount(*data, *f);
1219 
1220  list.resize(count);
1221  for (uint32 i = 0; i < count; i++)
1222  list[i] = getFloat(*data, f->type);
1223 
1224  return true;
1225 }
1226 
1228  std::vector<Common::UString> &list) const {
1229 
1230  const Field *f;
1232  if (!data) {
1233  if (f && !f->isList) {
1234  list.push_back("");
1235  return true;
1236  }
1237 
1238  return false;
1239  }
1240 
1241  const uint32 count = getListCount(*data, *f);
1242 
1243  list.resize(count);
1244  for (uint32 i = 0; i < count; i++)
1245  list[i] = getString(*data, *f, encoding);
1246 
1247  return true;
1248 }
1249 
1250 bool GFF4Struct::getString(uint32 field, std::vector<Common::UString> &list) const {
1251  return getString(field, _parent->getNativeEncoding(), list);
1252 }
1253 
1255  std::vector<uint32> &strRefs, std::vector<Common::UString> &strs) const {
1256 
1257 
1258  const Field *f;
1260  if (!data)
1261  return false;
1262 
1263  if (f->type != kFieldTypeTlkString)
1264  throw Common::Exception("GFF4: Field is not of TalkString type");
1265 
1266  const uint32 count = getListCount(*data, *f);
1267 
1268  strRefs.resize(count);
1269  strs.resize(count);
1270 
1271  std::vector<uint32> offsets;
1272  offsets.resize(count);
1273 
1274  for (uint32 i = 0; i < count; i++) {
1275  strRefs[i] = getUint(*data, kFieldTypeUint32);
1276 
1277  const uint32 offset = getUint(*data, kFieldTypeUint32);
1278 
1279  if (offset != 0xFFFFFFFF) {
1280  if (_parent->hasSharedStrings())
1281  strs[i] = _parent->getSharedString(offset);
1282  else if (offset != 0)
1283  strs[i] = getString(*data, encoding, _parent->getDataOffset() + offset);
1284  }
1285  }
1286 
1287  return true;
1288 }
1289 
1291  std::vector<uint32> &strRefs, std::vector<Common::UString> &strs) const {
1292 
1293  return getTalkString(field, _parent->getNativeEncoding(), strRefs, strs);
1294 }
1295 
1296 bool GFF4Struct::getVectorMatrix(uint32 field, std::vector< std::vector<double> > &list) const {
1297  const Field *f;
1299  if (!data)
1300  return false;
1301 
1302  const uint32 length = getVectorMatrixLength(*f, 0, 16);
1303  const uint32 count = getListCount(*data, *f);
1304 
1305  list.resize(count);
1306  for (uint32 i = 0; i < count; i++) {
1307 
1308  list[i].resize(length);
1309  for (uint32 j = 0; j < length; j++)
1310  list[i][j] = getDouble(*data, kFieldTypeFloat32);
1311  }
1312 
1313  return true;
1314 }
1315 
1316 bool GFF4Struct::getVectorMatrix(uint32 field, std::vector< std::vector<float> > &list) const {
1317  const Field *f;
1319  if (!data)
1320  return false;
1321 
1322  const uint32 length = getVectorMatrixLength(*f, 0, 16);
1323  const uint32 count = getListCount(*data, *f);
1324 
1325  list.resize(count);
1326  for (uint32 i = 0; i < count; i++) {
1327 
1328  list[i].resize(length);
1329  for (uint32 j = 0; j < length; j++)
1330  list[i][j] = getFloat(*data, kFieldTypeFloat32);
1331  }
1332 
1333  return true;
1334 }
1335 
1336 bool GFF4Struct::getMatrix4x4(uint32 field, std::vector<glm::mat4> &list) const {
1337  const Field *f;
1339  if (!data)
1340  return false;
1341 
1342  const uint32 length = getVectorMatrixLength(*f, 0, 16);
1343  const uint32 count = getListCount(*data, *f);
1344 
1345  list.resize(count);
1346  for (uint32 i = 0; i < count; i++) {
1347  float m[16];
1348 
1349  for (uint32 j = 0; j < length; j++)
1350  m[j] = getFloat(*data, kFieldTypeFloat32);
1351 
1352  list[i] = glm::make_mat4(m);
1353  }
1354 
1355  return true;
1356 }
1357 
1358 // --- Struct reader ---
1359 
1361  const Field *f = getField(field);
1362  if (!f)
1363  return 0;
1364 
1365  if (f->type != kFieldTypeStruct)
1366  throw Common::Exception("GFF4: Field is not of struct type");
1367  if (f->isList)
1368  throw Common::Exception("GFF4: Tried reading list as singular value");
1369 
1370  if (!f->structs.empty())
1371  return f->structs[0];
1372 
1373  return 0;
1374 }
1375 
1376 // --- Generic reader ---
1377 
1379  const Field *f = getField(field);
1380  if (!f)
1381  return 0;
1382 
1383  if (f->type != kFieldTypeGeneric)
1384  throw Common::Exception("GFF4: Field is not of generic type");
1385 
1386  if (!f->structs.empty())
1387  return f->structs[0];
1388 
1389  return 0;
1390 }
1391 
1392 // --- Struct list reader ---
1393 
1394 const GFF4List &GFF4Struct::getList(uint32 field) const {
1395  const Field *f = getField(field);
1396  if (!f)
1397  throw Common::Exception("GFF4: No such field");
1398 
1399  if (f->type != kFieldTypeStruct)
1400  throw Common::Exception("GFF4: Field is not of struct type");
1401 
1402  return f->structs;
1403 }
1404 
1405 // --- Struct data reader ---
1406 
1408  const Field *f;
1410  if (!data)
1411  return 0;
1412 
1413  const uint32 count = getListCount(*data, *f);
1414  const uint32 size = getFieldSize(f->type);
1415 
1416  if ((size == 0) || (count == 0))
1417  return 0;
1418 
1419  const size_t dataSize = count * size;
1420  const size_t dataBegin = data->pos();
1421  const size_t dataEnd = data->pos() + dataSize;
1422 
1423  if ((dataBegin >= data->size()) || ((data->size() - dataBegin) < dataSize))
1424  throw Common::Exception("Invalid data offset (%u, %u, %u)",
1425  (uint) dataBegin, (uint) dataSize, (uint) data->size());
1426 
1427  return new Common::SeekableSubReadStream(data, dataBegin, dataEnd);
1428 }
1429 
1430 } // End of namespace Aurora
#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
uint32 stringCount
Number of shared strings (V4.1 only).
Definition: gff4file.h:130
bool getVector3(uint32 field, double &v1, double &v2, double &v3) const
Definition: gff4file.cpp:999
Signed 8bit integer.
Definition: gff4file.h:210
size_t _fieldCount
Definition: gff4file.h:380
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
uint32 getType() const
Return the GFF4&#39;s specific type.
Definition: gff4file.cpp:112
This is a wrapper around SeekableSubReadStream, but it adds non-endian read methods whose endianness ...
Definition: readstream.h:383
#define TypeMan
Shortcut for accessing the file type manager.
Definition: util.h:85
Common::UString getString(uint32 field, Common::Encoding encoding, const Common::UString &def="") const
Return a field string, read from the given encoding.
Definition: gff4file.cpp:949
A class holding an UTF-8 string.
Definition: ustring.h:48
uint32 getDataOffset() const
Definition: gff4file.cpp:300
uint32 label
A numerical label of the field.
Definition: gff4file.h:354
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
int64 getSint(uint32 field, int64 def=0) const
Definition: gff4file.cpp:909
uint64_t uint64
Definition: types.h:206
FORCEINLINE int8 readSByte()
Read a signed byte from the stream and return it.
Definition: readstream.h:101
uint32 getListCount(Common::SeekableSubReadStreamEndian &data, const Field &field) const
Definition: gff4file.cpp:674
uint32 getFieldSize(FieldType type) const
Definition: gff4file.cpp:687
Signed 64bit integer.
Definition: gff4file.h:216
Utility functions to handle files used in BioWare&#39;s Aurora engine.
bool getTalkString(uint32 field, Common::Encoding encoding, uint32 &strRef, Common::UString &str) const
Return a talk string, which is a reference into the TalkTable and an optional direct string...
Definition: gff4file.cpp:967
bool isBigEndian() const
Is the GFF4&#39;s platform natively big endian?
Definition: gff4file.cpp:124
UTF-16 LE (little endian).
Definition: encoding.h:44
size_t pos() const
Obtains the current value of the stream position indicator of the stream.
Definition: readstream.cpp:140
void unregisterStruct(uint64 id)
Definition: gff4file.cpp:282
const GFF4Struct * getGeneric(uint32 field) const
Definition: gff4file.cpp:1378
A GFF (generic file format) V4.0/V4.1 file, found in Dragon Age: Origins, Dragon Age 2 and Sonic Chro...
Definition: gff4file.h:93
bool hasSharedStrings() const
Definition: gff4file.cpp:312
float getFloat(uint32 field, float def=0.0f) const
Definition: gff4file.cpp:937
Utility templates and functions for working with strings and streams.
Exception that provides a stack of explanations.
Definition: error.h:36
A 32bit fixed-point value, found in Sonic.
Definition: gff4file.h:226
size_t size() const
Obtains the total size of the stream, measured in bytes.
Definition: readstream.cpp:144
static void readHeader(Common::ReadStream &stream, uint32 &id, uint32 &version, bool &utf16le)
Read the header out of a stream.
Definition: aurorafile.cpp:53
uint16 structIndex
Index of the field&#39;s struct type (if kFieldTypeStruct).
Definition: gff4file.h:362
void loadStrings()
Definition: gff4file.cpp:245
Signed 32bit integer.
Definition: gff4file.h:214
friend class GFF4Struct
Definition: gff4file.h:201
Common::ScopedPtr< Common::SeekableReadStream > _origStream
Definition: gff4file.h:162
std::vector< const GFF4Struct * > GFF4List
Definition: types.h:453
uint32 structCount
Number of struct templates in this GFF4.
Definition: gff4file.h:129
UTF-16 BE (big endian).
Definition: encoding.h:45
size_t getBytesPerCodepoint(Encoding encoding)
Return the number of bytes per codepoint in this encoding.
Definition: encoding.cpp:366
Handling version V4.0/V4.1 of BioWare&#39;s GFFs (generic file format).
Unsigned 32bit integer.
Definition: gff4file.h:213
Basic exceptions to throw.
Unsigned 64bit integer.
Definition: gff4file.h:215
Common::SeekableReadStream * getData(uint32 field) const
Return the raw data of the field as a Seekable(Sub)ReadStream.
Definition: gff4file.cpp:1407
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
ASCII string, found in Sonic.
Definition: gff4file.h:227
void load(GFF4File &parent, uint32 offset, const GFF4File::StructTemplate &tmplt)
Definition: gff4file.cpp:423
static const uint32 kVersion41
Definition: gff4file.cpp:44
uint32 dataOffset
Offset to the data portion.
Definition: gff4file.h:132
2 unsigned 32bit integers, reference into the TLK table.
Definition: gff4file.h:225
static UString format(const char *s,...) GCC_PRINTF(1
Print formatted data into an UString object, similar to sprintf().
Definition: ustring.cpp:718
size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)
Sets the stream position indicator for the stream.
Definition: readstream.cpp:148
double getDouble(uint32 field, double def=0.0) const
Definition: gff4file.cpp:925
uint16_t uint16
Definition: types.h:202
static const uint32 kVersion40
Definition: gff4file.cpp:43
uint32 stringOffset
Offset to shared strings (V4.1 only).
Definition: gff4file.h:131
uint32 platformID
ID of the platform this GFF4 is for.
Definition: gff4file.h:126
FieldType type
Type of the field.
Definition: gff4file.h:355
uint64 getID() const
Return the struct&#39;s unique ID within the GFF4.
Definition: gff4file.cpp:409
uint32 getDataOffset(bool isReference, uint32 offset) const
Definition: gff4file.cpp:618
void loadStructs(GFF4File &parent, Field &field)
Definition: gff4file.cpp:455
void load(uint32 type)
Definition: gff4file.cpp:143
std::vector< Field > fields
Definition: gff4file.h:153
const GFF4File * _parent
Definition: gff4file.h:373
bool isList
Is this field a singular item or a list?
Definition: gff4file.h:358
FieldType
The type of a GFF4 field.
Definition: gff4file.h:207
bool hasField(uint32 field) const
Does this specific field exist?
Definition: gff4file.cpp:573
double readNintendoFixedPoint(uint32 value, bool sign, uint8 iBits, uint8 fBits)
Read a fixed-point value, in a format used by the Nintendo DS.
Definition: util.cpp:159
uint32 getPlatform() const
Return the platform this GFF4 is for.
Definition: gff4file.cpp:120
uint32 getRefCount() const
Return the number of structs that refer to this struct.
Definition: gff4file.cpp:413
Utility functions for working with differing string encodings.
Encoding
Definition: encoding.h:37
3 IEEE floats, 3D vector.
Definition: gff4file.h:219
const Field * getField(uint32 field) const
Definition: gff4file.cpp:610
uint32 _id
The file&#39;s ID.
Definition: aurorafile.h:77
StackException Exception
Definition: error.h:59
bool getFieldProperties(uint32 field, FieldType &type, uint32 &label, bool &isList) const
Collectively return all field properties in one go.
Definition: gff4file.cpp:596
uint32 _version
The file&#39;s version.
Definition: aurorafile.h:78
static uint64 generateID(uint32 offset, const GFF4File::StructTemplate *tmplt=0)
Definition: gff4file.cpp:556
const StructTemplate & getStructTemplate(uint32 i) const
Definition: gff4file.cpp:304
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
bool isBigEndian() const
Definition: gff4file.cpp:74
Basic reading stream interfaces.
Common::UString getSharedString(uint32 i) const
Definition: gff4file.cpp:316
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
FieldMap _fields
Definition: gff4file.h:382
uint32 type
The specific type this GFF4 describes.
Definition: gff4file.h:127
int64_t int64
Definition: types.h:205
void loadStructs()
Definition: gff4file.cpp:182
uint32 readUint32BE()
Read an unsigned 32-bit word stored in big endian (MSB first) order from the stream and return it...
Definition: readstream.h:166
Common::SeekableSubReadStreamEndian & getStream(uint32 offset) const
Definition: gff4file.cpp:294
StructMap _structs
All actual structs in this GFF4.
Definition: gff4file.h:174
GFF4List structs
List of GFF4Struct (if kFieldTypeStruct).
Definition: gff4file.h:363
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
bool isReference
Is this field a reference (pointer) to another field?
Definition: gff4file.h:359
void loadHeader(uint32 type)
Definition: gff4file.cpp:158
bool getVectorMatrix(uint32 field, std::vector< double > &vectorMatrix) const
Return a field vector or a matrix type as a std::vector of doubles.
Definition: gff4file.cpp:1114
bool getMatrix4x4(uint32 field, double(&m)[16]) const
Definition: gff4file.cpp:1073
const GFF4Struct * getStruct(uint32 field) const
Definition: gff4file.cpp:1360
GFF4File(Common::SeekableReadStream *gff4, uint32 type=0xFFFFFFFF)
Take over this stream and read a GFF4 file out of it.
Definition: gff4file.cpp:79
FieldType getFieldType(uint32 field) const
Return the type of this field, or kFieldTypeNone if it doesn&#39;t exist.
Definition: gff4file.cpp:581
void loadGeneric(GFF4File &parent, Field &field)
Definition: gff4file.cpp:498
uint32 getTypeVersion() const
Return the GFF4&#39;s specific type version.
Definition: gff4file.cpp:116
uint32_t uint32
Definition: types.h:204
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
Definition: strutil.cpp:117
16 IEEE floats, 4x4 matrix in row-major order.
Definition: gff4file.h:224
64bit IEEE float (double).
Definition: gff4file.h:218
SharedStrings _sharedStrings
The shared strings used in V4.1.
Definition: gff4file.h:171
Unsigned 16bit integer.
Definition: gff4file.h:211
FileType
Various file types used by the Aurora engine and found in archives.
Definition: types.h:56
A template of a struct, used when loading a struct.
Definition: gff4file.h:141
bool getBool(uint32 field, bool def=false) const
Definition: gff4file.cpp:921
Common::Encoding getNativeEncoding() const
Return the native UTF-16 encoding according to the GFF4&#39;s platform.
Definition: gff4file.cpp:128
UString readString(SeekableReadStream &stream, Encoding encoding)
Read a string with the given encoding of a stream.
Definition: encoding.cpp:287
StructTemplates _structTemplates
All struct templates in this GFF4.
Definition: gff4file.h:168
4 IEEE floats, Quaternion rotation.
Definition: gff4file.h:221
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
A field in the GFF4 struct.
Definition: gff4file.h:353
Common::ScopedPtr< Common::SeekableSubReadStreamEndian > _stream
Definition: gff4file.h:163
A "generic" field, able to hold any other type.
Definition: gff4file.h:229
4 IEEE floats, 4D vector.
Definition: gff4file.h:220
const std::vector< uint32 > & getFieldLabels() const
Return a list of all field labels in this struct.
Definition: gff4file.cpp:577
const GFF4List & getList(uint32 field) const
Definition: gff4file.cpp:1394
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
Unsigned 8bit integer.
Definition: gff4file.h:209
Signed 16bit integer.
Definition: gff4file.h:212
GFF4Struct * findStruct(uint64 id)
Definition: gff4file.cpp:286
size_t getFieldCount() const
Return the number of fields in this struct.
Definition: gff4file.cpp:569
uint64 getUint(uint32 field, uint64 def=0) const
Definition: gff4file.cpp:897
void clear()
Clear the string&#39;s contents.
Definition: ustring.cpp:236
void registerStruct(uint64 id, GFF4Struct *strct)
Definition: gff4file.cpp:264
const GFF4Struct & getTopLevel() const
Returns the top-level struct.
Definition: gff4file.cpp:135
GFF4Struct * _topLevelStruct
The top-level struct.
Definition: gff4file.h:176
GFF4Struct(GFF4File &parent, uint32 offset, const GFF4File::StructTemplate &tmplt)
Load a GFF4 struct.
Definition: gff4file.cpp:374
void read(Common::SeekableReadStream &gff4, uint32 version)
Definition: gff4file.cpp:48
Interface for a seekable & readable data stream.
Definition: readstream.h:265
uint32 typeVersion
The version of the specific type this GFF4 describes.
Definition: gff4file.h:128
4 IEEE floats, RGBA color.
Definition: gff4file.h:223
byte readByte()
Read an unsigned byte from the stream and return it.
Definition: readstream.h:92
std::vector< uint32 > _fieldLabels
The labels of all fields in this struct.
Definition: gff4file.h:385
bool getVector4(uint32 field, double &v1, double &v2, double &v3, double &v4) const
Definition: gff4file.cpp:1035
Header _header
This GFF4&#39;s header.
Definition: gff4file.h:166
uint32 offset
Offset into the GFF4 data.
Definition: gff4file.h:356
The global resource manager for Aurora resources.
static const uint32 kGFFID
Definition: gff4file.cpp:42
unsigned int uint
Definition: types.h:211
uint32 getLabel() const
Return the struct&#39;s label.
Definition: gff4file.cpp:417
uint32 getVectorMatrixLength(const Field &field, uint32 minLength, uint32 maxLength) const
Definition: gff4file.cpp:653
bool isGeneric
Is this field found in a generic?
Definition: gff4file.h:360