• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PredatorCZ / RevilLib / 185

21 Apr 2026 07:59PM UTC coverage: 8.612% (-2.1%) from 10.756%
185

push

github

PredatorCZ
update sdl

3 of 459 new or added lines in 1 file covered. (0.65%)

2404 existing lines in 10 files now uncovered.

762 of 8848 relevant lines covered (8.61%)

4773.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.09
/src/mtf_mod/serialize.cpp
1
/*  Revil Format Library
2
    Copyright(C) 2017-2026 Lukas Cone
3

4
    This program is free software : you can redistribute it and / or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation, either version 3 of the License, or
7
    (at your option) any later version.
8

9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
12
    GNU General Public License for more details.
13

14
    You should have received a copy of the GNU General Public License
15
    along with this program.If not, see <https://www.gnu.org/licenses/>.
16
*/
17

18
#include "header.hpp"
19
#include "pugixml.hpp"
20
#include "revil/xfs.hpp"
21
#include "spike/io/binreader.hpp"
22
#include "spike/io/binwritter.hpp"
23
#include "spike/util/endian.hpp"
24
#include "traits.hpp"
25
#include <map>
26

27
using namespace revil;
28

29
static constexpr uint32 MODID = CompileFourCC("MOD");
30
static constexpr uint32 DOMID = CompileFourCC("\0DOM");
31
static constexpr uint32 RMDID = CompileFourCC("\0DMR");
32

UNCOV
33
template <class traits> void MODInner<traits>::Reflect(bool swap) {
×
UNCOV
34
  for (size_t i = 0; i < bones.size(); i++) {
×
35
    const bool isRoot =
UNCOV
36
        sizeof(bones[i].parentIndex) == 1 && bones[i].parentIndex == 0xff;
×
37
    MODBone bne{
×
38
        .index = bones[i].index,
×
39
        .parentIndex = uint16(isRoot ? 0xffff : bones[i].parentIndex),
40
    };
41
    this->simpleBones.emplace_back(bne);
×
42
  }
43

UNCOV
44
  this->primitives.reserve(meshes.size());
×
45
  if (swap) {
×
UNCOV
46
    for (size_t i = 0; i < meshes.size(); i++) {
×
UNCOV
47
      this->primitives.emplace_back(meshes[i].ReflectBE(*this));
×
48
    }
49
  } else {
50
    for (size_t i = 0; i < meshes.size(); i++) {
×
51
      this->primitives.emplace_back(meshes[i].ReflectLE(*this));
×
52
    }
53
  }
54

55
  for (auto &r : skinRemaps) {
×
UNCOV
56
    this->skins.emplace_back(r.bones, r.count);
×
57
  }
58

59
  for (auto &m : this->materials) {
×
60
    this->materialRefs.emplace_back(&m);
×
61
  }
62
}
63

×
64
template <class material_type>
×
65
void MODMaterialProxy<material_type>::Write(BinWritterRef wr) const {
66
  auto main_ = main;
×
UNCOV
67
  main_.baseTextureIndex++;
×
UNCOV
68
  main_.normalTextureIndex++;
×
69
  main_.maskTextureIndex++;
70
  main_.lightTextureIndex++;
UNCOV
71
  main_.shadowTextureIndex++;
×
72
  main_.additionalTextureIndex++;
73
  main_.cubeMapTextureIndex++;
UNCOV
74
  main_.heightTextureIndex++;
×
75
  main_.glossTextureIndex++;
×
76
  wr.Write(main_);
×
77
}
×
78

79
template <class material_type>
80
void MODMaterialProxy<material_type>::Read(BinReaderRef_e rd) {
×
UNCOV
81
  rd.Read(main);
×
82
  if constexpr (!std::is_same_v<material_type, MODMaterialHash> &&
83
                !std::is_same_v<material_type, MODMaterialName>) {
84
    main.baseTextureIndex--;
85
    main.normalTextureIndex--;
×
86
    main.maskTextureIndex--;
×
87
    main.lightTextureIndex--;
88
    main.shadowTextureIndex--;
89
    main.additionalTextureIndex--;
×
90
    main.cubeMapTextureIndex--;
×
91
    main.heightTextureIndex--;
92
    main.glossTextureIndex--;
UNCOV
93
  }
×
94
}
×
95

UNCOV
96
#pragma region Endian Swappers
×
UNCOV
97

×
98
template <> void FByteswapper(MODBoneV1 &self, bool) {
×
99
  FByteswapper(self.absolutePosition);
100
  FByteswapper(self.parentDistance);
101
}
×
102

103
template <> void FByteswapper(MODBoneV1_5 &self, bool) {
104
  FByteswapper(self.absolutePosition);
×
UNCOV
105
  FByteswapper(self.parentDistance);
×
UNCOV
106
  FByteswapper(self.furthestVertexDistance);
×
107
}
×
108

109
template <> void FByteswapper(MODBoneV2 &self, bool) {
110
  FByteswapper(self.absolutePosition);
×
111
  FByteswapper(self.parentDistance);
×
112
  FByteswapper(self.furthestVertexDistance);
113
  FByteswapper(self.index);
114
}
115

×
UNCOV
116
template <> void FByteswapper(MtAABB &self, bool) {
×
117
  FByteswapper(self.min);
118
  FByteswapper(self.max);
119
}
×
120

×
121
template <> void FByteswapper(MtOBB &self, bool) {
122
  FByteswapper(self.transform);
UNCOV
123
  FByteswapper(self.extents);
×
124
}
×
125

UNCOV
126
template <> void FByteswapper(MODEnvelope &self, bool) {
×
UNCOV
127
  FByteswapper(self.boundingSphere);
×
UNCOV
128
  FByteswapper(self.boneIndex);
×
129
  FByteswapper(self.aabb);
130
  FByteswapper(self.obb);
UNCOV
131
}
×
132

133
template <> void FByteswapper(MODGroup &self, bool) {
134
  FByteswapper(self.boundingSphere);
×
UNCOV
135
  FByteswapper(self.index);
×
UNCOV
136
}
×
UNCOV
137

×
138
template <> void FByteswapper(MODMetaData &self, bool) {
139
  FByteswapper(self.lightGroup);
UNCOV
140
  FByteswapper(self.lowDistance);
×
UNCOV
141
  FByteswapper(self.middleDistance);
×
142
}
143

144
template <> void FByteswapper(MODMetaDataV2 &self, bool) {
145
  FByteswapper(static_cast<MODMetaData &>(self));
×
146
  FByteswapper(self.numEnvelopes);
×
147
}
148

UNCOV
149
template <> void FByteswapper(MODSkinRemap<24> &self, bool) {
×
150
  FByteswapper(self.count);
×
151
}
152

153
template <> void FByteswapper(MODSkinRemap<32> &self, bool) {
×
154
  FByteswapper(self.count);
×
155
}
156

