-
Notifications
You must be signed in to change notification settings - Fork 1
/
RWBinaryStream.hpp
366 lines (301 loc) · 8.04 KB
/
RWBinaryStream.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
// https://github.com/rwengine/openrw/blob/master/rwcore/loaders/RWBinaryStream.hpp
#ifndef _LIBRW_RWBINARYSTREAM_HPP_
#define _LIBRW_RWBINARYSTREAM_HPP_
#include <glm/gtc/type_precision.hpp>
#include <glm/mat3x3.hpp>
#include <glm/vec3.hpp>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
//Based on https://gist.github.com/socantre/3472964
template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
Dest dest;
std::memcpy(&dest, &source, sizeof(Dest));
return dest;
}
/**
* @brief Class for working with RenderWare binary streams.
*
* Stream files are split into chunks, each of which may have numerous
* child chunks (in particular, the "struct" chunk which is used to store
* data relating to the parent chunk).
*/
class RWBStream {
const char* _data;
std::ptrdiff_t _size;
const char* _dataCur;
const char* _nextChunk;
std::uint32_t _chunkVersion;
size_t _currChunkSz;
public:
typedef std::uint32_t ChunkID;
RWBStream(const char* data, size_t size)
: _data(data), _size(size), _dataCur(data), _nextChunk(data) {
}
/**
* Moves the stream to the next chunk and returns it's ID
*/
ChunkID getNextChunk() {
// Check that there's any data left
if ((_dataCur - _data) >= _size) return 0;
// _nextChunk is initally = to _data, making this a non-op
_dataCur = _nextChunk;
ChunkID id = bit_cast<std::uint32_t>(*_dataCur);
_dataCur += sizeof(ChunkID);
_currChunkSz = bit_cast<std::uint32_t>(*_dataCur);
_dataCur += sizeof(std::uint32_t);
_chunkVersion = bit_cast<std::uint32_t>(*_dataCur);
_dataCur += sizeof(std::uint32_t);
_nextChunk = _dataCur + _currChunkSz;
return id;
}
const char* getCursor() const {
return _dataCur;
}
size_t getCurrentChunkSize() const {
return _currChunkSz;
}
std::uint32_t getChunkVersion() const {
return _chunkVersion;
}
/**
* @brief Returns a new stream for the data inside this one.
*/
RWBStream getInnerStream() const {
return {_dataCur, _currChunkSz};
}
};
/**
* @file rwbinarystream.h
* Deprecated RenderWare binary stream interface.
* Contains the structs for the shared Render Ware binary stream data.
* Many thanks to
* http://www.gtamodding.com/index.php?title=RenderWare_binary_stream_file
*/
namespace RW {
enum {
SID_Struct = 0x0001,
SID_String = 0x0002,
SID_Extension = 0x0003,
SID_Texture = 0x0006,
SID_Material = 0x0007,
SID_MaterialList = 0x0008,
SID_FrameList = 0x000E,
SID_Geometry = 0x000F,
SID_Clump = 0x0010,
SID_Atomic = 0x0014,
SID_TextureNative = 0x0015,
SID_TextureDictionary = 0x0016,
SID_GeometryList = 0x001A,
SID_HAnimPLG = 0x011E,
SID_BinMeshPLG = 0x50E,
SID_NodeName = 0x0253F2FE
};
typedef glm::vec3 BSTVector3;
typedef glm::mat3 BSTMatrix;
struct BSSectionHeader {
uint32_t id;
uint32_t size;
uint32_t versionid;
};
struct BSExtension {};
struct BSFrameList {
uint32_t numframes;
};
struct BSClump {
uint32_t numatomics;
};
struct BSStruct {
uint32_t id; // = 0x0001
};
struct BSGeometryList {
uint32_t numgeometry;
};
struct BSGeometry {
uint16_t flags;
uint8_t numuvs;
uint8_t geomflags;
uint32_t numtris;
uint32_t numverts;
uint32_t numframes;
enum {
IsTriangleStrip = 0x1,
VertexTranslation = 0x2,
TexCoords1 = 0x4,
VertexColors = 0x8,
StoreNormals = 0x16,
DynamicVertexLighting = 0x32,
ModuleMaterialColor = 0x64,
TexCoords2 = 0x128
};
};
typedef glm::u8vec4 BSColor;
struct BSGeometryColor {
BSColor ambient;
BSColor diffuse;
BSColor specular;
};
struct BSGeometryUV {
float u;
float v;
};
struct BSGeometryTriangle {
uint16_t first;
uint16_t second;
uint16_t attrib; // Who designed this nonsense.
uint16_t third;
};
struct BSGeometryBounds {
BSTVector3 center;
float radius;
uint32_t positions;
uint32_t normals;
};
struct BSMaterialList {
uint32_t nummaterials;
};
struct BSMaterial {
uint32_t unknown;
BSColor color;
uint32_t alsounknown;
uint32_t numtextures;
float ambient;
float specular;
float diffuse;
};
struct BSTexture {
uint16_t filterflags;
uint16_t unknown;
};
struct BSBinMeshPLG {
uint32_t facetype;
uint32_t numsplits;
uint32_t numfaces;
};
struct BSMaterialSplit {
uint32_t numverts;
uint32_t index;
};
/**
* Texture Dictionary Structures (TXD)
*/
struct BSTextureDictionary {
uint16_t numtextures;
uint16_t unknown;
};
struct BSTextureNative {
uint32_t platform;
uint16_t filterflags;
uint8_t wrapV;
uint8_t wrapU;
char diffuseName[32];
char alphaName[32];
uint32_t rasterformat;
uint32_t alpha;
uint16_t width;
uint16_t height;
uint8_t bpp;
uint8_t nummipmaps;
uint8_t rastertype;
uint8_t dxttype;
uint32_t datasize;
enum {
FILTER_NONE = 0x0,
FILTER_NEAREST = 0x01,
FILTER_LINEAR = 0x02,
FILTER_MIP_NEAREST = 0x03,
FILTER_MIP_LINEAR = 0x04,
FILTER_LINEAR_MIP_NEAREST = 0x05,
FILTER_LINEAR_MIP_LINEAR = 0x06,
FILTER_MYSTERY_OPTION = 0x1101
};
enum {
WRAP_NONE = 0x00,
WRAP_WRAP = 0x01,
WRAP_MIRROR = 0x02,
WRAP_CLAMP = 0x03
};
enum {
FORMAT_DEFAULT = 0x0000, // helpful
FORMAT_1555 = 0x0100, // Alpha 1, RGB 5 b
FORMAT_565 = 0x0200, // 5r6g5b
FORMAT_4444 = 0x0300, // 4 bits each
FORMAT_LUM8 = 0x0400, // Greyscale
FORMAT_8888 = 0x0500, // 8 bits each
FORMAT_888 = 0x0600, // RGB 8 bits each
FORMAT_555 = 0x0A00, // do not use
FORMAT_EXT_AUTO_MIPMAP = 0x1000, // Generate mipmaps
FORMAT_EXT_PAL8 = 0x2000, // 256 colour palette
FORMAT_EXT_PAL4 = 0x4000, // 16 color palette
FORMAT_EXT_MIPMAP = 0x8000 // Mipmaps included
};
};
struct BSPaletteData {
uint32_t palette[256];
uint32_t rastersize;
};
/**
* Structure object
*/
class BinaryStreamSection {
public:
/**
* Data pointer
*/
const char* data;
/**
* Offset of this section in the data
*/
size_t offset;
/**
* The BSSectionHeader for the section
*/
BSSectionHeader header;
/**
* Structure header
*/
const BSSectionHeader* structure;
BinaryStreamSection(const char* data, size_t offset = 0)
: data(data), offset(offset), structure(nullptr) {
header = *reinterpret_cast<const BSSectionHeader*>(data + offset);
if (header.size > sizeof(structure)) {
structure = reinterpret_cast<const BSSectionHeader*>(
data + offset + sizeof(BSSectionHeader));
if (structure->id != SID_Struct) {
structure = nullptr;
}
}
}
template <class T>
T readStructure() {
return *reinterpret_cast<const T*>(data + offset +
sizeof(BSSectionHeader) * 2);
}
template <class T>
T& readSubStructure(size_t internalOffset) {
return *reinterpret_cast<T*>(data + offset + sizeof(BSSectionHeader) +
internalOffset);
}
template <class T>
T readRaw(size_t internalOffset) {
return *reinterpret_cast<T*>(data + offset + internalOffset);
}
const char* raw() {
return data + offset + sizeof(BSSectionHeader);
}
bool hasMoreData(size_t length) {
return (length) < (header.size);
}
BinaryStreamSection getNextChildSection(size_t& internalOffset) {
size_t realOffset = internalOffset;
assert(realOffset < header.size);
BinaryStreamSection sec(data,
offset + sizeof(BSSectionHeader) + realOffset);
internalOffset += sec.header.size + sizeof(BSSectionHeader);
return sec;
}
};
}
#endif