xoreos  0.0.5
herffile.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 #include <cassert>
26 
27 #include "src/common/util.h"
28 #include "src/common/error.h"
29 #include "src/common/filepath.h"
31 #include "src/common/encoding.h"
32 #include "src/common/hash.h"
33 
34 #include "src/aurora/herffile.h"
35 #include "src/aurora/util.h"
36 
37 namespace Aurora {
38 
39 HERFFile::HERFFile(Common::SeekableReadStream *herf) : _herf(herf), _dictOffset(0xFFFFFFFF), _dictSize(0) {
40  assert(_herf);
41 
42  load(*_herf);
43 }
44 
46 }
47 
49  uint32 magic = herf.readUint32LE();
50  if (magic != 0x00F1A5C0)
51  throw Common::Exception("Invalid HERF file (0x%08X)", magic);
52 
53  uint32 resCount = herf.readUint32LE();
54 
55  _resources.resize(resCount);
56  _iResources.resize(resCount);
57 
58  try {
59 
60  searchDictionary(herf, resCount);
61  readResList(herf);
62 
63  } catch (Common::Exception &e) {
64  e.add("Failed reading HERF file");
65  throw;
66  }
67 }
68 
70  const uint32 dictHash = Common::hashStringDJB2("erf.dict");
71 
72  const size_t pos = herf.pos();
73 
74  for (uint32 i = 0; i < resCount; i++) {
75  uint32 hash = herf.readUint32LE();
76  if (hash == dictHash) {
77  _dictSize = herf.readUint32LE();
78  _dictOffset = herf.readUint32LE();
79  break;
80  }
81 
82  herf.skip(8);
83  }
84 
85  herf.seek(pos);
86 }
87 
88 void HERFFile::readDictionary(Common::SeekableReadStream &herf, std::map<uint32, Common::UString> &dict) {
89  if (_dictOffset == 0xFFFFFFFF)
90  return;
91 
92  size_t pos = herf.pos();
93 
94  herf.seek(_dictOffset);
95 
96  uint32 magic = herf.readUint32LE();
97  if (magic != 0x00F1A5C0)
98  throw Common::Exception("Invalid HERF dictionary (0x%08X)", magic);
99 
100  uint32 hashCount = herf.readUint32LE();
101 
102  for (uint32 i = 0; i < hashCount; i++) {
103  if ((size_t)herf.pos() >= (_dictOffset + _dictSize))
104  break;
105 
106  uint32 hash = herf.readUint32LE();
107  dict[hash] = Common::readStringFixed(herf, Common::kEncodingASCII, 128).toLower();
108  }
109 
110  herf.seek(pos);
111 }
112 
114  std::map<uint32, Common::UString> dict;
115  readDictionary(herf, dict);
116 
117  uint32 index = 0;
118  ResourceList::iterator res = _resources.begin();
119  IResourceList::iterator iRes = _iResources.begin();
120  for (; (res != _resources.end()) && (iRes != _iResources.end()); ++index, ++res, ++iRes) {
121  res->index = index;
122 
123  res->hash = herf.readUint32LE();
124 
125  iRes->size = herf.readUint32LE();
126  iRes->offset = herf.readUint32LE();
127 
128  if (iRes->offset >= (uint32)herf.size())
129  throw Common::Exception("HERFFile::readResList(): Resource goes beyond end of file");
130 
131  std::map<uint32, Common::UString>::const_iterator name = dict.find(res->hash);
132  if (name != dict.end()) {
133  res->name = Common::FilePath::getStem(name->second);
134  res->type = TypeMan.getFileType(name->second);
135  }
136 
137  if ((iRes->offset == _dictOffset) && (iRes->size == _dictSize)) {
138  res->name = "erf";
139  res->type = kFileTypeDICT;
140  }
141  }
142 }
143 
145  return _resources;
146 }
147 
149  if (index >= _iResources.size())
150  throw Common::Exception("Resource index out of range (%u/%u)", index, (uint)_iResources.size());
151 
152  return _iResources[index];
153 }
154 
156  return getIResource(index).size;
157 }
158 
160  const IResource &res = getIResource(index);
161 
162  if (tryNoCopy)
163  return new Common::SeekableSubReadStream(_herf.get(), res.offset, res.offset + res.size);
164 
165  _herf->seek(res.offset);
166 
167  return _herf->readStream(res.size);
168 }
169 
171  return Common::kHashDJB2;
172 }
173 
174 } // End of namespace Aurora
uint32 _dictOffset
The offset of the dict file (if available).
Definition: herffile.h:88
static uint32 hashStringDJB2(const UString &string)
Definition: hash.h:51
Common::HashAlgo getNameHashAlgo() const
Return with which algorithm the name is hashed.
Definition: herffile.cpp:170
Common::SeekableReadStream * getResource(uint32 index, bool tryNoCopy=false) const
Return a stream of the resource&#39;s contents.
Definition: herffile.cpp:159
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
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
#define TypeMan
Shortcut for accessing the file type manager.
Definition: util.h:85
uint32 getResourceSize(uint32 index) const
Return the size of a resource.
Definition: herffile.cpp:155
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
Internal resource information.
Definition: herffile.h:73
Implementing the reading stream interfaces for plain memory blocks.
djb2 hash function by Daniel J. Bernstein.
Definition: hash.h:39
Utility functions to handle files used in BioWare&#39;s Aurora engine.
Utility hash functions.
Exception that provides a stack of explanations.
Definition: error.h:36
const IResource & getIResource(uint32 index) const
Definition: herffile.cpp:148
Basic exceptions to throw.
Utility templates and functions.
Common::ScopedPtr< Common::SeekableReadStream > _herf
Definition: herffile.h:80
void readDictionary(Common::SeekableReadStream &herf, std::map< uint32, Common::UString > &dict)
Definition: herffile.cpp:88
std::list< Resource > ResourceList
Definition: archive.h:57
const ResourceList & getResources() const
Return the list of resources.
Definition: herffile.cpp:144
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
BioWare&#39;s HERF (hashed ERF) file parsing.
Utility functions for working with differing string encodings.
HashAlgo
The algorithm used for hashing.
Definition: hash.h:37
StackException Exception
Definition: error.h:59
HERFFile(Common::SeekableReadStream *herf)
Take over this stream and read an HERF file out of it.
Definition: herffile.cpp:39
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
void readResList(Common::SeekableReadStream &herf)
Definition: herffile.cpp:113
ResourceList _resources
External list of resource names and types.
Definition: herffile.h:83
void load(Common::SeekableReadStream &herf)
Definition: herffile.cpp:48
uint32 size
The resource&#39;s size.
Definition: herffile.h:75
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
IResourceList _iResources
Internal list of resource offsets and sizes.
Definition: herffile.h:86
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
static UString getStem(const UString &p)
Return a file name&#39;s stem.
Definition: filepath.cpp:87
UString toLower() const
Return a lowercased copy of the string.
Definition: ustring.cpp:481
uint32_t uint32
Definition: types.h:204
uint32 offset
The offset of the resource within the HERF.
Definition: herffile.h:74
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
HERF file name -> hashes dictionary.
Definition: types.h:256
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
Interface for a seekable & readable data stream.
Definition: readstream.h:265
uint32 _dictSize
The size of the dict file (if available).
Definition: herffile.h:89
Utility class for manipulating file paths.
unsigned int uint
Definition: types.h:211
void searchDictionary(Common::SeekableReadStream &herf, uint32 resCount)
Definition: herffile.cpp:69