×
UNCOV
157
template <> void FByteswapper(MODSkinRemap<64> &self, bool) {
×
UNCOV
158
  FByteswapper(self.count);
×
159
}
160

UNCOV
161
template <> void FByteswapper(MODHeaderCommon &self, bool) {
×
162
  FByteswapper(self.id);
163
  FByteswapper(self.version);
164
  FByteswapper(self.numBones);
×
165
  FByteswapper(self.numMeshes);
×
UNCOV
166
  FByteswapper(self.numMaterials);
×
UNCOV
167
  FByteswapper(self.numVertices);
×
168
  FByteswapper(self.numIndices);
169
  FByteswapper(self.numEdges);
UNCOV
170
}
×
171

×
172
template <> void FByteswapper(MODHeaderX99 &self, bool) {
173
  FByteswapper(static_cast<MODHeaderCommon &>(self));
174
  FByteswapper(self.vertexBufferSize);
UNCOV
175
  FByteswapper(self.unkBufferSize);
×
UNCOV
176
  FByteswapper(self.numTextures);
×
177
  FByteswapper(self.numGroups);
178
  FByteswapper(self.numBoneMaps);
UNCOV
179
  FByteswapper(self.bones);
×
180
  FByteswapper(self.groups);
×
181
  FByteswapper(self.textures);
182
  FByteswapper(self.meshes);
UNCOV
183
  FByteswapper(self.vertexBuffer);
×
UNCOV
184
  FByteswapper(self.unkBuffer);
×
185
  FByteswapper(self.indices);
UNCOV
186
}
×
UNCOV
187

×
188
template <> void FByteswapper(MODHeaderXC5 &self, bool) {
×
189
  FByteswapper(static_cast<MODHeaderCommon &>(self));
190
  FByteswapper(self.vertexBufferSize);
191
  FByteswapper(self.numTextures);
×
192
  FByteswapper(self.numGroups);
193
  FByteswapper(self.bones);
194
  FByteswapper(self.groups);
×
195
  FByteswapper(self.textures);
×
UNCOV
196
  FByteswapper(self.meshes);
×
UNCOV
197
  FByteswapper(self.vertexBuffer);
×
198
  FByteswapper(self.indices);
199
}
200

×
UNCOV
201
template <> void FByteswapper(MODHeaderXDx32 &self, bool) {
×
202
  FByteswapper(static_cast<MODHeaderCommon &>(self));
203
  FByteswapper(self.vertexBufferSize);
204
  FByteswapper(self.numTextures);
UNCOV
205
  FByteswapper(self.numGroups);
×
206
  FByteswapper(self.bones);
×
207
  FByteswapper(self.groups);
208
  FByteswapper(self.materialHashes);
209
  FByteswapper(self.meshes);
×
UNCOV
210
  FByteswapper(self.vertexBuffer);
×
211
  FByteswapper(self.indices);
212
  FByteswapper(self.dataEnd);
213
}
×
UNCOV
214

×
215
template <> void FByteswapper(MODHeaderX70 &self, bool) {
216
  FByteswapper(static_cast<MODHeaderCommon &>(self));
×
217
  FByteswapper(self.vertexBufferSize);
×
UNCOV
218
  FByteswapper(self.unkBufferSize);
×
219
  FByteswapper(self.numTextures);
220
  FByteswapper(self.bones);
UNCOV
221
  FByteswapper(self.textures);
×
222
  FByteswapper(self.meshes);
223
  FByteswapper(self.vertexBuffer);
224
  FByteswapper(self.unkBuffer);
×
225
  FByteswapper(self.indices);
×
226
}
×
UNCOV
227

×
228
template <> void FByteswapper(MODHeaderXE5 &self, bool) {
229
  FByteswapper(static_cast<MODHeaderCommon &>(self));
230
  FByteswapper(self.vertexBufferSize);
×
UNCOV
231
  FByteswapper(self.numTextures);
×
232
  FByteswapper(self.numGroups);
233
  FByteswapper(self.numSkins);
234
  FByteswapper(self.bones);
235
  FByteswapper(self.groups);
×
UNCOV
236
  FByteswapper(self.materials);
×
237
  FByteswapper(self.meshes);
238
  FByteswapper(self.vertexBuffer);
239
  FByteswapper(self.indices);
×
UNCOV
240
}
×
241

242
template <> void FByteswapper(MODHeaderX170 &self, bool) {
UNCOV
243
  FByteswapper(static_cast<MODHeaderCommon &>(self));
×
244
  FByteswapper(self.vertexBufferSize);
×
245
  FByteswapper(self.unkBufferSize);
UNCOV
246
  FByteswapper(self.numTextures);
×
247
  FByteswapper(self.bones);
×
248
  FByteswapper(self.textures);
×
249
  FByteswapper(self.meshes);
250
  FByteswapper(self.vertexBuffer);
251
  FByteswapper(self.unkBuffer);
×
252
  FByteswapper(self.indices);
253
}
UNCOV
254

×
255
template <> void FByteswapper(MODHeaderX21 &self, bool) {
×
UNCOV
256
  FByteswapper(static_cast<MODHeaderCommon &>(self));
×
UNCOV
257
  FByteswapper(self.vertexBufferSize);
×
258
  FByteswapper(self.numGroups);
259
  FByteswapper(self.numSkins);
260
  FByteswapper(self.bones);
×
261
  FByteswapper(self.groups);
×
262
  FByteswapper(self.materials);
263
  FByteswapper(self.meshes);
264
  FByteswapper(self.vertexBuffer);
265
  FByteswapper(self.indices);
×
UNCOV
266
  FByteswapper(self.unkSize);
×
267
  FByteswapper(self.unkData);
268
}
269

×
270
template <> void FByteswapper(MODMaterialX70 &self, bool way) {
×
271
  FByteswapper(self.pshData);
272
  FByteswapper(self.vshData, way);
273
  FByteswapper(self.baseTextureIndex);
×
274
  FByteswapper(self.normalTextureIndex);
×
275
  FByteswapper(self.maskTextureIndex);
276
  FByteswapper(self.lightTextureIndex);
×
UNCOV
277
  FByteswapper(self.shadowTextureIndex);
×
UNCOV
278
  FByteswapper(self.additionalTextureIndex);
×
279
  FByteswapper(self.cubeMapTextureIndex);
280
  FByteswapper(self.heightTextureIndex);
UNCOV
281
  FByteswapper(self.glossTextureIndex);
×
282
  FByteswapper(self.transparency);
283
  FByteswapper(self.fresnelFactor);
UNCOV
284
  FByteswapper(self.lightMapScale);
×
285
  FByteswapper(self.detailFactor);
×
286
  FByteswapper(self.transmit);
×
287
  FByteswapper(self.paralax);
×
288
  FByteswapper(self.blendState);
289
}
290

