xoreos  0.0.5
keyfile.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 "src/common/util.h"
30 #include "src/common/strutil.h"
31 #include "src/common/error.h"
32 #include "src/common/readstream.h"
33 #include "src/common/encoding.h"
34 
35 #include "src/aurora/keyfile.h"
36 
37 static const uint32 kKEYID = MKTAG('K', 'E', 'Y', ' ');
38 static const uint32 kVersion1 = MKTAG('V', '1', ' ', ' ');
39 static const uint32 kVersion11 = MKTAG('V', '1', '.', '1');
40 
41 namespace Aurora {
42 
44  load(key);
45 }
46 
48 }
49 
51  readHeader(key);
52 
53  if (_id != kKEYID)
54  throw Common::Exception("Not a KEY file (%s)", Common::debugTag(_id).c_str());
55 
56  if ((_version != kVersion1) && (_version != kVersion11))
57  throw Common::Exception("Unsupported KEY file version %s", Common::debugTag(_version).c_str());
58 
59  uint32 bifCount = key.readUint32LE();
60  uint32 resCount = key.readUint32LE();
61 
62  _bifs.reserve(bifCount);
63  _resources.reserve(resCount);
64 
65  // Version 1.1 has some NULL bytes here
66  if (_version == kVersion11)
67  key.skip(4);
68 
69  uint32 offFileTable = key.readUint32LE();
70  uint32 offResTable = key.readUint32LE();
71 
72  key.skip( 8); // Build year and day
73  key.skip(32); // Reserved
74 
75  try {
76 
77  _bifs.resize(bifCount);
78  readBIFList(key, offFileTable);
79 
80  _resources.resize(resCount);
81  readResList(key, offResTable);
82 
83  } catch (Common::Exception &e) {
84  e.add("Failed reading KEY file");
85  throw;
86  }
87 
88 }
89 
91  key.seek(offset);
92 
93  for (BIFList::iterator bif = _bifs.begin(); bif != _bifs.end(); ++bif) {
94  key.skip(4); // File size of the bif
95 
96  uint32 nameOffset = key.readUint32LE();
97  uint32 nameSize = 0;
98 
99  // nameSize is expanded to 4 bytes in 1.1 and the location is dropped
100  if (_version == kVersion11) {
101  nameSize = key.readUint32LE();
102  } else {
103  nameSize = key.readUint16LE();
104  key.skip(2); // Location of the bif (HD, CD, ...)
105  }
106 
107  const size_t curPos = key.seek(nameOffset);
108 
109  *bif = Common::readStringFixed(key, Common::kEncodingASCII, nameSize);
110 
111  key.seek(curPos);
112 
113  bif->replaceAll('\\', '/');
114  if (bif->beginsWith("/"))
115  bif->erase(bif->begin());
116  }
117 }
118 
120  key.seek(offset);
121 
122  for (ResourceList::iterator res = _resources.begin(); res != _resources.end(); ++res) {
123  res->name = Common::readStringFixed(key, Common::kEncodingASCII, 16);
124  res->type = (FileType) key.readUint16LE();
125 
126  uint32 id = key.readUint32LE();
127 
128  // The new flags field holds the bifIndex now. The rest contains fixed
129  // resource info.
130  if (_version == kVersion11) {
131  uint32 flags = key.readUint32LE();
132  res->bifIndex = (flags & 0xFFF00000) >> 20;
133  } else
134  res->bifIndex = id >> 20;
135 
136  // TODO: Fixed resources?
137  res->resIndex = id & 0xFFFFF;
138  }
139 }
140 
142  return _bifs;
143 }
144 
146  return _resources;
147 }
148 
149 } // End of namespace Aurora
#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
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
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
std::vector< Common::UString > BIFList
Definition: keyfile.h:82
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
KEYFile(Common::SeekableReadStream &key)
Definition: keyfile.cpp:43
void readResList(Common::SeekableReadStream &key, uint32 offset)
Definition: keyfile.cpp:119
const ResourceList & getResources() const
Return a list of all containing resources.
Definition: keyfile.cpp:145
ResourceList _resources
All containing resources.
Definition: keyfile.h:95
static const uint32 kVersion11
Definition: keyfile.cpp:39
Utility templates and functions for working with strings and streams.
Exception that provides a stack of explanations.
Definition: error.h:36
static void readHeader(Common::ReadStream &stream, uint32 &id, uint32 &version, bool &utf16le)
Read the header out of a stream.
Definition: aurorafile.cpp:53
Handling BioWare&#39;s KEYs (resource index files).
Basic exceptions to throw.
Utility templates and functions.
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
Utility functions for working with differing string encodings.
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
static const uint32 kKEYID
Definition: keyfile.cpp:37
Basic reading stream interfaces.
const BIFList & getBIFs() const
Return a list of all managed bifs.
Definition: keyfile.cpp:141
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
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
BIFList _bifs
All managed bifs.
Definition: keyfile.h:94
void load(Common::SeekableReadStream &key)
Definition: keyfile.cpp:50
FileType
Various file types used by the Aurora engine and found in archives.
Definition: types.h:56
static const uint32 kVersion1
Definition: keyfile.cpp:38
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 readBIFList(Common::SeekableReadStream &key, uint32 offset)
Definition: keyfile.cpp:90
Interface for a seekable & readable data stream.
Definition: readstream.h:265
std::vector< Resource > ResourceList
Definition: keyfile.h:81