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

PredatorCZ / RevilLib / 175

19 Nov 2025 10:16PM UTC coverage: 10.614% (-0.5%) from 11.16%
175

push

github

PredatorCZ
add more mtf texture support

0 of 139 new or added lines in 2 files covered. (0.0%)

639 existing lines in 6 files now uncovered.

757 of 7132 relevant lines covered (10.61%)

6360.16 hits per line

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

0.0
/src/tex.cpp
1
/*  Revil Format Library
2
    Copyright(C) 2020-2025 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 "tex.hpp"
19
#include "hfs.hpp"
20
#include "revil/tex.hpp"
21
#include "spike/except.hpp"
22
#include "spike/format/DDS.hpp"
23
#include "spike/io/binreader_stream.hpp"
24
#include <map>
25

26
using namespace revil;
27

UNCOV
28
TexelInputFormat ConvertTEXFormat(TEXFormat fmt) {
×
29
  TexelInputFormat retVal;
30

31
  switch (fmt) {
×
32
  case TEXFormat::DXT1:
33
    retVal.type = TexelInputFormatType::BC1;
34
    break;
35
  case TEXFormat::DXT2:
×
36
    retVal.type = TexelInputFormatType::BC2;
37
    retVal.premultAlpha = true;
38
    break;
×
39
  case TEXFormat::DXT3:
×
40
    retVal.type = TexelInputFormatType::BC2;
41
    break;
×
42
  case TEXFormat::DXT5:
×
43
    retVal.type = TexelInputFormatType::BC3;
44
    break;
×
45
  case TEXFormat::RGBA8_PACKED:
×
46
    retVal.type = TexelInputFormatType::RGBA8;
47
    break;
×
48
  case TEXFormat::RG8_SNORM:
×
49
    retVal.type = TexelInputFormatType::RG8;
50
    retVal.snorm = true;
51
    break;
×
52

53
  default:
×
NEW
54
    throw es::RuntimeError("Unknown texture format!");
×
55
  }
56

57
  return retVal;
×
58
}
59

NEW
60
TexelInputFormat ConvertTEXFormat(TEXFormatV2 fmt, Platform platform) {
×
61
  TexelInputFormat retVal;
62

63
  switch (fmt) {
×
64
  case TEXFormatV2::BC1:
65
  case TEXFormatV2::COMPRESSED_NORMAL_MAP:
66
  case TEXFormatV2::BC1A:
67
    retVal.type = TexelInputFormatType::BC1;
68
    break;
NEW
69
  case TEXFormatV2::COMPRESSED_GRAYSCALE:
×
NEW
70
    retVal.type = platform == Platform::PS4 || platform == Platform::NSW
×
NEW
71
                      ? TexelInputFormatType::BC4
×
72
                      : TexelInputFormatType::BC1;
73
    break;
74
  case TEXFormatV2::BC2:
75
  case TEXFormatV2::BC2_PA:
76
    retVal.type = TexelInputFormatType::BC2;
77
    break;
78
  case TEXFormatV2::BC3:
79
  case TEXFormatV2::BC3_LM:
80
  case TEXFormatV2::BC3_PM:
81
  case TEXFormatV2::BC3_YUV:
82
  case TEXFormatV2::BC3_CM:
83
  case TEXFormatV2::BC3_PA:
84
  case TEXFormatV2::BC3_YUV_PA:
85
  case TEXFormatV2::BC3_EFF:
86
    retVal.type = TexelInputFormatType::BC3;
87
    break;
88

NEW
89
  case TEXFormatV2::COMPRESSED_DERIVED_NORMAL_MAP:
×
NEW
90
    retVal.type = platform == Platform::PS4 || platform == Platform::NSW
×
NEW
91
                      ? TexelInputFormatType::BC5
×
92
                      : TexelInputFormatType::BC3;
93
    break;
UNCOV
94
  case TEXFormatV2::RGBA16F:
×
95
    retVal.type = TexelInputFormatType::RGBA16;
96
    break;
×
97
  case TEXFormatV2::RGBA8:
×
98
  case TEXFormatV2::RGBA8_PA:
99
  case TEXFormatV2::RGBA8_LP4:
100
    retVal.type = TexelInputFormatType::RGBA8;
101
    break;
×
102
  case TEXFormatV2::R8:
×
103
    retVal.type = TexelInputFormatType::R8;
104
    break;
×
NEW
105
  case TEXFormatV2::BC7_PA:
×
106
  case TEXFormatV2::BC7:
107
    retVal.type = TexelInputFormatType::BC7;
NEW
108
    break;
×
NEW
109
  case TEXFormatV2::RGB10A2:
×
110
    retVal.type = TexelInputFormatType::RGB10A2;
NEW
111
    break;
×
112
  default:
×
NEW
113
    throw es::RuntimeError("Unknown texture format!");
×
114
  }
115

116
  return retVal;
×
117
}
118

NEW
119
TexelInputFormat ConvertTEXFormat(TEXFormat3DS fmt) {
×
120
  TexelInputFormat retVal;
121

122
  switch (fmt) {
×
123
  case TEXFormat3DS::IA8:
124
    retVal.type = TexelInputFormatType::RG8;
125
    retVal.swizzle.r = TexelSwizzleType::Red;
126
    retVal.swizzle.g = TexelSwizzleType::Red;
127
    retVal.swizzle.b = TexelSwizzleType::Red;
128
    retVal.swizzle.a = TexelSwizzleType::Green;
129
    break;
NEW
130
  case TEXFormat3DS::ETC1:
×
131
    retVal.type = TexelInputFormatType::ETC1;
132
    break;
×
NEW
133
  case TEXFormat3DS::ETC1A4:
×
134
    retVal.type = TexelInputFormatType::ETC1A4;
135
    break;
×
NEW
136
  case TEXFormat3DS::A4:
×
137
  case TEXFormat3DS::L4:
138
    retVal.type = TexelInputFormatType::R4;
139
    break;
×
NEW
140
  case TEXFormat3DS::RGB8:
×
141
    retVal.type = TexelInputFormatType::RGB8;
142
    break;
×
NEW
143
  case TEXFormat3DS::RGBA8:
×
144
    retVal.type = TexelInputFormatType::RGBA8;
145
    retVal.swizzle.r = TexelSwizzleType::Alpha;
146
    retVal.swizzle.g = TexelSwizzleType::Red;
147
    retVal.swizzle.b = TexelSwizzleType::Green;
148
    retVal.swizzle.a = TexelSwizzleType::Blue;
149
    break;
×
NEW
150
  case TEXFormat3DS::RGBA4:
×
151
    retVal.type = TexelInputFormatType::RGBA4;
152
    break;
×
NEW
153
  case TEXFormat3DS::R5G6B5:
×
154
    retVal.type = TexelInputFormatType::R5G6B5;
155
    break;
×
NEW
156
  case TEXFormat3DS::R8:
×
157
    retVal.type = TexelInputFormatType::R8;
158
    break;
×
NEW
159
  case TEXFormat3DS::RG4:
×
160
    retVal.type = TexelInputFormatType::RG4;
161
    break;
×
NEW
162
  case TEXFormat3DS::AL4:
×
163
    retVal.type = TexelInputFormatType::RG4;
164
    retVal.swizzle.r = TexelSwizzleType::Red;
165
    retVal.swizzle.g = TexelSwizzleType::Red;
166
    retVal.swizzle.b = TexelSwizzleType::Red;
167
    retVal.swizzle.a = TexelSwizzleType::Green;
168
    break;
×
169

170
  default:
×
NEW
171
    throw es::RuntimeError("Unknown texture format!");
×
172
  }
173

174
  return retVal;
×
175
}
176

177
void ApplyModifications(NewTexelContextCreate &ctx, Platform platform) {
×
178
  if (ctx.baseFormat.type == TexelInputFormatType::RGBA8 &&
×
179
      platform == Platform::PS3 && IsPow2(ctx.width) && IsPow2(ctx.height)) {
×
180
    ctx.baseFormat.tile = TexelTile::Morton;
×
181
  } else if (platform == Platform::PS4) {
×
NEW
182
    ctx.baseFormat.tile = TexelTile::PS4;
×
183
  } else if (platform == Platform::NSW) {
×
184
    ctx.baseFormat.tile = TexelTile::NX;
×
185
  }
186
}
187

188
TEX LoadTEXx56(BinReaderRef_e rd) {
×
189
  TEX main;
190
  TEXx56 header;
191
  rd.Read(header);
×
192

193
  if (header.layout == TEXx56::TextureLayout::Corrected) {
×
194
    rd.Read(main.color);
×
195
  }
196

197
  if (header.type == TextureType::Volume) {
×
198
    BinReaderRef rdn(rd);
199
    DDS_Header ddsHdr;
200
    DDS_PixelFormat ddsPf;
×
201
    DDS_HeaderEnd ddsFt;
×
202
    rdn.Read(ddsHdr);
203
    rdn.Read(ddsPf);
204
    rdn.Read(ddsFt);
205

206
    main.ctx.width = ddsHdr.width;
×
207
    main.ctx.height = ddsHdr.height;
×
208
    main.ctx.depth = ddsHdr.depth;
×
209
    main.ctx.numMipmaps = ddsHdr.mipMapCount;
×
210

211
    if (ddsPf == DDSFormat_DXT5) {
×
212
      main.ctx.baseFormat.type = TexelInputFormatType::BC3;
×
213
    } else {
NEW
214
      throw es::RuntimeError("Unknown texture format!");
×
215
    }
216
  } else if (header.type == TextureType::Cubemap) {
×
NEW
217
    throw es::RuntimeError("Cubemaps are not supported.");
×
218
  } else {
219
    main.ctx.width = header.width;
×
220
    main.ctx.height = header.height;
×
221
    main.ctx.depth = header.arraySize;
×
222
    main.ctx.numMipmaps = header.numMips;
×
223
    main.ctx.baseFormat = ConvertTEXFormat(header.fourcc);
×
224
  }
225

226
  size_t bufferSize = rd.GetSize() - rd.Tell();
×
227
  rd.ReadContainer(main.buffer, bufferSize);
×
228
  ApplyModifications(main.ctx, Platform::Win32);
229

230
  return main;
×
231
}
×
232

233
template <class header_type>
234
TEX LoadTEXx66(BinReaderRef_e rd, Platform platform) {
×
235
  TEX main;
236
  header_type header;
237
  rd.Read(header);
×
238

239
  main.ctx.width = header.width;
×
240
  main.ctx.height = header.height;
×
241
  main.ctx.depth = std::max(1, int(header.arraySize));
×
242
  main.ctx.numMipmaps = header.numMips;
×
243
  main.ctx.baseFormat = ConvertTEXFormat(header.fourcc);
×
244
  main.color = Vector4A16(header.colorCorrection);
×
245

246
  TextureType type = static_cast<TextureType>(
247
      header.type.template Get<typename header_type::TextureType>());
248

249
  if (type == TextureType::Cubemap) {
×
250
    main.ctx.numFaces = 6;
×
251
    rd.Read(main.harmonics);
×
252
  }
253

254
  rd.ReadContainer(main.offsets, header.numFaces * header.numMips);
×
255
  uint32 bufferBegin = rd.Tell();
×
256

257
  for (uint32 &o : main.offsets) {
×
258
    o -= bufferBegin;
×
259
  }
260

261
  size_t bufferSize = rd.GetSize() - bufferBegin;
×
262

263
  rd.ReadContainer(main.buffer, bufferSize);
×
264
  ApplyModifications(main.ctx, platform);
×
265

266
  if (rd.SwappedEndian() &&
×
267
      main.ctx.baseFormat.type == TexelInputFormatType::RGBA8) {
×
268
    main.ctx.baseFormat.swapPacked = true;
×
269
  }
270

271
  return main;
×
272
}
×
273

×
274
TEX LoadTEXx87(BinReaderRef_e rd, Platform platform) {
275
  TEX main;
276
  TEXx87 header;
×
277
  rd.Read(header);
278
  using t = TEXx87;
×
279

×
280
  main.ctx.width = header.tier0.Get<t::Width>();
×
281
  main.ctx.height = header.tier1.Get<t::Height>();
×
282
  main.ctx.depth = header.tier1.Get<t::Depth>();
×
283
  main.ctx.numMipmaps = header.tier0.Get<t::NumMips>();
×
284
  main.ctx.baseFormat = ConvertTEXFormat(header.format, platform);
285

286
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
287

288
  if (type == TextureTypeV2::Cubemap) {
×
289
    main.ctx.numFaces = 6;
×
290
    rd.Read(main.harmonics);
×
291
  }
292

293
  uint32 numOffsets =
×
294
      std::max(int8(1), main.ctx.numFaces) * main.ctx.numMipmaps;
×
295
  rd.ReadContainer(main.offsets, numOffsets);
296

×
297
  uint32 bufferBegin = rd.Tell();
×
298

299
  for (uint32 &o : main.offsets) {
300
    o -= bufferBegin;
×
301
  }
302

×
303
  size_t bufferSize = rd.GetSize() - bufferBegin;
×
304
  rd.ReadContainer(main.buffer, bufferSize);
305
  ApplyModifications(main.ctx, platform);
×
306

×
307
  if (rd.SwappedEndian() &&
×
308
      main.ctx.baseFormat.type == TexelInputFormatType::RGBA8) {
309
    main.ctx.baseFormat.swapPacked = true;
310
  }
×
311

×
312
  return main;
×
313
}
314

315
TEX LoadTEXx9D(BinReaderRef_e rd, Platform platform) {
×
316
  TEX main;
317
  TEXx9D header;
×
318
  rd.Read(header);
×
319
  using t = TEXx9D;
×
320

×
321
  main.ctx.width = header.tier1.Get<t::Width>();
×
322
  main.ctx.height = header.tier1.Get<t::Height>();
×
323
  main.ctx.depth = header.depth;
324
  main.ctx.numMipmaps = header.tier1.Get<t::NumMips>();
325

326
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
327

×
328
  if (type == TextureTypeV2::Cubemap) {
×
329
    main.ctx.numFaces = 6;
×
330
    rd.Read(main.harmonics);
331
  }
332

×
333
  uint32 numOffsets =
×
334
      std::max(int8(1), main.ctx.numFaces) * main.ctx.numMipmaps;
335

×
336
  auto fallback = [&] {
×
337
    rd.ReadContainer(main.offsets, numOffsets);
338
    main.ctx.baseFormat = ConvertTEXFormat(header.format, platform);
339
  };
×
340

341
  if (!rd.SwappedEndian()) {
×
UNCOV
342
    uint32 offset0;
×
343
    rd.Push();
344
    rd.Read(offset0);
×
345
    rd.Pop();
×
UNCOV
346
    uint32 dataBeginPredict = (numOffsets * sizeof(uint32)) + rd.Tell();
×
347

348
    if (offset0 == dataBeginPredict) {
349
      fallback();
×
UNCOV
350
    } else {
×
351
      std::vector<uint64> offsets;
UNCOV
352
      rd.ReadContainer(offsets, numOffsets);
×
353
      main.offsets.assign(offsets.begin(), offsets.end());
354
      main.ctx.baseFormat = ConvertTEXFormat(header.format, platform);
UNCOV
355
    }
×
356
  } else {
357
    fallback();
358
  }
×
359

×
UNCOV
360
  uint32 bufferBegin = rd.Tell();
×
UNCOV
361

×
UNCOV
362
  for (uint32 &o : main.offsets) {
×
363
    o -= bufferBegin;
364
  }
365

UNCOV
366
  size_t bufferSize = rd.GetSize() - bufferBegin;
×
UNCOV
367

×
UNCOV
368
  rd.ReadContainer(main.buffer, bufferSize);
×
369
  ApplyModifications(main.ctx, platform);
370

371
  return main;
372
}
×
UNCOV
373

×
374
TEX LoadTEXx09(BinReaderRef_e rd_, Platform) {
375
  BinReaderRef rd(rd_);
×
376
  TEX main;
UNCOV
377
  TEXx09 header;
×
378
  rd.Read(header);
×
379

380
  main.ctx.width = header.width;
UNCOV
381
  main.ctx.height = header.height;
×
NEW
382
  main.ctx.numMipmaps = 1;
×
NEW
383

×
384
  if (header.type == TEXTypeAndr::Cubemap) {
NEW
385
    throw es::RuntimeError("Cubemaps are not supported.");
×
NEW
386
  }
×
NEW
387

×
388
  main.offsets.emplace_back(0);
389

390
  switch (header.format) {
×
UNCOV
391
  case TEXFormatAndr::PVRTC4:
×
392
    main.ctx.baseFormat.type = TexelInputFormatType::PVRTC4;
NEW
393
    main.ctx.baseFormat.swizzle.r = TexelSwizzleType::Blue;
×
394
    main.ctx.baseFormat.swizzle.b = TexelSwizzleType::Red;
395
    main.offsets.back() = header.pvrVariantOffset - header.dataOffset;
396
    break;
×
397
  case TEXFormatAndr::ETC1:
398
    main.ctx.baseFormat.type = TexelInputFormatType::ETC1;
399
    break;
×
UNCOV
400
  case TEXFormatAndr::RGBA4:
×
UNCOV
401
    main.ctx.baseFormat.type = TexelInputFormatType::RGBA4;
×
402
    break;
×
403
  case TEXFormatAndr::RGBA8:
404
    main.ctx.baseFormat.type = TexelInputFormatType::RGBA8;
405
    break;
NEW
406
  case TEXFormatAndr::BC3:
×
NEW
407
    main.ctx.baseFormat.type = TexelInputFormatType::BC3;
×
NEW
408
    break;
×
409
  case TEXFormatAndr::R5G6B5:
410
    main.ctx.baseFormat.type = TexelInputFormatType::R5G6B5;
411
    break;
412
  default:
×
413
    throw es::RuntimeError("Unknown texture format!");
414
  }
×
UNCOV
415

×
NEW
416
  rd.Seek(header.dataOffset);
×
417
  size_t bufferSize = rd.GetSize() - header.dataOffset;
418

NEW
419
  rd.ReadContainer(main.buffer, bufferSize);
×
420

421
  return main;
422
}
×
423

UNCOV
424
TEX LoadTEXxA0(BinReaderRef_e rd, Platform platform) {
×
425
  TEX main;
UNCOV
426
  TEXx9D header;
×
427
  rd.Read(header);
×
428
  using t = TEXx9D;
429

×
430
  main.ctx.width = header.tier1.Get<t::Width>();
×
UNCOV
431
  main.ctx.height = header.tier1.Get<t::Height>();
×
NEW
432
  main.ctx.depth = header.depth;
×
433
  main.ctx.numMipmaps = header.tier1.Get<t::NumMips>();
434

435
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
×
436

437
  if (type == TextureTypeV2::Cubemap) {
438
    main.ctx.numFaces = 6;
×
439
    rd.Read(main.harmonics);
440
  }
×
UNCOV
441

×
442
  uint32 numOffsets = main.ctx.numMipmaps;
443

UNCOV
444
  uint32 bufferSize;
×
445
  rd.Read(bufferSize);
446
  rd.ReadContainer(main.offsets, numOffsets);
×
NEW
447
  main.ctx.baseFormat = ConvertTEXFormat(header.format, platform);
×
448

UNCOV
449
  if (type == TextureTypeV2::Cubemap) {
×
UNCOV
450
    uint32 faceSize;
×
451
    rd.Read(faceSize);
452
    auto offsets = main.offsets;
×
453

454
    for (uint32 f = 0; f < 5; f++) {
455
      for (auto &o : offsets) {
456
        o += faceSize;
457
      }
458

×
UNCOV
459
      main.offsets.insert(main.offsets.end(), offsets.begin(), offsets.end());
×
UNCOV
460
    }
×
461
  }
UNCOV
462

×
463
  rd.ReadContainer(main.buffer, bufferSize);
×
464
  ApplyModifications(main.ctx, platform);
465

466
  return main;
×
467
}
UNCOV
468

×
NEW
469
TEX LoadTEXxA6(BinReaderRef_e rd, Platform) {
×
NEW
470
  TEX main;
×
NEW
471
  TEXx9D header;
×
NEW
472
  rd.Read(header);
×
NEW
473
  using t = TEXx9D;
×
NEW
474

×
NEW
475
  main.ctx.width = header.tier1.Get<t::Width>();
×
NEW
476
  main.ctx.height = header.tier1.Get<t::Height>();
×
NEW
477
  main.ctx.depth = header.depth;
×
NEW
478
  main.ctx.numMipmaps = header.tier1.Get<t::NumMips>();
×
NEW
479

×
NEW
480
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
×
NEW
481

×
NEW
482
  if (type == TextureTypeV2::Cubemap) {
×
NEW
483
    main.ctx.numFaces = 6;
×
NEW
484
    rd.Read(main.harmonics);
×
NEW
485
  }
×
NEW
486

×
NEW
487
  uint32 numOffsets =
×
NEW
488
      main.ctx.numMipmaps * std::max(int8(1), main.ctx.numFaces);
×
NEW
489
  rd.ReadContainer(main.offsets, numOffsets);
×
NEW
490
  main.ctx.baseFormat = ConvertTEXFormat(TEXFormat3DS(header.format));
×
NEW
491

×
492
  size_t bufferSize = rd.GetSize() - rd.Tell();
493

NEW
494
  rd.ReadContainer(main.buffer, bufferSize);
×
NEW
495
  main.ctx.baseFormat.tile = TexelTile::N3DS;
×
496

NEW
497
  return main;
×
498
}
NEW
499

×
NEW
500
TEX LoadTEXxA4(BinReaderRef_e rd, Platform) {
×
501
  TEX main;
NEW
502
  TEXx9D header;
×
503
  rd.Read(header);
504
  using t = TEXx9D;
NEW
505

×
506
  main.ctx.width = header.tier1.Get<t::Width>();
507
  main.ctx.height = header.tier1.Get<t::Height>();
NEW
508
  main.ctx.depth = header.depth;
×
NEW
509
  main.ctx.numMipmaps = header.tier1.Get<t::NumMips>();
×
NEW
510

×
NEW
511
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
×
512

513
  if (type == TextureTypeV2::Cubemap) {
514
    main.ctx.numFaces = 6;
NEW
515
    rd.Read(main.harmonics);
×
NEW
516
    throw es::RuntimeError("Cubemaps are not supported.");
×
NEW
517
  }
×
518

519
  main.offsets.emplace_back(0);
NEW
520
  main.ctx.baseFormat = ConvertTEXFormat(TEXFormat3DS(header.format));
×
521

522
  size_t bufferSize = rd.GetSize() - rd.Tell();
NEW
523

×
NEW
524
  rd.ReadContainer(main.buffer, bufferSize);
×
NEW
525
  main.ctx.baseFormat.tile = TexelTile::N3DS;
×
526

NEW
527
  return main;
×
528
}
NEW
529

×
UNCOV
530
static const std::map<uint16, TEX (*)(BinReaderRef_e, Platform)> texLoaders{
×
531
    {0x66, LoadTEXx66<TEXx66>}, {0x70, LoadTEXx66<TEXx70>}, {0x87, LoadTEXx87},
NEW
532
    {0x97, LoadTEXx9D},         {0x98, LoadTEXx9D},         {0x99, LoadTEXx9D},
×
NEW
533
    {0x9A, LoadTEXx9D},         {0x9D, LoadTEXx9D},         {0x09, LoadTEXx09},
×
NEW
534
    {0xA0, LoadTEXxA0},         {0xA3, LoadTEXxA0},         {0xA6, LoadTEXxA6},
×
535
    {0xA5, LoadTEXxA6},         {0xA4, LoadTEXxA4},
536
};
UNCOV
537

×
538
void revil::LoadDetectTex(BinReaderRef_e rd, Platform platform,
539
                          TextureVersion loadFunc) {
540
  struct {
541
    uint32 id;
×
542
    union {
×
543
      uint8 versionV10;
544
      uint16 versionV11;
×
545
      uint32 versionV20;
×
546
    };
547

×
548
    void NoSwap();
549
  } header{};
550

×
551
  rd.Read(header);
552
  rd.Seek(0);
553

×
NEW
554
  std::stringstream backup;
×
NEW
555
  if (header.id == SFHID) {
×
NEW
556
    backup = ProcessHFS(rd);
×
557
    rd = BinReaderRef_e(backup);
558
    rd.Push();
559
    rd.Read(header);
NEW
560
    rd.Pop();
×
NEW
561
  }
×
NEW
562

×
563
  if (header.id == XETID) {
564
    rd.SwapEndian(true);
565
  } else if (header.id != TEXID && header.id != TEXSID) {
566
    throw es::InvalidHeaderError(header.id);
×
567
  }
×
UNCOV
568

×
569
  if (header.versionV10 == 0x56) {
NEW
570
    loadFunc(0x56, rd, platform);
×
571
    return;
UNCOV
572
  } else if (rd.SwappedEndian()) {
×
UNCOV
573
    FByteswapper(header.versionV11);
×
574
  }
UNCOV
575

×
UNCOV
576
  if (platform == Platform::Auto) {
×
577
    platform = rd.SwappedEndian() ? Platform::PS3 : Platform::Win32;
578
  }
×
579

580
  if (loadFunc(header.versionV11, rd, platform)) {
UNCOV
581
    return;
×
582
  }
583

UNCOV
584
  if (rd.SwappedEndian()) {
×
UNCOV
585
    FByteswapper(header.versionV20);
×
586
  }
×
UNCOV
587

×
588
  if (loadFunc(header.versionV10, rd, platform)) {
589
    return;
590
  }
UNCOV
591

×
NEW
592
  throw es::InvalidVersionError();
×
NEW
593
}
×
NEW
594

×
595
void TEX::Load(BinReaderRef_e rd, Platform platform) {
596
  auto func = [this](uint32 version, BinReaderRef_e rd, Platform platform) {
NEW
597
    if (version == 0x56) {
×
NEW
598
      if (rd.SwappedEndian()) {
×
599
        throw es::RuntimeError("X360 texture format is unsupported.");
NEW
600
      }
×
601

NEW
602
      *this = LoadTEXx56(rd);
×
NEW
603
      return true;
×
604
    }
NEW
605

×
NEW
606
    auto found = texLoaders.find(version);
×
607
    if (!es::IsEnd(texLoaders, found)) {
608
      *this = found->second(rd, platform);
609
      return true;
610
    };
611

612
    return false;
613
  };
614

615
  LoadDetectTex(rd, platform, func);
616
}
×
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

© 2025 Coveralls, Inc