×
UNCOV
291
template <> void FByteswapper(MODMaterialX170 &self, bool) {
×
292
  FByteswapper(self.pshData);
293
  FByteswapper(self.vshData);
294
  FByteswapper(self.baseTextureIndex);
295
  FByteswapper(self.normalTextureIndex);
×
296
  FByteswapper(self.maskTextureIndex);
×
297
  FByteswapper(self.lightTextureIndex);
298
  FByteswapper(self.shadowTextureIndex);
299
  FByteswapper(self.additionalTextureIndex);
×
300
  FByteswapper(self.cubeMapTextureIndex);
×
301
  FByteswapper(self.heightTextureIndex);
302
  FByteswapper(self.glossTextureIndex);
UNCOV
303
  FByteswapper(self.transparency);
×
304
  FByteswapper(self.fresnelFactor);
×
305
  FByteswapper(self.lightMapScale);
UNCOV
306
  FByteswapper(self.detailFactor);
×
UNCOV
307
  FByteswapper(self.transmit);
×
308
  FByteswapper(self.paralax);
×
309
  FByteswapper(self.blendState);
310
}
311

×
312
template <> void FByteswapper(MODMaterialXC5 &self, bool way) {
313
  FByteswapper(self.pshData, way);
314
  FByteswapper(self.vshData, way);
×
UNCOV
315
  FByteswapper(self.baseTextureIndex);
×
UNCOV
316
  FByteswapper(self.normalTextureIndex);
×
317
  FByteswapper(self.maskTextureIndex);
×
318
  FByteswapper(self.lightTextureIndex);
319
  FByteswapper(self.shadowTextureIndex);
320
  FByteswapper(self.additionalTextureIndex);
×
321
  FByteswapper(self.cubeMapTextureIndex);
×
322
  FByteswapper(self.heightTextureIndex);
323
  FByteswapper(self.glossTextureIndex);
324
  FByteswapper(self.transparency);
325
  FByteswapper(self.fresnelFactor);
×
UNCOV
326
  FByteswapper(self.lightMapScale);
×
327
  FByteswapper(self.detailFactor);
328
  FByteswapper(self.transmit);
329
  FByteswapper(self.paralax);
×
330
  FByteswapper(self.blendState);
×
331
}
332

UNCOV
333
template <> void FByteswapper(MODMaterialHash &self, bool) {
×
334
  FByteswapper(self.hash);
×
335
}
UNCOV
336

×
UNCOV
337
template <> void FByteswapper(MODMeshX99 &self, bool) {
×
UNCOV
338
  FByteswapper(self.groupIndex);
×
339
  FByteswapper(self.materialIndex);
340
  FByteswapper(self.numVertices);
UNCOV
341
  FByteswapper(self.endIndex);
×
342
  FByteswapper(self.vertexStart);
343
  FByteswapper(self.vertexStreamOffset);
344
  FByteswapper(self.vertexStream2Offset);
×
UNCOV
345
  FByteswapper(self.indexStart);
×
UNCOV
346
  FByteswapper(self.numIndices);
×
UNCOV
347
  FByteswapper(self.indexValueOffset);
×
348
  FByteswapper(self.startIndex);
349
  FByteswapper(self.skinInfo);
UNCOV
350
}
×
UNCOV
351

×
352
template <> void FByteswapper(MODMeshX70 &self, bool) {
353
  FByteswapper(self.groupIndex);
354
  FByteswapper(self.materialIndex);
355
  FByteswapper(self.numVertices);
×
356
  FByteswapper(self.vertexStart);
×
357
  FByteswapper(self.vertexStreamOffset);
358
  FByteswapper(self.vertexStream2Offset);
UNCOV
359
  FByteswapper(self.indexStart);
×
360
  FByteswapper(self.numIndices);
×
361
  FByteswapper(self.indexValueOffset);
362
  FByteswapper(self.bboxMin);
363
  FByteswapper(self.bboxMax);
×
364
}
×
365

366
template <> void FByteswapper(MODMeshXC5 &self, bool way) {
×
UNCOV
367
  FByteswapper(self.drawMode);
×
UNCOV
368
  FByteswapper(self.numVertices);
×
369
  FByteswapper(self.data0, way);
370
  FByteswapper(self.data1, way);
UNCOV
371
  FByteswapper(self.vertexStart);
×
372
  FByteswapper(self.vertexStreamOffset);
373
  FByteswapper(self.vertexFormat);
374
  FByteswapper(self.indexStart);
×
375
  FByteswapper(self.numIndices);
×
UNCOV
376
  FByteswapper(self.indexValueOffset);
×
UNCOV
377
  FByteswapper(self.numEnvelopes);
×
378
  FByteswapper(self.meshIndex);
379
  FByteswapper(self.minVertex);
UNCOV
380
  FByteswapper(self.maxVertex);
×
381
  FByteswapper(self.boundaryInfo);
×
382
}
383

384
template <> void FByteswapper(MODMeshXD2 &self, bool way) {
UNCOV
385
  FByteswapper(self.drawMode);
×
UNCOV
386
  FByteswapper(self.numVertices);
×
387
  FByteswapper(self.data0, way);
388
  FByteswapper(self.data1, way);
UNCOV
389
  FByteswapper(self.vertexStart);
×
390
  FByteswapper(self.vertexStreamOffset);
×
391
  FByteswapper(self.vertexFormat);
392
  FByteswapper(self.indexStart);
UNCOV
393
  FByteswapper(self.numIndices);
×
UNCOV
394
  FByteswapper(self.indexValueOffset);
×
395
  FByteswapper(self.meshIndex);
UNCOV
396
  FByteswapper(self.minVertex);
×
UNCOV
397
  FByteswapper(self.maxVertex);
×
398
}
×
399

400
template <> void FByteswapper(MODMeshXE5 &self, bool way) {
401
  FByteswapper<MODMeshXD2>(self, way);
×
402
}
403

