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

PredatorCZ / RevilLib / 147

13 May 2024 09:43PM UTC coverage: 11.246% (-0.3%) from 11.534%
147

push

github

PredatorCZ
add lmt v68 support

757 of 6731 relevant lines covered (11.25%)

6713.75 hits per line

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

0.08
/src/mtf_mod/serialize.cpp
1
/*  Revil Format Library
2
    Copyright(C) 2017-2023 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

33
template <class T> using use_name = decltype(std::declval<T>().Name());
34
template <class C>
35
constexpr static bool use_name_v = es::is_detected_v<use_name, C>;
36

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

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

59
  for (auto &r : skinRemaps) {
×
60
    this->skins.emplace_back(r.bones, r.count);
×
61
  }
62

63
  for (auto &m : this->materials) {
×
64
    revil::MODMaterial &ref = this->materialRefs.emplace_back();
×
65
    if constexpr (use_name_v<std::decay_t<decltype(m.main)>>) {
66
      ref.name = m.main.Name();
×
67
    }
68

69
    ref.refl = &m.asMetadata;
×
70
  }
71
}
72

×
73
template <class material_type>
×
74
void MODMaterialProxy<material_type>::Write(BinWritterRef wr) const {
75
  auto main_ = main;
×
76
  main_.baseTextureIndex++;
×
77
  main_.normalTextureIndex++;
×
78
  main_.maskTextureIndex++;
79
  main_.lightTextureIndex++;
80
  main_.shadowTextureIndex++;
×
81
  main_.additionalTextureIndex++;
82
  main_.cubeMapTextureIndex++;
83
  main_.detailTextureIndex++;
×
84
  main_.AOTextureIndex++;
×
85
  wr.Write(main_);
×
86
}
×
87

88
template <class material_type>
89
void MODMaterialProxy<material_type>::Read(BinReaderRef_e rd) {
×
90
  rd.Read(main);
×
91
  if constexpr (!std::is_same_v<material_type, MODMaterialHash> &&
92
                !std::is_same_v<material_type, MODMaterialName>) {
93
    main.baseTextureIndex--;
94
    main.normalTextureIndex--;
×
95
    main.maskTextureIndex--;
×
96
    main.lightTextureIndex--;
97
    main.shadowTextureIndex--;
98
    main.additionalTextureIndex--;
×
99
    main.cubeMapTextureIndex--;
×
100
    main.detailTextureIndex--;
101
    main.AOTextureIndex--;
×
102
  }
103
}
104

×
105
#pragma region Endian Swappers
106

107
template <> void FByteswapper(MODBoneV1 &self, bool) {
×
108
  FByteswapper(self.absolutePosition);
×
109
  FByteswapper(self.parentDistance);
110
}
×
111

×
112
template <> void FByteswapper(MODBoneV1_5 &self, bool) {
×
113
  FByteswapper(self.absolutePosition);
114
  FByteswapper(self.parentDistance);
115
  FByteswapper(self.furthestVertexDistance);
×
116
}
117

118
template <> void FByteswapper(MODBoneV2 &self, bool) {
×
119
  FByteswapper(self.absolutePosition);
×
120
  FByteswapper(self.parentDistance);
×
121
  FByteswapper(self.furthestVertexDistance);
×
122
  FByteswapper(self.index);
123
}
124

×
125
template <> void FByteswapper(MODBounds &self, bool) {
×
126
  FByteswapper(self.bboxMax);
127
  FByteswapper(self.bboxMin);
128
  FByteswapper(self.boundingSphere);
129
}
×
130

×
131
template <> void FByteswapper(MODEnvelope &self, bool) {
132
  FByteswapper(self.absolutePosition);
133
  FByteswapper(self.boneIndex);
×
134
  FByteswapper(self.bounds);
×
135
}
136

137
template <> void FByteswapper(MODGroup &self, bool) {
138
  FByteswapper(self.boundingSphere);
139
  FByteswapper(self.index);
×
140
}
141

142
template <> void FByteswapper(MODMetaData &self, bool) {
×
143
  FByteswapper(self.lightGroup);
×
144
  FByteswapper(self.lowDistance);
145
  FByteswapper(self.middleDistance);
×
146
}
×
147

×
148
template <> void FByteswapper(MODMetaDataV2 &self, bool) {
149
  FByteswapper(static_cast<MODMetaData &>(self));
150
  FByteswapper(self.numEnvelopes);
×
151
}
152

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

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

×
161
template <> void FByteswapper(MODSkinRemap<64> &self, bool) {
162
  FByteswapper(self.count);
163
}
164

×
165
template <> void FByteswapper(MODHeaderCommon &self, bool) {
×
166
  FByteswapper(self.id);
167
  FByteswapper(self.version);
168
  FByteswapper(self.numBones);
×
169
  FByteswapper(self.numMeshes);
×
170
  FByteswapper(self.numMaterials);
171
  FByteswapper(self.numVertices);
×
172
  FByteswapper(self.numIndices);
173
  FByteswapper(self.numEdges);
174
}
×
175

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

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

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

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

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

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

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

×
274
template <> void FByteswapper(MODMaterialX70 &self, bool way) {
×
275
  FByteswapper(self.pshData);
276
  FByteswapper(self.vshData, way);
×
277
  FByteswapper(self.baseTextureIndex);
278
  FByteswapper(self.normalTextureIndex);
279
  FByteswapper(self.maskTextureIndex);
×
280
  FByteswapper(self.lightTextureIndex);
281
  FByteswapper(self.shadowTextureIndex);
282
  FByteswapper(self.additionalTextureIndex);
×
283
  FByteswapper(self.cubeMapTextureIndex);
×
284
  FByteswapper(self.detailTextureIndex);
285
  FByteswapper(self.AOTextureIndex);
×
286
  FByteswapper(self.transparency);
×
287
  FByteswapper(self.fresnelFactor);
×
288
  FByteswapper(self.fresnelBias);
289
  FByteswapper(self.specularPower);
290
  FByteswapper(self.envMapPower);
×
291
  FByteswapper(self.lightMapScale);
292
  FByteswapper(self.detailFactor);
293
  FByteswapper(self.detailWrap);
×
294
  FByteswapper(self.envMapBias);
×
295
  FByteswapper(self.normalBias);
×
296
  FByteswapper(self.transmit);
×
297
  FByteswapper(self.paralax);
298
  FByteswapper(self.hash);
299
}
×
300

×
301
template <> void FByteswapper(MODMaterialX170 &self, bool) {
302
  FByteswapper(self.pshData);
303
  FByteswapper(self.vshData);
304
  FByteswapper(self.baseTextureIndex);
×
305
  FByteswapper(self.normalTextureIndex);
×
306
  FByteswapper(self.maskTextureIndex);
307
  FByteswapper(self.lightTextureIndex);
308
  FByteswapper(self.shadowTextureIndex);
×
309
  FByteswapper(self.additionalTextureIndex);
×
310
  FByteswapper(self.cubeMapTextureIndex);
311
  FByteswapper(self.detailTextureIndex);
×
312
  FByteswapper(self.AOTextureIndex);
313
  FByteswapper(self.transparency);
314
  FByteswapper(self.unk00);
×
315
  FByteswapper(self.fresnelFactor);
316
  FByteswapper(self.fresnelBias);
317
  FByteswapper(self.specularPower);
×
318
  FByteswapper(self.envMapPower);
×
319
  FByteswapper(self.lightMapScale);
320
  FByteswapper(self.detailFactor);
×
321
  FByteswapper(self.detailWrap);
×
322
  FByteswapper(self.envMapBias);
×
323
  FByteswapper(self.normalBias);
324
  FByteswapper(self.transmit);
325
  FByteswapper(self.paralax);
×
326
  FByteswapper(self.hash);
327
}
328

×
329
template <> void FByteswapper(MODMaterialXC5 &self, bool way) {
×
330
  FByteswapper(self.pshData, way);
×
331
  FByteswapper(self.vshData, way);
×
332
  FByteswapper(self.baseTextureIndex);
333
  FByteswapper(self.normalTextureIndex);
334
  FByteswapper(self.maskTextureIndex);
×
335
  FByteswapper(self.lightTextureIndex);
×
336
  FByteswapper(self.shadowTextureIndex);
337
  FByteswapper(self.additionalTextureIndex);
338
  FByteswapper(self.cubeMapTextureIndex);
339
  FByteswapper(self.detailTextureIndex);
×
340
  FByteswapper(self.AOTextureIndex);
×
341
  FByteswapper(self.transparency);
342
  FByteswapper(self.unk01);
343
  FByteswapper(self.specularPower);
×
344
  FByteswapper(self.envMapPower);
×
345
  FByteswapper(self.lightMapScale);
346
  FByteswapper(self.detailFactor);
347
  FByteswapper(self.detailWrap);
348
  FByteswapper(self.envMapBias);
349
  FByteswapper(self.normalBias);
×
350
  FByteswapper(self.unk02);
351
  FByteswapper(self.unk03);
352
  FByteswapper(self.unk04);
×
353
  FByteswapper(self.unk05);
×
354
  FByteswapper(self.unk06);
355
  FByteswapper(self.unk07);
×
356
}
×
357

×
358
template <> void FByteswapper(MODMaterialHash &self, bool) {
359
  FByteswapper(self.hash);
360
}
×
361

362
template <> void FByteswapper(MODMeshX99 &self, bool) {
363
  FByteswapper(self.unk);
×
364
  FByteswapper(self.materialIndex);
×
365
  FByteswapper(self.numVertices);
×
366
  FByteswapper(self.endIndex);
×
367
  FByteswapper(self.vertexStart);
368
  FByteswapper(self.vertexStreamOffset);
369
  FByteswapper(self.vertexStream2Offset);
×
370
  FByteswapper(self.indexStart);
×
371
  FByteswapper(self.numIndices);
372
  FByteswapper(self.indexValueOffset);
373
  FByteswapper(self.startIndex);
374
  FByteswapper(self.skinInfo);
×
375
}
×
376

377
template <> void FByteswapper(MODMeshX70 &self, bool) {
378
  FByteswapper(self.unk);
×
379
  FByteswapper(self.materialIndex);
×
380
  FByteswapper(self.numVertices);
381
  FByteswapper(self.vertexStart);
×
382
  FByteswapper(self.vertexStreamOffset);
383
  FByteswapper(self.vertexStream2Offset);
384
  FByteswapper(self.indexStart);
×
385
  FByteswapper(self.numIndices);
386
  FByteswapper(self.indexValueOffset);
387
  FByteswapper(self.bboxMin);
×
388
  FByteswapper(self.bboxMax);
×
389
}
390

×
391
template <> void FByteswapper(MODMeshXC5 &self, bool way) {
×
392
  FByteswapper(self.unk);
×
393
  FByteswapper(self.numVertices);
394
  FByteswapper(self.data0, way);
395
  FByteswapper(self.data1, way);
×
396
  FByteswapper(self.vertexStart);
397
  FByteswapper(self.vertexStreamOffset);
398
  FByteswapper(self.vertexFormat);
×
399
  FByteswapper(self.indexStart);
×
400
  FByteswapper(self.numIndices);
×
401
  FByteswapper(self.indexValueOffset);
×
402
  FByteswapper(self.numEnvelopes);
403
  FByteswapper(self.meshIndex);
404
  FByteswapper(self.minVertex);
×
405
  FByteswapper(self.maxVertex);
×
406
  FByteswapper(self.hash);
407
}
408

409
template <> void FByteswapper(MODMeshXD2 &self, bool way) {
×
410
  FByteswapper(self.unk);
×
411
  FByteswapper(self.numVertices);
412
  FByteswapper(self.data0, way);
413
  FByteswapper(self.data1, way);
×
414
  FByteswapper(self.vertexStart);
×
415
  FByteswapper(self.vertexStreamOffset);
416
  FByteswapper(self.vertexFormat);
×
417
  FByteswapper(self.indexStart);
418
  FByteswapper(self.numIndices);
419
  FByteswapper(self.indexValueOffset);
×
420
  FByteswapper(self.meshIndex);
421
  FByteswapper(self.minVertex);
422
  FByteswapper(self.maxVertex);
×
423
  FByteswapper(self.unk);
×
424
}
425

×
426
template <> void FByteswapper(MODMeshXE5 &self, bool way) {
×
427
  FByteswapper<MODMeshXD2>(self, way);
×
428
}
429

430
#pragma endregion
×
431
#pragma region Savers
432
void SaveMODX99(const MODInner<MODTraitsX99LE> &main, BinWritterRef wr) {
433
  MODHeaderX99 header{};
×
434
  header.id = MODID;
×
435
  header.version = 0x99;
×
436
  wr.Push();
×
437
  wr.Skip(sizeof(header));
438
  wr.ApplyPadding();
439
  wr.Skip(sizeof(main.bounds) + sizeof(main.metadata));
×
440
  wr.ApplyPadding();
×
441

442
  header.numBones = main.bones.size();
443

444
  if (header.numBones) {
×
445
    header.bones = wr.Tell();
×
446
    header.numBoneMaps = main.skinRemaps.size();
447
    wr.WriteContainer(main.bones);
448
    wr.WriteContainer(main.refPoses);
×
449
    wr.WriteContainer(main.transforms);
×
450
    wr.Write(main.remaps);
451
    wr.WriteContainer(main.skinRemaps);
×
452
  }
453

454
  wr.ApplyPadding();
×
455
  header.numGroups = main.groups.size();
456

457
  if (header.numGroups) {
×
458
    header.groups = wr.Tell();
×
459
    wr.WriteContainer(main.groups);
460
  }
×
461

×
462
  wr.ApplyPadding();
×
463
  header.numTextures = main.paths.size();
464
  header.numMaterials = main.materials.size();
465

×
466
  if (header.numTextures || header.numMaterials) {
467
    header.textures = wr.Tell();
468
    for (auto &p : main.paths) {
×
469
      wr.WriteContainer(p);
×
470
      wr.Skip(MODTraitsX99LE::pathSize - p.size());
×
471
    }
×
472
    wr.WriteContainer(main.materials);
473
  }
474

×
475
  wr.ApplyPadding();
×
476
  header.numMeshes = main.meshes.size();
477
  header.meshes = wr.Tell();
478
  wr.WriteContainer(main.meshes);
479
  wr.WriteContainerWCount(main.envelopes);
×
480
  wr.ApplyPadding();
×
481
  header.vertexBufferSize = main.vertexBuffer.size() - main.unkBufferSize;
482
  header.unkBufferSize = main.unkBufferSize;
483
  header.vertexBuffer = wr.Tell();
×
484
  wr.WriteBuffer(main.vertexBuffer.data(), header.vertexBufferSize);
×
485

486
  if (header.unkBufferSize) {
×
487
    wr.ApplyPadding();
488
    header.unkBuffer = wr.Tell();
489
    wr.WriteBuffer(main.vertexBuffer.data() + header.vertexBufferSize,
×
490
                   header.unkBufferSize);
491
  }
492

×
493
  wr.ApplyPadding();
×
494
  header.indices = wr.Tell();
495
  header.numIndices = main.indexBuffer.size() + 1;
×
496
  wr.WriteContainer(main.indexBuffer);
×
497
  const size_t eof = wr.Tell();
×
498
  wr.Pop();
499
  wr.Write(header);
500
  wr.ApplyPadding();
×
501
  wr.Write(main.bounds);
502
  wr.Write(main.metadata);
503
  wr.Seek(eof);
×
504
  wr.ApplyPadding();
×
505
}
×
506

×
507
void SaveMODXC5(const MODInner<MODTraitsXC5> &main, BinWritterRef wr) {
508
  MODHeaderXC5 header{};
509
  header.id = MODID;
×
510
  header.version = 0xC5;
×
511
  wr.Push();
512
  wr.Skip(sizeof(header));
513
  wr.ApplyPadding();
514
  wr.Skip(sizeof(main.bounds) + sizeof(main.metadata));
×
515
  wr.ApplyPadding();
×
516

517
  header.numBones = main.bones.size();
518

×
519
  if (header.numBones) {
×
520
    header.bones = wr.Tell();
521
    wr.WriteContainer(main.bones);
×
522
    wr.WriteContainer(main.refPoses);
523
    wr.WriteContainer(main.transforms);
524
    wr.Write(main.remaps);
×
525
  }
526

527
  wr.ApplyPadding();
528
  header.numGroups = main.groups.size();
529

×
530
  if (header.numGroups) {
×
531
    header.groups = wr.Tell();
×
532
    wr.WriteContainer(main.groups);
×
533
  }
×
534

×
535
  wr.ApplyPadding();
×
536
  header.numTextures = main.paths.size();
×
537
  header.numMaterials = main.materials.size();
×
538

×
539
  if (header.numTextures || header.numMaterials) {
×
540
    header.textures = wr.Tell();
541
    for (auto &p : main.paths) {
542
      wr.WriteContainer(p);
×
543
      wr.Skip(MODTraitsXC5::pathSize - p.size());
×
544
    }
×
545
    wr.WriteContainer(main.materials);
×
546
  }
×
547

×
548
  wr.ApplyPadding();
×
549
  header.numMeshes = main.meshes.size();
×
550
  header.meshes = wr.Tell();
×
551
  wr.WriteContainer(main.meshes);
×
552
  wr.WriteContainerWCount(main.envelopes);
×
553
  wr.ApplyPadding();
554
  header.vertexBufferSize = main.vertexBuffer.size();
555
  header.vertexBuffer = wr.Tell();
×
556
  wr.WriteContainer(main.vertexBuffer);
×
557
  wr.ApplyPadding();
×
558
  header.indices = wr.Tell();
×
559
  header.numIndices = main.indexBuffer.size();
×
560
  wr.WriteContainer(main.indexBuffer);
×
561
  const size_t eof = wr.Tell();
×
562
  wr.Pop();
×
563
  wr.Write(header);
×
564
  wr.ApplyPadding();
×
565
  wr.Write(main.bounds);
×
566
  wr.Write(main.metadata);
567
  wr.Seek(eof);
568
  wr.ApplyPadding();
569
}
570
#pragma endregion
×
571
#pragma region Loaders
×
572

573
template <class Header, class Traits>
574
MODImpl::ptr LoadMODX70(BinReaderRef_e rd) {
×
575
  Header header;
×
576
  MODInner<Traits> main;
×
577
  rd.Read(header);
×
578
  rd.ApplyPadding();
×
579
  rd.Read(main.bounds);
×
580
  rd.Read(main.metadata);
×
581
  header.numIndices--;
×
582

×
583
  if (header.numBones) {
584
    rd.Seek(header.bones);
585
    rd.ReadContainer(main.bones, header.numBones);
×
586
    rd.ReadContainer(main.refPoses, header.numBones);
×
587
    rd.ReadContainer(main.transforms, header.numBones);
588
  }
589

×
590
  rd.Seek(header.textures);
×
591
  rd.ReadContainerLambda(main.paths, header.numTextures,
×
592
                         [](BinReaderRef_e rd, std::string &p) {
×
593
                           MODPath<Traits::pathSize> path;
×
594
                           rd.Read(path);
×
595
                           p = path.path;
×
596
                         });
×
597
  rd.ReadContainer(main.materials, header.numMaterials);
×
598

599
  rd.Seek(header.meshes);
600
  rd.ReadContainer(main.meshes, header.numMeshes);
×
601

×
602
  main.unkBufferSize = header.unkBufferSize;
603

604
  main.vertexBuffer.resize(header.vertexBufferSize + main.unkBufferSize);
×
605

×
606
  rd.Seek(header.vertexBuffer);
×
607
  rd.ReadBuffer(main.vertexBuffer.data(), header.vertexBufferSize);
×
608

×
609
  if (header.unkBufferSize) {
×
610
    rd.Seek(header.unkBuffer);
×
611
    rd.ReadBuffer(main.vertexBuffer.data() + header.vertexBufferSize,
×
612
                  header.unkBufferSize);
×
613
  }
614

615
  rd.Seek(header.indices);
×
616
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
617

618
  return std::make_unique<decltype(main)>(std::move(main));
619
}
×
620

×
621
MODImpl::ptr LoadMODXC5(BinReaderRef_e rd) {
×
622
  MODHeaderXC5 header;
×
623
  MODInner<MODTraitsXC5> main;
×
624
  rd.Read(header);
×
625
  rd.ApplyPadding();
×
626
  rd.Read(main.bounds);
×
627
  rd.Read(main.metadata);
×
628

629
  if (header.numBones) {
630
    rd.Seek(header.bones);
631
    rd.ReadContainer(main.bones, header.numBones);
632
    rd.ReadContainer(main.refPoses, header.numBones);
633
    rd.ReadContainer(main.transforms, header.numBones);
×
634
    rd.Read(main.remaps);
×
635
  }
×
636

637
  if (header.numGroups) {
638
    rd.Seek(header.groups);
×
639
    rd.ReadContainer(main.groups, header.numGroups);
×
640
  }
×
641

×
642
  rd.Seek(header.textures);
643
  rd.ReadContainerLambda(main.paths, header.numTextures,
644
                         [](BinReaderRef_e rd, std::string &p) {
×
645
                           MODPath<MODTraitsXC5::pathSize> path;
×
646
                           rd.Read(path);
×
647
                           p = path.path;
×
648
                         });
×
649
  rd.ReadContainer(main.materials, header.numMaterials);
650

651
  rd.Seek(header.meshes);
×
652
  rd.ReadContainer(main.meshes, header.numMeshes);
×
653
  rd.ReadContainer(main.envelopes);
×
654

×
655
  rd.Seek(header.vertexBuffer);
656
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
657

×
658
  rd.Seek(header.indices);
×
659
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
660

661
  return std::make_unique<decltype(main)>(std::move(main));
662
}
663

×
664
MODImpl::ptr LoadMODXC3(BinReaderRef_e rd) {
×
665
  MODHeaderXC5 header;
×
666
  MODInner<MODTraitsXC5> main;
667
  rd.Read(header);
668
  rd.ApplyPadding();
×
669
  rd.Read(main.bounds);
×
670
  rd.Read(main.metadata);
×
671

×
672
  if (header.numBones) {
673
    rd.Seek(header.bones);
674
    rd.ReadContainer(main.bones, header.numBones);
×
675
    rd.ReadContainer(main.refPoses, header.numBones);
×
676
    rd.ReadContainer(main.transforms, header.numBones);
×
677
    rd.Read(main.remaps);
678
  }
679

×
680
  if (header.numGroups) {
×
681
    rd.Seek(header.groups);
682
    rd.ReadContainer(main.groups, header.numGroups);
683
  }
×
684

×
685
  rd.Seek(header.textures);
686
  rd.ReadContainerLambda(main.paths, header.numTextures,
687
                         [](BinReaderRef_e rd, std::string &p) {
×
688
                           MODPath<MODTraitsXC5::pathSize> path;
×
689
                           rd.Read(path);
690
                           p = path.path;
691
                         });
×
692
  rd.ReadContainer(main.materials, header.numMaterials);
×
693

×
694
  rd.Seek(header.meshes);
×
695
  rd.ReadContainerLambda(main.meshes, header.numMeshes,
×
696
                         [](BinReaderRef_e rd, auto &m) {
×
697
                           rd.Read(m);
×
698
                           rd.Skip(8);
×
699
                         });
×
700
  rd.ReadContainer(main.envelopes);
701

702
  rd.Seek(header.vertexBuffer);
×
703
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
704

×
705
  rd.Seek(header.indices);
×
706
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
707

×
708
  return std::make_unique<decltype(main)>(std::move(main));
×
709
}
×
710

×
711
template <class Traits> MODImpl::ptr LoadMODX99(BinReaderRef_e rd) {
×
712
  MODHeaderX99 header;
×
713
  MODInner<Traits> main;
×
714
  rd.Read(header);
×
715
  rd.ApplyPadding();
×
716
  rd.Read(main.bounds);
717
  rd.Read(main.metadata);
718
  header.numIndices--;
×
719

×
720
  if (header.numBones) {
×
721
    rd.Seek(header.bones);
×
722
    rd.ReadContainer(main.bones, header.numBones);
×
723
    rd.ReadContainer(main.refPoses, header.numBones);
×
724
    rd.ReadContainer(main.transforms, header.numBones);
×
725
    rd.Read(main.remaps);
×
726
    rd.ReadContainer(main.skinRemaps, header.numBoneMaps);
×
727
  }
×
728

×
729
  if (header.numGroups) {
730
    rd.Seek(header.groups);
731
    rd.ReadContainer(main.groups, header.numGroups);
×
732
  }
×
733

×
734
  rd.Seek(header.textures);
×
735
  rd.ReadContainerLambda(main.paths, header.numTextures,
×
736
                         [](BinReaderRef_e rd, std::string &p) {
×
737
                           MODPath<Traits::pathSize> path;
×
738
                           rd.Read(path);
×
739
                           p = path.path;
×
740
                         });
×
741
  rd.ReadContainer(main.materials, header.numMaterials);
×
742

×
743
  rd.Seek(header.meshes);
744
  rd.ReadContainer(main.meshes, header.numMeshes);
745
  rd.ReadContainer(main.envelopes);
×
746

×
747
  main.unkBufferSize = header.unkBufferSize;
×
748

×
749
  main.vertexBuffer.resize(header.vertexBufferSize + main.unkBufferSize);
×
750

×
751
  rd.Seek(header.vertexBuffer);
×
752
  rd.ReadBuffer(main.vertexBuffer.data(), header.vertexBufferSize);
×
753

×
754
  if (header.unkBufferSize) {
×
755
    rd.Seek(header.unkBuffer);
×
756
    rd.ReadBuffer(main.vertexBuffer.data() + header.vertexBufferSize,
757
                  header.unkBufferSize);
758
  }
×
759

×
760
  rd.Seek(header.indices);
×
761
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
762

×
763
  return std::make_unique<decltype(main)>(std::move(main));
×
764
}
×
765

×
766
template <class Traits> MODImpl::ptr LoadMODXD2x32(BinReaderRef_e rd) {
×
767
  MODHeaderXDx32 header;
×
768
  MODInner<Traits> main;
×
769
  rd.Read(header);
×
770
  rd.ApplyPadding();
771
  rd.Read(main.bounds);
772
  rd.Read(main.metadata);
×
773

×
774
  if (header.bones > 0 && header.bones <= 0x80) {
×
775
    // UMVC3 PS3 uses unique model
×
776
    throw std::runtime_error("Unsupported model format");
×
777
  }
×
778

×
779
  if (header.numBones) {
×
780
    rd.Seek(header.bones);
×
781
    rd.ReadContainer(main.bones, header.numBones);
×
782
    rd.ReadContainer(main.refPoses, header.numBones);
×
783
    rd.ReadContainer(main.transforms, header.numBones);
784
    rd.Read(main.remaps);
785
  }
×
786

×
787
  if (header.numGroups) {
×
788
    rd.Seek(header.groups);
×
789
    rd.ReadContainer(main.groups, header.numGroups);
×
790
  }
×
791

×
792
  rd.ReadContainer(main.materials, header.numMaterials);
×
793

×
794
  rd.Seek(header.meshes);
×
795
  rd.ReadContainerLambda(main.meshes, header.numMeshes,
×
796
                         [](BinReaderRef_e rd, auto &m) {
×
797
                           rd.Read(m);
×
798
                           rd.Skip(8);
799
                         });
800

×
801
  if constexpr (std::is_same_v<MODMetaDataV2, typename Traits::metadata>) {
×
802
    rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes);
×
803
  } else {
×
804
    rd.ReadContainer(main.envelopes);
×
805
  }
×
806

×
807
  rd.Seek(header.vertexBuffer);
×
808
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
809

×
810
  rd.Seek(header.indices);
×
811
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
812

×
813
  return std::make_unique<decltype(main)>(std::move(main));
×
814
}
×
815

×
816
template <class Traits> MODImpl::ptr LoadMODXDxLEx32(BinReaderRef_e rdn) {
×
817
  BinReaderRef rd(rdn);
×
818
  MODHeaderXDx32 header;
×
819
  MODInner<Traits> main;
×
820
  rd.Read(header);
×
821
  rd.ApplyPadding();
×
822
  rd.Read(main.bounds);
×
823
  rd.Read(main.metadata);
×
824

×
825
  if (header.numBones) {
826
    rd.Seek(header.bones);
827
    rd.ReadContainer(main.bones, header.numBones);
×
828
    rd.ReadContainer(main.refPoses, header.numBones);
×
829
    rd.ReadContainer(main.transforms, header.numBones);
830
    rd.Read(main.remaps);
×
831
  }
×
832

×
833
  if (header.numGroups) {
×
834
    rd.Seek(header.groups);
×
835
    rd.ReadContainer(main.groups, header.numGroups);
×
836
  }
×
837

×
838
  rdn.ReadContainer(main.materials, header.numMaterials);
×
839

×
840
  rd.Seek(header.meshes);
×
841
  rd.ReadContainer(main.meshes, header.numMeshes);
×
842

×
843
  if constexpr (std::is_same_v<MODMetaDataV2, typename Traits::metadata>) {
×
844
    rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes);
×
845
  } else {
×
846
    rd.ReadContainer(main.envelopes);
×
847
  }
×
848

×
849
  rd.Seek(header.vertexBuffer);
×
850
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
851

×
852
  rd.Seek(header.indices);
×
853
  rd.ReadContainer(main.indexBuffer, header.numIndices);
854

855
  return std::make_unique<decltype(main)>(std::move(main));
×
856
}
×
857

858
template <class Traits, class TraitsFallback>
×
859
MODImpl::ptr LoadMODXDxLE(BinReaderRef_e rdn) {
×
860
  BinReaderRef rd(rdn);
×
861
  MODHeaderXDx64 header;
×
862
  MODInner<Traits> main;
×
863
  rd.Push();
×
864
  rd.Read(header);
×
865
  rd.ApplyPadding();
×
866
  rd.Read(main.bounds);
×
867
  rd.Read(main.metadata);
×
868
  {
×
869
    uint64 maxPtr = header.bones | header.groups | header.materialNames |
×
870
                    header.meshes | header.vertexBuffer | header.indices |
×
871
                    header.dataEnd;
×
872
    size_t fileSize = rd.GetSize() << 1;
×
873

×
874
    if (maxPtr > fileSize) {
×
875
      rd.Pop();
×
876
      return LoadMODXDxLEx32<TraitsFallback>(rd);
×
877
    }
×
878
  }
×
879

×
880
  if (header.numBones) {
×
881
    rd.Seek(header.bones);
×
882
    rd.ReadContainer(main.bones, header.numBones);
883
    rd.ReadContainer(main.refPoses, header.numBones);
884
    rd.ReadContainer(main.transforms, header.numBones);
×
885
    rd.Read(main.remaps);
×
886
  }
887

888
  if (header.numGroups) {
×
889
    rd.Seek(header.groups);
×
890
    rd.ReadContainer(main.groups, header.numGroups);
×
891
  }
×
892

×
893
  rdn.ReadContainer(main.materials, header.numMaterials);
×
894

×
895
  rd.Seek(header.meshes);
×
896
  rdn.ReadContainerLambda(main.meshes, header.numMeshes,
×
897
                          [](BinReaderRef_e rd, auto &m) {
×
898
                            rd.Read(m);
×
899
                            rd.Skip(8);
×
900
                          });
×
901
  rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes);
902

903
  rd.Seek(header.vertexBuffer);
×
904
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
905

×
906
  rd.Seek(header.indices);
×
907
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
908

×
909
  return std::make_unique<decltype(main)>(std::move(main));
×
910
}
×
911

×
912
MODImpl::ptr LoadMODX06(BinReaderRef_e rdn) {
×
913
  MODHeaderX06 header;
×
914
  MODInner<MODTraitsX06> main;
×
915
  BinReaderRef rd(rdn);
916
  rd.Push();
917
  rd.Read(header);
×
918
  rd.ApplyPadding();
×
919
  rd.Read(main.bounds);
×
920
  rd.Read(main.metadata);
×
921

922
  if (header.numBones) {
×
923
    rd.Seek(header.bones);
×
924
    rd.ReadContainer(main.bones, header.numBones);
×
925
    rd.ReadContainer(main.refPoses, header.numBones);
×
926
    rd.ReadContainer(main.transforms, header.numBones);
×
927
    rd.Read(main.remaps);
×
928
    rd.ReadContainer(main.skinRemaps, header.numSkins);
×
929
  }
×
930

×
931
  if (header.numGroups) {
×
932
    rd.Seek(header.groups);
×
933
    rd.ReadContainer(main.groups, header.numGroups);
934
  }
935

×
936
  rdn.ReadContainer(main.materials, header.numMaterials);
×
937

×
938
  rd.Seek(header.meshes);
×
939
  rdn.ReadContainerLambda(main.meshes, header.numMeshes,
940
                          [](BinReaderRef_e rd, auto &m) {
×
941
                            rd.Read(m);
×
942
                            rd.Skip(8);
×
943
                          });
×
944
  rd.ReadContainer(main.envelopes);
×
945

×
946
  rd.Seek(header.vertexBuffer);
×
947
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
948

×
949
  rd.Seek(header.indices);
950
  rd.ReadContainer(main.indexBuffer, header.numIndices);
951

952
  return std::make_unique<decltype(main)>(std::move(main));
×
953
}
×
954

955
MODImpl::ptr LoadMODXE5(BinReaderRef_e rd) {
956
  MODHeaderXE5 header;
957
  MODInner<MODTraitsXE5> main;
958
  rd.Push();
×
959
  rd.Read(header);
×
960
  rd.ApplyPadding();
×
961
  rd.Read(main.bounds);
×
962
  rd.Read(main.metadata);
963

×
964
  if (header.numBones) {
×
965
    rd.Seek(header.bones);
×
966
    rd.ReadContainer(main.bones, header.numBones);
×
967
    rd.ReadContainer(main.refPoses, header.numBones);
968
    rd.ReadContainer(main.transforms, header.numBones);
×
969
    rd.Read(main.remaps);
970
    rd.ReadContainer(main.skinRemaps, header.numSkins);
×
971
  }
×
972

×
973
  if (header.numGroups) {
×
974
    rd.Seek(header.groups);
×
975
    rd.ReadContainer(main.groups, header.numGroups);
×
976
  }
×
977

×
978
  rd.ReadContainer(main.materials, header.numMaterials);
979

980
  rd.Seek(header.meshes);
×
981
  rd.ReadContainer(main.meshes, header.numMeshes);
×
982
  rd.ReadContainer(main.envelopes);
983

×
984
  rd.Seek(header.vertexBuffer);
×
985
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
986

987
  rd.Seek(header.indices);
988
  rd.ReadContainer(main.indexBuffer, header.numIndices);
×
989

×
990
  return std::make_unique<decltype(main)>(std::move(main));
×
991
}
992

×
993
MODImpl::ptr LoadMODXFF2C(BinReaderRef_e rd) {
×
994
  MODHeaderXE5 header;
×
995
  MODInner<MODTraitsXD3LE> main;
996
  rd.Push();
×
997
  rd.Read(header);
998
  rd.ApplyPadding();
999
  rd.Read(main.bounds);
1000
  rd.Read(main.metadata);
1001

×
1002
  if (header.numBones) {
×
1003
    rd.Seek(header.bones);
×
1004
    rd.ReadContainer(main.bones, header.numBones);
×
1005
    rd.ReadContainer(main.refPoses, header.numBones);
×
1006
    rd.ReadContainer(main.transforms, header.numBones);
×
1007
    rd.Read(main.remaps);
×
1008
  }
×
1009

×
1010
  if (header.numGroups) {
×
1011
    rd.Seek(header.groups);
1012
    rd.ReadContainer(main.groups, header.numGroups);
×
1013
  }
×
1014

×
1015
  rd.ReadContainer(main.materials, header.numMaterials);
×
1016

×
1017
  rd.Seek(header.meshes);
1018
  rd.ReadContainerLambda(main.meshes, header.numMeshes,
1019
                         [](BinReaderRef_e rd, auto &m) {
×
1020
                           rd.Read(m);
×
1021
                           rd.Skip(8);
×
1022
                         });
×
1023
  rd.ReadContainer(main.envelopes);
1024

1025
  rd.Seek(header.vertexBuffer);
1026
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
1027

×
1028
  rd.Seek(header.indices);
×
1029
  rd.ReadContainer(main.indexBuffer, header.numIndices);
1030

×
1031
  return std::make_unique<decltype(main)>(std::move(main));
1032
}
1033

×
1034
std::vector<MODMaterialProxy<MODMaterialX21>>
×
1035
XFSToMaterials(const revil::XFS &main) {
×
1036
  pugi::xml_document root;
×
1037
  main.ToXML(root);
1038
  std::vector<MODMaterialProxy<MODMaterialX21>> retval;
×
1039
  auto mtArr = root.child("class").child("array");
×
1040
  retval.resize(mtArr.attribute("count").as_int());
×
1041

×
1042
  for (uint32 curMat = 0; auto &c : mtArr.children()) {
1043
    auto &mat = retval.at(curMat++).main;
×
1044
    mat.name = "Material_";
1045
    mat.name.append(c.find_child_by_attribute("name", "mTagID")
×
1046
                        .attribute("value")
×
1047
                        .as_string());
×
1048
  }
×
1049

×
1050
  return retval;
×
1051
}
1052

1053
MODImpl::ptr LoadMODX21(BinReaderRef_e rd) {
×
1054
  MODHeaderX21 header;
×
1055
  MODInner<MODTraitsX21> main;
1056
  rd.Push();
×
1057
  rd.Read(header);
×
1058
  rd.ApplyPadding();
×
1059
  rd.Read(main.bounds);
1060
  rd.Read(main.metadata);
1061

×
1062
  if (header.numBones) {
×
1063
    rd.Seek(header.bones);
×
1064
    rd.ReadContainer(main.bones, header.numBones);
1065
    rd.ReadContainer(main.refPoses, header.numBones);
×
1066
    rd.ReadContainer(main.transforms, header.numBones);
×
1067
    rd.Read(main.remaps);
×
1068
    // skins??
1069
  }
×
1070

1071
  if (header.numGroups) {
1072
    rd.Seek(header.groups);
1073
    rd.ReadContainer(main.groups, header.numGroups);
1074
  }
×
1075

×
1076
  rd.Seek(header.materials);
×
1077
  revil::XFS materials;
×
1078
  materials.Load(rd, true);
×
1079
  main.materials = XFSToMaterials(materials);
×
1080

×
1081
  rd.Seek(header.meshes);
×
1082
  rd.ReadContainer(main.meshes, header.numMeshes);
1083
  rd.ReadContainer(main.envelopes);
×
1084

×
1085
  rd.Seek(header.vertexBuffer);
×
1086
  rd.ReadContainer(main.vertexBuffer, header.vertexBufferSize);
×
1087

1088
  rd.Seek(header.indices);
1089
  rd.ReadContainer(main.indexBuffer, header.numIndices);
1090

×
1091
  return std::make_unique<decltype(main)>(std::move(main));
×
1092
}
×
1093

1094
#pragma endregion
×
1095

1096
bool MODMaker::operator<(const MODMaker &i0) const {
1097
  return reinterpret_cast<const uint64 &>(*this) <
1098
         reinterpret_cast<const uint64 &>(i0);
1099
}
1100

×
1101
static const std::map<MODMaker, MODImpl::ptr (*)(BinReaderRef_e)> modLoaders{
1102
    {{MODVersion::X70, true}, LoadMODX70<MODHeaderX70, MODTraitsX70>},
1103
    {{MODVersion::X170}, LoadMODX70<MODHeaderX170, MODTraitsX170>},
×
1104
    {{MODVersion::X99}, LoadMODX99<MODTraitsX99LE>},
×
1105
    {{MODVersion::X19C}, LoadMODX99<MODTraitsX99LE>},
×
1106
    {{MODVersion::X99, true}, LoadMODX99<MODTraitsX99BE>},
×
1107
    {{MODVersion::XC3, true}, LoadMODXC3},
×
1108
    {{MODVersion::XC5}, LoadMODXC5},
1109
    {{MODVersion::XD2}, LoadMODXDxLEx32<MODTraitsXD2>},
×
1110
    {{MODVersion::XD3}, LoadMODXDxLE<MODTraitsXD3x64, MODTraitsXD3LE>},
×
1111
    {{MODVersion::XD6},
×
1112
     LoadMODXDxLE<MODTraitsXD6, MODTraitsXD3LE>}, // unused fallback
×
1113
    {{MODVersion::XD4},
×
1114
     LoadMODXDxLEx32<MODTraitsXD3PS4>}, // todo normals (different traits)
1115

1116
    {{MODVersion::XD2, true}, LoadMODXD2x32<MODTraitsXD2>},
×
1117
    {{MODVersion::XD3, true}, LoadMODXD2x32<MODTraitsXD2>},
×
1118
    {{MODVersion::XD4, true}, LoadMODXD2x32<MODTraitsXD2>},
1119
    {{MODVersion::X05}, LoadMODX06},
1120
    {{MODVersion::X06}, LoadMODX06},
1121
    {{MODVersion::XE5, true}, LoadMODXE5},
1122
    {{MODVersion::XE5}, LoadMODXE5},
1123
    {{MODVersion::XE6, true}, LoadMODXE5},
×
1124
    {{MODVersion::XE6}, LoadMODXE5},
1125
    {{MODVersion::XE7}, LoadMODXE5},
×
1126
    {{MODVersion::XFF2C, true}, LoadMODXFF2C},
×
1127
    {{MODVersion::X21, true}, LoadMODX21},
1128
};
×
1129

1130
template <class C> MODImpl::ptr makeMod() {
×
1131
  return std::make_unique<MODInner<C>>();
1132
}
×
1133

×
1134
static const std::map<MODMaker, MODImpl::ptr (*)()> modMakers{
1135
    {{MODVersion::X70, true}, makeMod<MODTraitsX70>},
×
1136
};
×
1137

×
1138
MOD::MOD(MODMaker make) {
×
1139
  auto found = modMakers.find(make);
1140

1141
  if (es::IsEnd(modMakers, found)) {
×
1142
    throw std::runtime_error("Cannon find specified MODMaker instance.");
×
1143
  }
1144

×
1145
  pi = found->second();
1146
}
×
1147

1148
void MOD::Load(const std::string &fileName) {
1149
  BinReader rd(fileName);
×
1150
  Load(rd);
×
1151
}
×
1152

×
1153
void MOD::Load(BinReaderRef_e rd) {
×
1154
  MODHeaderCommon header;
1155
  rd.Push();
×
1156
  rd.Read(header);
×
1157
  rd.Pop();
×
1158

×
1159
  if (header.id == DOMID || header.id == RMDID) {
×
1160
    rd.SwapEndian(true);
1161
    FByteswapper(header);
1162
  } else if (header.id != MODID) {
×
1163
    throw es::InvalidHeaderError(header.id);
×
1164
  }
1165

1166
  MODMaker mk;
1167
  mk.version = static_cast<MODVersion>(header.version);
1168
  mk.swappedEndian = rd.SwappedEndian();
1169

×
1170
  auto found = modLoaders.find(mk);
1171

×
1172
  if (es::IsEnd(modLoaders, found)) {
×
1173
    throw es::InvalidVersionError(mk.version);
1174
  }
×
1175

1176
  pi = found->second(rd);
×
1177
  pi->Reflect(rd.SwappedEndian());
1178
}
×
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