404
#pragma endregion
×
405
#pragma region Savers
×
UNCOV
406
void SaveMODX99(const MODInner<MODTraitsX99LE> &main, BinWritterRef wr) {
×
UNCOV
407
  MODHeaderX99 header{};
×
408
  header.id = MODID;
409
  header.version = 0x99;
410
  wr.Push();
×
UNCOV
411
  wr.Skip(sizeof(header));
×
412
  wr.ApplyPadding();
413
  wr.Skip(sizeof(main.boundingSphere) + sizeof(main.boundingBox) +
414
          sizeof(main.metadata));
UNCOV
415
  wr.ApplyPadding();
×
416

×
417
  header.numBones = main.bones.size();
418

419
  if (header.numBones) {
×
UNCOV
420
    header.bones = wr.Tell();
×
421
    header.numBoneMaps = main.skinRemaps.size();
422
    wr.WriteContainer(main.bones);
423
    wr.WriteContainer(main.refPoses);
×
UNCOV
424
    wr.WriteContainer(main.transforms);
×
425
    wr.Write(main.remaps);
426
    wr.WriteContainer(main.skinRemaps);
×
427
  }
×
UNCOV
428

×
429
  wr.ApplyPadding();
430
  header.numGroups = main.groups.size();
UNCOV
431

×
432
  if (header.numGroups) {
433
    header.groups = wr.Tell();
434
    wr.WriteContainer(main.groups);
×
435
  }
×
436

×
UNCOV
437
  wr.ApplyPadding();
×
438
  header.numTextures = main.paths.size();
439
  header.numMaterials = main.materials.size();
440

×
UNCOV
441
  if (header.numTextures || header.numMaterials) {
×
442
    header.textures = wr.Tell();
443
    for (auto &p : main.paths) {
444
      wr.WriteContainer(p);
445
      wr.Skip(MODTraitsX99LE::pathSize - p.size());
×
UNCOV
446
    }
×
447
    wr.WriteContainer(main.materials);
448
  }
449

×
UNCOV
450
  wr.ApplyPadding();
×
451
  header.numMeshes = main.meshes.size();
452
  header.meshes = wr.Tell();
453
  wr.WriteContainer(main.meshes);
454
  wr.WriteContainerWCount(main.envelopes);
UNCOV
455
  wr.ApplyPadding();
×
UNCOV
456
  header.vertexBufferSize = main.vertexBuffer.size() - main.unkBufferSize;
×
457
  header.unkBufferSize = main.unkBufferSize;
×
458
  header.vertexBuffer = wr.Tell();
×
UNCOV
459
  wr.WriteBuffer(main.vertexBuffer.data(), header.vertexBufferSize);
×
460

×
461
  if (header.unkBufferSize) {
×
462
    wr.ApplyPadding();
×
UNCOV
463
    header.unkBuffer = wr.Tell();
×
UNCOV
464
    wr.WriteBuffer(main.vertexBuffer.data() + header.vertexBufferSize,
×
465
                   header.unkBufferSize);
×
466
  }
467

468
  wr.ApplyPadding();
×
469
  header.indices = wr.Tell();
×
470
  header.numIndices = main.indexBuffer.size() + 1;
×
471
  wr.WriteContainer(main.indexBuffer);
×
UNCOV
472
  const size_t eof = wr.Tell();
×
UNCOV
473
  wr.Pop();
×
474
  wr.Write(header);
×
475
  wr.ApplyPadding();
×
UNCOV
476
  wr.Write(main.boundingSphere);
×
UNCOV
477
  wr.Write(main.boundingBox);
×
UNCOV
478
  wr.Write(main.metadata);
×
479
  wr.Seek(eof);
480
  wr.ApplyPadding();
UNCOV
481
}
×
UNCOV
482

×
483
void SaveMODXC5(const MODInner<MODTraitsXC5> &main, BinWritterRef wr) {
×
484
  MODHeaderXC5 header{};
×
UNCOV
485
  header.id = MODID;
×
486
  header.version = 0xC5;
×
UNCOV
487
  wr.Push();
×
UNCOV
488
  wr.Skip(sizeof(header));
×
489
  wr.ApplyPadding();
×
UNCOV
490
  wr.Skip(sizeof(main.boundingSphere) + sizeof(main.boundingBox) +
×
UNCOV
491
          sizeof(main.metadata));
×
492
  wr.ApplyPadding();
493

494
  header.numBones = main.bones.size();
495

496
  if (header.numBones) {
×
497
    header.bones = wr.Tell();
×
498
    wr.WriteContainer(main.bones);
499
    wr.WriteContainer(main.refPoses);
500
    wr.WriteContainer(main.transforms);
×
UNCOV
501
    wr.Write(main.remaps);
×
UNCOV
502
  }
×
503

×
504
  wr.ApplyPadding();
×
505
  header.numGroups = main.groups.size();
×
506

×
UNCOV
507
  if (header.numGroups) {
×
UNCOV
508
    header.groups = wr.Tell();
×
509
    wr.WriteContainer(main.groups);
510
  }
UNCOV
511

×
UNCOV
512
  wr.ApplyPadding();
×
513
  header.numTextures = main.paths.size();
514
  header.numMaterials = main.materials.size();
515

×
UNCOV
516
  if (header.numTextures || header.numMaterials) {
×
UNCOV
517
    header.textures = wr.Tell();
×
518
    for (auto &p : main.paths) {
×
519
      wr.WriteContainer(p);
×
UNCOV
520
      wr.Skip(MODTraitsXC5::pathSize - p.size());
×
521
    }
×
UNCOV
522
    wr.WriteContainer(main.materials);
×
UNCOV
523
  }
×
524

525
  wr.ApplyPadding();
UNCOV
526
  header.numMeshes = main.meshes.size();
×
UNCOV
527
  header.meshes = wr.Tell();
×
528
  wr.WriteContainer(main.meshes);
529
  wr.WriteContainerWCount(main.envelopes);
530
  wr.ApplyPadding();
×
531
  header.vertexBufferSize = main.vertexBuffer.size();
×
532
  header.vertexBuffer = wr.Tell();
×
533
  wr.WriteContainer(main.vertexBuffer);
×
534
  wr.ApplyPadding();
×
535
  header.indices = wr.Tell();
×
536
  header.numIndices = main.indexBuffer.size();
×
537
  wr.WriteContainer(main.indexBuffer);
×
538
  const size_t eof = wr.Tell();
×
539
  wr.Pop();
540
  wr.Write(header);
UNCOV
541
  wr.ApplyPadding();
×
542
  wr.Write(main.boundingSphere);
×
543
  wr.Write(main.boundingBox);
544
  wr.Write(main.metadata);
545
  wr.Seek(eof);
×
546
  wr.ApplyPadding();
×
547
}
×
548
#pragma endregion
×
549
#pragma region Loaders
×
550

×
551
template <class Header, class Traits>
×
552
MODImpl::ptr LoadMODX70(BinReaderRef_e rd) {
×
UNCOV
553
  Header header;
×
554
  MODInner<Traits> main;
555
  rd.Read(header);
556
  rd.ApplyPadding();
557
  rd.Read(main.boundingSphere);
558
  rd.Read(main.boundingBox);
559
  rd.Read(main.metadata);
×
560
  header.numIndices--;
×
561

×
562
  if (header.numBones) {
563
    rd.Seek(header.bones);
564
    rd.ReadContainer(main.bones, header.numBones);
×
565
    rd.ReadContainer(main.refPoses, header.numBones);
×
UNCOV
566
    rd.ReadContainer(main.transforms, header.numBones);
×
UNCOV
567
  }
×
568

569
  rd.Seek(header.textures);
570
  rd.ReadContainerLambda(main.paths, header.numTextures,
×
571
                         [](BinReaderRef_e rd, std::string &p) {
×
UNCOV
572
                           MODPath<Traits::pathSize> path;
×
UNCOV
573
                           rd.Read(path);
×
574
                           p = path.path;
×
575
                         });
576
  rd.ReadContainer(main.materials, header.numMaterials);
577

×
578
  rd.Seek(header.meshes);
579
  rd.ReadContainer(main.meshes, header.numMeshes);
580

581
  main.unkBufferSize = header.unkBufferSize;
582

×
583
  main.vertexBuffer.resize(header.vertexBufferSize + main.unkBufferSize);
584

585
  rd.Seek(header.vertexBuffer);
586
  rd.ReadBuffer(main.vertexBuffer.data(), header.vertexBufferSize);
UNCOV
587

×
UNCOV
588
  if (header.unkBufferSize) {
×
589
    rd.Seek(header.unkBuffer);
×
590
    rd.ReadBuffer(main.vertexBuffer.data() + header.vertexBufferSize,
591
                  header.unkBufferSize);
×
592
  }
593

594
  rd.Seek(header.indices);
×
595
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
596

×
597
  return std::make_unique<decltype(main)>(std::move(main));
598
}
UNCOV
599

×
600
MODImpl::ptr LoadMODXC5(BinReaderRef_e rd) {
×
601
  MODHeaderXC5 header;
×
UNCOV
602
  MODInner<MODTraitsXC5> main;
×
603
  rd.Read(header);
604
  rd.ApplyPadding();
605
  rd.Read(main.boundingSphere);
×
606
  rd.Read(main.boundingBox);
×
607
  rd.Read(main.metadata);
×
608

609
  if (header.numBones) {
610
    rd.Seek(header.bones);
×
611
    rd.ReadContainer(main.bones, header.numBones);
×
612
    rd.ReadContainer(main.refPoses, header.numBones);
613
    rd.ReadContainer(main.transforms, header.numBones);
UNCOV
614
    rd.Read(main.remaps);
×
615
  }
×
616

617
  if (header.numGroups) {
UNCOV
618
    rd.Seek(header.groups);
×
619
    rd.ReadContainer(main.groups, header.numGroups);
×
620
  }
621

622
  rd.Seek(header.textures);
×
623
  rd.ReadContainerLambda(main.paths, header.numTextures,
×
624
                         [](BinReaderRef_e rd, std::string &p) {
×
625
                           MODPath<MODTraitsXC5::pathSize> path;
×
626
                           rd.Read(path);
×
627
                           p = path.path;
×
UNCOV
628
                         });
×
UNCOV
629
  rd.ReadContainer(main.materials, header.numMaterials);
×
UNCOV
630

×
631
  rd.Seek(header.meshes);
632
  rd.ReadContainer(main.meshes, header.numMeshes);
633
  rd.ReadContainer(main.envelopes);
×
634

×
635
  rd.Seek(header.vertexBuffer);
×
UNCOV
636
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
UNCOV
637

×
638
  rd.Seek(header.indices);
×
639
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
640

×
641
  return std::make_unique<decltype(main)>(std::move(main));
×
UNCOV
642
}
×
UNCOV
643

×
644
MODImpl::ptr LoadMODXC3(BinReaderRef_e rd) {
×
645
  MODHeaderXC5 header;
×
646
  MODInner<MODTraitsXC5> main;
×
647
  rd.Read(header);
648
  rd.ApplyPadding();
UNCOV
649
  rd.Read(main.boundingSphere);
×
UNCOV
650
  rd.Read(main.boundingBox);
×
651
  rd.Read(main.metadata);
×
652

×
653
  if (header.numBones) {
×
654
    rd.Seek(header.bones);
×
UNCOV
655
    rd.ReadContainer(main.bones, header.numBones);
×
UNCOV
656
    rd.ReadContainer(main.refPoses, header.numBones);
×
657
    rd.ReadContainer(main.transforms, header.numBones);
×
658
    rd.Read(main.remaps);
×
659
  }
×
660

661
  if (header.numGroups) {
UNCOV
662
    rd.Seek(header.groups);
×
663
    rd.ReadContainer(main.groups, header.numGroups);
×
664
  }
×
665

×
UNCOV
666
  rd.Seek(header.textures);
×
UNCOV
667
  rd.ReadContainerLambda(main.paths, header.numTextures,
×
668
                         [](BinReaderRef_e rd, std::string &p) {
×
669
                           MODPath<MODTraitsXC5::pathSize> path;
×
670
                           rd.Read(path);
×
671
                           p = path.path;
×
UNCOV
672
                         });
×
UNCOV
673
  rd.ReadContainer(main.materials, header.numMaterials);
×
674

675
  rd.Seek(header.meshes);
676
  rd.ReadContainerLambda(main.meshes, header.numMeshes,
×
UNCOV
677
                         [](BinReaderRef_e rd, auto &m) {
×
UNCOV
678
                           rd.Read(m);
×
679
                           rd.Skip(8);
×
680
                         });
×
UNCOV
681
  rd.ReadContainer(main.envelopes);
×
UNCOV
682

×
683
  rd.Seek(header.vertexBuffer);
×
684
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
UNCOV
685

×
UNCOV
686
  rd.Seek(header.indices);
×
687
  rd.ReadContainer(main.indexBuffer, header.numIndices);
688

UNCOV
689
  return std::make_unique<decltype(main)>(std::move(main));
×
UNCOV
690
}
×
691

×
692
template <class Traits> MODImpl::ptr LoadMODX99(BinReaderRef_e rd) {
×
693
  MODHeaderX99 header;
×
694
  MODInner<Traits> main;
×
695
  rd.Read(header);
×
696
  rd.ApplyPadding();
×
697
  rd.Read(main.boundingSphere);
×
698
  rd.Read(main.boundingBox);
×
699
  rd.Read(main.metadata);
×
UNCOV
700
  header.numIndices--;
×
701

702
  if (header.numBones) {
703
    rd.Seek(header.bones);
×
704
    rd.ReadContainer(main.bones, header.numBones);
×
705
    rd.ReadContainer(main.refPoses, header.numBones);
×
706
    rd.ReadContainer(main.transforms, header.numBones);
×
707
    rd.Read(main.remaps);
×
708
    rd.ReadContainer(main.skinRemaps, header.numBoneMaps);
×
709
  }
×
710

×
711
  if (header.numGroups) {
×
712
    rd.Seek(header.groups);
×
713
    rd.ReadContainer(main.groups, header.numGroups);
×
714
  }
715

UNCOV
716
  rd.Seek(header.textures);
×
UNCOV
717
  rd.ReadContainerLambda(main.paths, header.numTextures,
×
718
                         [](BinReaderRef_e rd, std::string &p) {
×
719
                           MODPath<Traits::pathSize> path;
×
720
                           rd.Read(path);
×
721
                           p = path.path;
×
722
                         });
×
723
  rd.ReadContainer(main.materials, header.numMaterials);
×
724

×
725
  rd.Seek(header.meshes);
×
726
  rd.ReadContainer(main.meshes, header.numMeshes);
×
727
  rd.ReadContainer(main.envelopes);
×
728

×
729
  main.unkBufferSize = header.unkBufferSize;
730

731
  main.vertexBuffer.resize(header.vertexBufferSize + main.unkBufferSize);
×
732

733
  rd.Seek(header.vertexBuffer);
×
734
  rd.ReadBuffer(main.vertexBuffer.data(), header.vertexBufferSize);
×
735

×
736
  if (header.unkBufferSize) {
×
737
    rd.Seek(header.unkBuffer);
×
738
    rd.ReadBuffer(main.vertexBuffer.data() + header.vertexBufferSize,
×
739
                  header.unkBufferSize);
×
740
  }
×
741

×
742
  rd.Seek(header.indices);
×
UNCOV
743
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
744

745
  return std::make_unique<decltype(main)>(std::move(main));
746
}
747

748
template <class Traits> MODImpl::ptr LoadMODXD2x32(BinReaderRef_e rd) {
749
  MODHeaderXDx32 header;
×
750
  MODInner<Traits> main;
751
  rd.Read(header);
752
  rd.ApplyPadding();
×
753
  rd.Read(main.boundingSphere);
754
  rd.Read(main.boundingBox);
755
  rd.Read(main.metadata);
×
UNCOV
756

×
UNCOV
757
  if (header.bones > 0 && header.bones <= 0x80) {
×
758
    // UMVC3 PS3 uses unique model
×
759
    throw es::RuntimeError("Unsupported model format");
×
760
  }
×
761

×
762
  if (header.numBones) {
×
763
    rd.Seek(header.bones);
×
764
    rd.ReadContainer(main.bones, header.numBones);
×
765
    rd.ReadContainer(main.refPoses, header.numBones);
766
    rd.ReadContainer(main.transforms, header.numBones);
767
    rd.Read(main.remaps);
768
  }
769

UNCOV
770
  if (header.numGroups) {
×
771
    rd.Seek(header.groups);
772
    rd.ReadContainer(main.groups, header.numGroups);
773
  }
×
774

×
775
  rd.ReadContainer(main.materials, header.numMaterials);
776

×
777
  rd.Seek(header.meshes);
×
778
  rd.ReadContainerLambda(main.meshes, header.numMeshes,
×
779
                         [](BinReaderRef_e rd, auto &m) {
×
780
                           rd.Read(m);
×
781
                           rd.Skip(8);
×
782
                         });
×
UNCOV
783

×
UNCOV
784
  if constexpr (std::is_same_v<MODMetaDataV2, typename Traits::metadata>) {
×
785
    rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes);
×
786
  } else {
787
    rd.ReadContainer(main.envelopes);
788
  }
789

790
  rd.Seek(header.vertexBuffer);
791
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
792

793
  rd.Seek(header.indices);
794
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
795

×
796
  return std::make_unique<decltype(main)>(std::move(main));
797
}
UNCOV
798

×
UNCOV
799
template <class Traits> MODImpl::ptr LoadMODXDxLEx32(BinReaderRef_e rdn) {
×
800
  BinReaderRef rd(rdn);
×
801
  MODHeaderXDx32 header;
×
802
  MODInner<Traits> main;
×
803
  rd.Read(header);
×
804
  rd.ApplyPadding();
×
805
  rd.Read(main.boundingSphere);
×
806
  rd.Read(main.boundingBox);
×
807
  rd.Read(main.metadata);
×
808

×
809
  if (header.numBones) {
×
810
    rd.Seek(header.bones);
×
811
    rd.ReadContainer(main.bones, header.numBones);
812
    rd.ReadContainer(main.refPoses, header.numBones);
813
    rd.ReadContainer(main.transforms, header.numBones);
×
814
    rd.Read(main.remaps);
×
815
  }
×
816

×
817
  if (header.numGroups) {
×
818
    rd.Seek(header.groups);
×
819
    rd.ReadContainer(main.groups, header.numGroups);
×
820
  }
×
821

×
822
  rdn.ReadContainer(main.materials, header.numMaterials);
×
823

×
824
  rd.Seek(header.meshes);
×
825
  rd.ReadContainer(main.meshes, header.numMeshes);
826

827
  if constexpr (std::is_same_v<MODMetaDataV2, typename Traits::metadata>) {
×
828
    rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes);
×
UNCOV
829
  } else {
×
830
    rd.ReadContainer(main.envelopes);
×
831
  }
832

×
833
  rd.Seek(header.vertexBuffer);
×
834
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
835

×
836
  rd.Seek(header.indices);
×
837
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
838

×
839
  return std::make_unique<decltype(main)>(std::move(main));
×
840
}
×
841

×
842
template <class Traits, class TraitsFallback>
×
843
MODImpl::ptr LoadMODXDxLE(BinReaderRef_e rdn) {
844
  BinReaderRef rd(rdn);
845
  MODHeaderXDx64 header;
×
846
  MODInner<Traits> main;
×
847
  rd.Push();
×
848
  rd.Read(header);
×
849
  rd.ApplyPadding();
850
  rd.Read(main.boundingSphere);
×
851
  rd.Read(main.boundingBox);
×
852
  rd.Read(main.metadata);
×
UNCOV
853
  {
×
UNCOV
854
    uint64 maxPtr = header.bones | header.groups | header.materialNames |
×
855
                    header.meshes | header.vertexBuffer | header.indices |
×
856
                    header.dataEnd;
×
UNCOV
857
    size_t fileSize = rd.GetSize() << 1;
×
858

×
859
    if (maxPtr > fileSize) {
860
      rd.Pop();
861
      return LoadMODXDxLEx32<TraitsFallback>(rd);
×
862
    }
×
863
  }
864

865
  if (header.numBones) {
866
    rd.Seek(header.bones);
867
    rd.ReadContainer(main.bones, header.numBones);
×
868
    rd.ReadContainer(main.refPoses, header.numBones);
×
869
    rd.ReadContainer(main.transforms, header.numBones);
×
870
    rd.Read(main.remaps);
×
871
  }
872

×
873
  if (header.numGroups) {
×
874
    rd.Seek(header.groups);
×
875
    rd.ReadContainer(main.groups, header.numGroups);
876
  }
×
877

878
  rdn.ReadContainer(main.materials, header.numMaterials);
×
879

880
  rd.Seek(header.meshes);
×
881
  rdn.ReadContainerLambda(main.meshes, header.numMeshes,
×
UNCOV
882
                          [](BinReaderRef_e rd, auto &m) {
×
UNCOV
883
                            rd.Read(m);
×
884
                            rd.Skip(8);
×
885
                          });
×
UNCOV
886
  rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes);
×
UNCOV
887

×
888
  rd.Seek(header.vertexBuffer);
889
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
890

×
891
  rd.Seek(header.indices);
×
892
  rd.ReadContainer(main.indexBuffer, header.numIndices);
893

×
894
  return std::make_unique<decltype(main)>(std::move(main));
×
895
}
×
896

897
MODImpl::ptr LoadMODX06(BinReaderRef_e rdn) {
898
  MODHeaderX06 header;
×
899
  MODInner<MODTraitsX06> main;
×
900
  BinReaderRef rd(rdn);
×
901
  rd.Push();
UNCOV
902
  rd.Read(header);
×
903
  rd.ApplyPadding();
×
904
  rd.Read(main.boundingSphere);
×
905
  rd.Read(main.boundingBox);
906
  rd.Read(main.metadata);
×
907

908
  if (header.numBones) {
909
    rd.Seek(header.bones);
910
    rd.ReadContainer(main.bones, header.numBones);
911
    rd.ReadContainer(main.refPoses, header.numBones);
×
912
    rd.ReadContainer(main.transforms, header.numBones);
×
913
    rd.Read(main.remaps);
×
914
    rd.ReadContainer(main.skinRemaps, header.numSkins);
×
UNCOV
915
  }
×
UNCOV
916

×
917
  if (header.numGroups) {
×
918
    rd.Seek(header.groups);
×
919
    rd.ReadContainer(main.groups, header.numGroups);
×
920
  }
×
921

922
  rdn.ReadContainer(main.materials, header.numMaterials);
×
923

×
924
  rd.Seek(header.meshes);
×
925
  rdn.ReadContainerLambda(main.meshes, header.numMeshes,
×
926
                          [](BinReaderRef_e rd, auto &m) {
×
927
                            rd.Read(m);
928
                            rd.Skip(8);
929
                          });
×
930
  rd.ReadContainer(main.envelopes);
×
931

×
932
  rd.Seek(header.vertexBuffer);
×
933
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
934

935
  rd.Seek(header.indices);
936
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
937

×
938
  return std::make_unique<decltype(main)>(std::move(main));
×
UNCOV
939
}
×
940

941
MODImpl::ptr LoadMODXE5(BinReaderRef_e rd) {
×
942
  MODHeaderXE5 header;
943
  MODInner<MODTraitsXE5> main;
944
  rd.Push();
×
945
  rd.Read(header);
×
946
  rd.ApplyPadding();
×
947
  rd.Read(main.boundingSphere);
×
948
  rd.Read(main.boundingBox);
UNCOV
949
  rd.Read(main.metadata);
×
UNCOV
950

×
UNCOV
951
  if (header.numBones) {
×
952
    rd.Seek(header.bones);
953
    rd.ReadContainer(main.bones, header.numBones);
×
954
    rd.ReadContainer(main.refPoses, header.numBones);
UNCOV
955
    rd.ReadContainer(main.transforms, header.numBones);
×
956
    rd.Read(main.remaps);
UNCOV
957
    rd.ReadContainer(main.skinRemaps, header.numSkins);
×
958
  }
×
959

×
960
  if (header.numGroups) {
×
961
    rd.Seek(header.groups);
×
UNCOV
962
    rd.ReadContainer(main.groups, header.numGroups);
×
963
  }
964

965
  rd.ReadContainer(main.materials, header.numMaterials);
×
966

×
967
  rd.Seek(header.meshes);
968
  rd.ReadContainer(main.meshes, header.numMeshes);
×
UNCOV
969
  rd.ReadContainer(main.envelopes);
×
970

×
971
  rd.Seek(header.vertexBuffer);
972
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
973

×
974
  rd.Seek(header.indices);
×
975
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
976

977
  return std::make_unique<decltype(main)>(std::move(main));
×
UNCOV
978
}
×
UNCOV
979

×
980
MODImpl::ptr LoadMODXFF2C(BinReaderRef_e rd) {
981
  MODHeaderXE5 header;
×
982
  MODInner<MODTraitsXD3LE> main;
983
  rd.Push();
984
  rd.Read(header);
985
  rd.ApplyPadding();
UNCOV
986
  rd.Read(main.boundingSphere);
×
UNCOV
987
  rd.Read(main.boundingBox);
×
988
  rd.Read(main.metadata);
×
989

×
990
  if (header.numBones) {
×
UNCOV
991
    rd.Seek(header.bones);
×
992
    rd.ReadContainer(main.bones, header.numBones);
×
993
    rd.ReadContainer(main.refPoses, header.numBones);
×
994
    rd.ReadContainer(main.transforms, header.numBones);
UNCOV
995
    rd.Read(main.remaps);
×
996
  }
×
UNCOV
997

×
UNCOV
998
  if (header.numGroups) {
×
999
    rd.Seek(header.groups);
1000
    rd.ReadContainer(main.groups, header.numGroups);
1001
  }
1002

×
1003
  rd.ReadContainer(main.materials, header.numMaterials);
×
1004

×
1005
  rd.Seek(header.meshes);
×
1006
  rd.ReadContainerLambda(main.meshes, header.numMeshes,
1007
                         [](BinReaderRef_e rd, auto &m) {
×
1008
                           rd.Read(m);
1009
                           rd.Skip(8);
1010
                         });
1011
  rd.ReadContainer(main.envelopes);
1012

1013
  rd.Seek(header.vertexBuffer);
×
1014
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
1015

1016
  rd.Seek(header.indices);
×
UNCOV
1017
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
UNCOV
1018

×
1019
  return std::make_unique<decltype(main)>(std::move(main));
×
1020
}
×
1021

×
1022
std::vector<MODMaterialProxy<MODMaterialX21>>
UNCOV
1023
XFSToMaterials(const revil::XFS &main) {
×
UNCOV
1024
  pugi::xml_document root;
×
UNCOV
1025
  main.ToXML(root);
×
1026
  std::vector<MODMaterialProxy<MODMaterialX21>> retval;
×
1027
  auto mtArr = root.child("class").child("array");
×
1028
  retval.resize(mtArr.attribute("count").as_int());
1029

1030
  for (uint32 curMat = 0; auto &c : mtArr.children()) {
×
UNCOV
1031
    auto &mat = retval.at(curMat++).main;
×
1032
    mat.name = "Material_";
1033
    mat.name.append(c.find_child_by_attribute("name", "mTagID")
1034
                        .attribute("value")
1035
                        .as_string());
1036
  }
UNCOV
1037

×
1038
  return retval;
1039
}
×
1040

×
1041
MODImpl::ptr LoadMODX21(BinReaderRef_e rd) {
UNCOV
1042
  MODHeaderX21 header;
×
1043
  MODInner<MODTraitsX21> main;
UNCOV
1044
  rd.Push();
×
1045
  rd.Read(header);
1046
  rd.ApplyPadding();
×
1047
  rd.Read(main.boundingSphere);
×
1048
  rd.Read(main.boundingBox);
1049
  rd.Read(main.metadata);
×
1050

×
UNCOV
1051
  if (header.numBones) {
×
UNCOV
1052
    rd.Seek(header.bones);
×
1053
    rd.ReadContainer(main.bones, header.numBones);
1054
    rd.ReadContainer(main.refPoses, header.numBones);
UNCOV
1055
    rd.ReadContainer(main.transforms, header.numBones);
×
1056
    rd.Read(main.remaps);
×
1057
    // skins??
1058
  }
×
1059

UNCOV
1060
  if (header.numGroups) {
×
1061
    rd.Seek(header.groups);
1062
    rd.ReadContainer(main.groups, header.numGroups);
1063
  }
×
UNCOV
1064

×
1065
  rd.Seek(header.materials);
×
1066
  revil::XFS materials;
×
1067
  materials.Load(rd, true);
×
UNCOV
1068
  main.materials = XFSToMaterials(materials);
×
1069

UNCOV
1070
  rd.Seek(header.meshes);
×
UNCOV
1071
  rd.ReadContainer(main.meshes, header.numMeshes);
×
UNCOV
1072
  rd.ReadContainer(main.envelopes);
×
UNCOV
1073

×
1074
  rd.Seek(header.vertexBuffer);
×
1075
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
1076

1077
  rd.Seek(header.indices);
×
1078
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
1079

1080
  return std::make_unique<decltype(main)>(std::move(main));
1081
}
1082

1083
#pragma endregion
1084

×
1085
bool MODMaker::operator<(const MODMaker &i0) const {
1086
  return reinterpret_cast<const uint64 &>(*this) <
×
UNCOV
1087
         reinterpret_cast<const uint64 &>(i0);
×
1088
}
UNCOV
1089

×
1090
static const std::map<MODMaker, MODImpl::ptr (*)(BinReaderRef_e)> modLoaders{
1091
    {{MODVersion::X70, true}, LoadMODX70<MODHeaderX70, MODTraitsX70>},
×
1092
    {{MODVersion::X170}, LoadMODX70<MODHeaderX170, MODTraitsX170>},
UNCOV
1093
    {{MODVersion::X99}, LoadMODX99<MODTraitsX99LE>},
×
1094
    {{MODVersion::X19C}, LoadMODX99<MODTraitsX99LE>},
×
1095
    {{MODVersion::X99, true}, LoadMODX99<MODTraitsX99BE>},
UNCOV
1096
    {{MODVersion::XC3, true}, LoadMODXC3},
×
UNCOV
1097
    {{MODVersion::XC5}, LoadMODXC5},
×
UNCOV
1098
    {{MODVersion::XD2}, LoadMODXDxLEx32<MODTraitsXD2>},
×
UNCOV
1099
    {{MODVersion::XD3}, LoadMODXDxLE<MODTraitsXD3x64, MODTraitsXD3LE>},
×
1100
    {{MODVersion::XD6},
1101
     LoadMODXDxLE<MODTraitsXD6, MODTraitsXD3LE>}, // unused fallback
UNCOV
1102
    {{MODVersion::XD4},
×
1103
     LoadMODXDxLEx32<MODTraitsXD3PS4>}, // todo normals (different traits)
×
1104

1105
    {{MODVersion::XD2, true}, LoadMODXD2x32<MODTraitsXD2>},
×
1106
    {{MODVersion::XD3, true}, LoadMODXD2x32<MODTraitsXD2>},
1107
    {{MODVersion::XD4, true}, LoadMODXD2x32<MODTraitsXD2>},
×
1108
    {{MODVersion::X05}, LoadMODX06},
1109
    {{MODVersion::X06}, LoadMODX06},
1110
    {{MODVersion::XE5, true}, LoadMODXE5},
×
1111
    {{MODVersion::XE5}, LoadMODXE5},
×
1112
    {{MODVersion::XE6, true}, LoadMODXE5},
×
1113
    {{MODVersion::XE6}, LoadMODXE5},
×
UNCOV
1114
    {{MODVersion::XE7}, LoadMODXE5},
×
UNCOV
1115
    {{MODVersion::XFF2C, true}, LoadMODXFF2C},
×
1116
    {{MODVersion::X21, true}, LoadMODX21},
1117
};
×
UNCOV
1118

×
UNCOV
1119
template <class C> MODImpl::ptr makeMod() {
×
UNCOV
1120
  return std::make_unique<MODInner<C>>();
×
UNCOV
1121
}
×
1122

1123
static const std::map<MODMaker, MODImpl::ptr (*)()> modMakers{
UNCOV
1124
    {{MODVersion::X70, true}, makeMod<MODTraitsX70>},
×
1125
};
×
1126

1127
MOD::MOD(MODMaker make) {
1128
  auto found = modMakers.find(make);
1129

1130
  if (es::IsEnd(modMakers, found)) {
UNCOV
1131
    throw es::RuntimeError("Cannon find specified MODMaker instance.");
×
1132
  }
1133

×
UNCOV
1134
  pi = found->second();
×
1135
}
1136

×
1137
void MOD::Load(const std::string &fileName) {
1138
  BinReader rd(fileName);
×
1139
  Load(rd);
UNCOV
1140
}
×
1141

×
1142
void MOD::Load(BinReaderRef_e rd) {
UNCOV
1143
  MODHeaderCommon header;
×
1144
  rd.Push();
×
UNCOV
1145
  rd.Read(header);
×
1146
  rd.Pop();
×
1147

1148
  if (header.id == DOMID || header.id == RMDID) {
1149
    rd.SwapEndian(true);
×
1150
    FByteswapper(header);
×
1151
  } else if (header.id != MODID) {
1152
    throw es::InvalidHeaderError(header.id);
×
1153
  }
1154

1155
  MODMaker mk;
×
1156
  mk.version = static_cast<MODVersion>(header.version);
1157
  mk.swappedEndian = rd.SwappedEndian();
1158

×
1159
  auto found = modLoaders.find(mk);
×
UNCOV
1160

×
UNCOV
1161
  if (es::IsEnd(modLoaders, found)) {
×
1162
    throw es::InvalidVersionError(mk.version);
×
1163
  }
UNCOV
1164

×
UNCOV
1165
  pi = found->second(rd);
×
UNCOV
1166
  pi->Reflect(rd.SwappedEndian());
×
UNCOV
1167
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc