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

PredatorCZ / RevilLib / 164

13 Nov 2025 11:19PM UTC coverage: 11.207% (+0.02%) from 11.187%
164

push

github

PredatorCZ
refactor mtf textures

0 of 114 new or added lines in 1 file covered. (0.0%)

802 existing lines in 3 files now uncovered.

757 of 6755 relevant lines covered (11.21%)

6709.97 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 "revil/tex.hpp"
19
#include "spike/except.hpp"
20
#include "spike/format/DDS.hpp"
21
#include "spike/io/binreader_stream.hpp"
22
#include "spike/type/bitfield.hpp"
23
#include <map>
24
#include <vector>
25

26
using namespace revil;
27

28
enum class TextureType : uint8 {
29
  None,
30
  ColorPixel,
31
  General,
32
  Cubemap,
33
  Volume,
34
};
35

36
enum class TextureTypeV2 {
37
  General = 2,
38
  Volume = 3,
39
  Cubemap = 6,
40
};
41

42
enum class GeneralTextureType {
43
  None,
44
  IllumMap,  // IM
45
  ColorMap,  // BM, LM, or SRGB??
46
  NormalMap, // NM XGXA
47
};
48

49
enum class CubemapTextureType {
50
  Eye, // LP PC, some struct dump
51
  Classic,
52
};
53

54
enum class TEXFormat : uint32 {
55
  DXT1 = CompileFourCC("DXT1"),
56
  DXT2 = CompileFourCC("DXT2"),
57
  DXT3 = CompileFourCC("DXT3"),
58
  DXT5 = CompileFourCC("DXT5"),
59
  RGBA8_PACKED = 0x15,
60
  RG8_SNORM = 0x3c,
61

62
  /*360
63
  405274959
64
  405275014
65
  438305106
66
  438305107
67
  438305108
68
  438305137
69
  438305147
70
  438305148*/
71
};
72

73
enum class TEXFormatV2 : uint8 {
74
  RGBA16F = 0x2,
75
  DXT5_YUV = 0xA,
76
  BC7 = 0x10,
77
  DXT1 = 0x13,
78
  DXT3 = 0x15,
79
  DXT5 = 0x17,
80
  DXT1_Gray = 0x19, // BC4 for some?
81
  DXT1_NM = 0x1e,
82
  DXT5_NM = 0x1f,
83
  DXT5_LM = 0x20, // rgb lightmap, alpha ambient occlusion?
84
  DXT5_PM = 0x25, // rgb NM, alpha HM
85
  DXT5_ID = 0x2a,
86
  RGBA8 = 0x27,
87
};
88

89
enum class TEXFormatV2PS4 : uint8 {
90
  R8 = 0x7,
91
  DXT5_YUV = 0xA,
92
  BC7 = 0x10,
93
  DXT1 = 0x13,
94
  DXT3 = 0x15,
95
  DXT5 = 0x17,
96
  DXT1_NM = 0x1e,
97
  BC5S = 0x1f,
98
  BC4 = 0x19,
99
};
100

101
enum class TEXFormatA0 : uint8 {
102
  R8 = 0,
103
  RGBA8 = 7,
104
  BC3_YUV = 0xA,
105
  BC1 = 0x13,
106
  BC2 = 0x15,
107
  BC3 = 0x17,
108
  BC4 = 0x19,
109
  BC1_NM = 0x1e,
110
  BC5 = 0x1f,
111
};
112

113
static constexpr uint32 TEXID = CompileFourCC("TEX");
114
static constexpr uint32 TEXSID = CompileFourCC("TEX ");
115
static constexpr uint32 XETID = CompileFourCC("\0XET");
116

117
struct TEXx70 {
×
118
  using TextureType = BitMemberDecl<0, 4>;
119
  using TextureSubtype = BitMemberDecl<1, 4>;
120
  using TextureLayout = BitFieldType<uint16, TextureType, TextureSubtype>;
121
  uint32 id = TEXID;
122
  uint16 version;
123
  TextureLayout type;
124
  uint8 numMips;
125
  uint8 numFaces = 1; // 6 for cubemap
126
  uint16 null = 0;
127
  uint16 width;
128
  uint16 height;
129
  uint32 arraySize = 0;
130
  TEXFormat fourcc;
131
  Vector4 colorCorrection{1.f, 1.f, 1.f, 0};
132

133
  void SwapEndian(bool way) {
×
134
    FByteswapper(id);
×
135
    FByteswapper(version);
×
136
    FByteswapper(type, way);
×
137
    FByteswapper(width);
×
138
    FByteswapper(height);
×
139
    FByteswapper(arraySize);
×
140
    FByteswapper(fourcc);
×
141
    FByteswapper(colorCorrection);
×
142
  }
143
};
144

145
struct TEXx66 {
×
146
  using TextureType = BitMemberDecl<0, 4>;
147
  using TextureSubtype = BitMemberDecl<1, 4>;
148
  using TextureLayout = BitFieldType<uint16, TextureType, TextureSubtype>;
149
  uint32 id = TEXID;
150
  uint16 version;
151
  TextureLayout type;
152
  uint8 numMips;
153
  uint8 numFaces = 1;
154
  uint16 width;
155
  uint16 height;
156
  uint16 arraySize;
157
  TEXFormat fourcc;
158
  Vector4 colorCorrection{1.f, 1.f, 1.f, 0};
159

160
  void SwapEndian(bool way) {
×
161
    FByteswapper(id);
×
162
    FByteswapper(version);
×
163
    FByteswapper(type, way);
×
164
    FByteswapper(width);
×
165
    FByteswapper(height);
×
166
    FByteswapper(arraySize);
×
167
    FByteswapper(fourcc);
×
168
    FByteswapper(colorCorrection);
×
169
  }
170
};
171

172
struct TEXx56 {
173
  enum class TextureLayout : uint8 { General, Illum, Corrected = 4 };
174

175
  uint32 id;
176
  uint8 version;
177
  TextureType type;
178
  TextureLayout layout;
179
  uint8 numMips;
180
  uint32 width;
181
  uint32 height;
182
  uint32 arraySize;
183
  TEXFormat fourcc;
184

185
  void SwapEndian() {
×
186
    FByteswapper(id);
×
187
    FByteswapper(width);
×
188
    FByteswapper(height);
×
189
    FByteswapper(arraySize);
×
190
    FByteswapper(fourcc);
×
191
  }
192
};
193

194
struct TEXx87 {
195
  using TextureType = BitMemberDecl<0, 4>;
196
  using NumMips = BitMemberDecl<1, 5>;
197
  using NumFaces = BitMemberDecl<2, 8>;
198
  using Width = BitMemberDecl<3, 13>;
199
  using Tier0 = BitFieldType<uint32, TextureType, NumMips, NumFaces, Width>;
200
  using Height = BitMemberDecl<0, 13>;
201
  using Depth = BitMemberDecl<1, 13>;
202
  using Null = BitMemberDecl<2, 6>;
203
  using Tier1 = BitFieldType<uint32, Height, Depth, Null>;
204

205
  uint32 id;
206
  uint16 version;
207
  uint16 null;
208
  Tier0 tier0;
209
  Tier1 tier1;
210
  TEXFormatV2 format;
211

212
  void SwapEndian(bool way) {
×
213
    FByteswapper(id);
×
214
    FByteswapper(version);
×
215
    FByteswapper(tier0, way);
×
216
    FByteswapper(tier1, way);
217
  }
218
};
219

220
struct TEXx9D {
221
  using Version = BitMemberDecl<0, 8>;
222
  using Unk00 = BitMemberDecl<1, 6>;
223
  using Unk01 = BitMemberDecl<2, 14>;
224
  using TextureType = BitMemberDecl<3, 4>;
225
  using Tier0 = BitFieldType<uint32, Version, Unk00, Unk01, TextureType>;
226

227
  using NumMips = BitMemberDecl<0, 6>;
228
  using Width = BitMemberDecl<1, 13>;
229
  using Height = BitMemberDecl<2, 13>;
230
  using Tier1 = BitFieldType<uint32, NumMips, Width, Height>;
231

232
  using NumFaces = BitMemberDecl<0, 8>;
233
  using TextureFormat = BitMemberDecl<1, 5>;
234
  using Flags = BitMemberDecl<2, 3>;
235
  using Depth = BitMemberDecl<3, 16>;
236
  using Tier2 = BitFieldType<uint32, NumFaces, TextureFormat, Flags, Depth>;
237

238
  uint32 id;
239
  Tier0 tier0;
240
  Tier1 tier1;
241
  Tier2 tier2;
242

243
  void SwapEndian(bool) {
×
244
    FByteswapper(id);
×
245
    FByteswapper(tier0.value);
×
246
    FByteswapper(tier1.value);
×
247
    FByteswapper(tier2.value);
×
248
  }
249
};
250

251
enum class TEXFormatAndr : uint8 {
252
  RGBA8 = 0x1,
253
  RGBA4 = 0x7,
254
  ETC1 = 0x0A,
255
  PVRTC4 = 0x0D,
256
};
257

258
enum class TEXTypeAndr : uint32 {
259
  Base = 0x11,
260
  Normal = 0x21,
261
  Mask = 0x31,
262
  CubeMap = 0x61,
263
};
264

265
struct TEXx09 {
266
  uint32 id;
267
  uint16 version;
268
  TEXFormatAndr format;
269
  uint8 unk; // 4
270
  TEXTypeAndr type;
271

272
  uint32 width : 13;
273
  uint32 height : 13;
274
  uint32 numMips : 4;
275
  uint32 unk0 : 1;
276
  uint32 unk1 : 1;
277

278
  uint32 offset0;
279
  uint32 pvrtcOffset;
280
  uint32 offset1;
281

282
  uint32 unkSize;
283
  uint32 pvrtcSize;
284
  uint32 dxtSize;
285
};
286

287
struct TEXCubemapData {
288
  float unk[27];
289
};
290

NEW
291
TexelInputFormat ConvertTEXFormat(TEXFormat fmt) {
×
292
  TexelInputFormat retVal;
293

UNCOV
294
  switch (fmt) {
×
295
  case TEXFormat::DXT1:
296
    retVal.type = TexelInputFormatType::BC1;
297
    break;
NEW
298
  case TEXFormat::DXT2:
×
299
    retVal.type = TexelInputFormatType::BC2;
300
    retVal.premultAlpha = true;
NEW
301
    break;
×
UNCOV
302
  case TEXFormat::DXT3:
×
303
    retVal.type = TexelInputFormatType::BC2;
NEW
304
    break;
×
UNCOV
305
  case TEXFormat::DXT5:
×
306
    retVal.type = TexelInputFormatType::BC3;
NEW
307
    break;
×
UNCOV
308
  case TEXFormat::RGBA8_PACKED:
×
309
    retVal.type = TexelInputFormatType::RGBA8;
NEW
310
    break;
×
UNCOV
311
  case TEXFormat::RG8_SNORM:
×
312
    retVal.type = TexelInputFormatType::RG8;
313
    retVal.snorm = true;
NEW
314
    break;
×
315

316
  default:
×
317
    throw std::runtime_error("Unknown texture format!");
×
318
  }
319

NEW
320
  return retVal;
×
321
}
322

NEW
323
TexelInputFormat ConvertTEXFormat(TEXFormatV2 fmt) {
×
324
  TexelInputFormat retVal;
325

UNCOV
326
  switch (fmt) {
×
327
  case TEXFormatV2::DXT1:
328
  case TEXFormatV2::DXT1_Gray:
329
  case TEXFormatV2::DXT1_NM:
330
    retVal.type = TexelInputFormatType::BC1;
331
    break;
UNCOV
332
  case TEXFormatV2::DXT3:
×
333
    retVal.type = TexelInputFormatType::BC2;
NEW
334
    break;
×
UNCOV
335
  case TEXFormatV2::DXT5:
×
336
  case TEXFormatV2::DXT5_NM:
337
  case TEXFormatV2::DXT5_LM:
338
  case TEXFormatV2::DXT5_PM:
339
  case TEXFormatV2::DXT5_ID:
340
  case TEXFormatV2::DXT5_YUV:
341
    retVal.type = TexelInputFormatType::BC3;
NEW
342
    break;
×
UNCOV
343
  case TEXFormatV2::RGBA16F:
×
344
    retVal.type = TexelInputFormatType::RGBA16;
NEW
345
    break;
×
UNCOV
346
  case TEXFormatV2::RGBA8:
×
347
    retVal.type = TexelInputFormatType::RGBA8;
NEW
348
    break;
×
349

350
  default:
×
351
    throw std::runtime_error("Unknown texture format!");
×
352
  }
353

NEW
354
  return retVal;
×
355
}
356

NEW
357
TexelInputFormat ConvertTEXFormat(TEXFormatV2PS4 fmt) {
×
358
  TexelInputFormat retVal;
359

UNCOV
360
  switch (fmt) {
×
361
  case TEXFormatV2PS4::DXT1:
362
  case TEXFormatV2PS4::DXT1_NM:
363
    retVal.type = TexelInputFormatType::BC1;
364
    break;
UNCOV
365
  case TEXFormatV2PS4::DXT3:
×
366
    retVal.type = TexelInputFormatType::BC2;
NEW
367
    break;
×
UNCOV
368
  case TEXFormatV2PS4::DXT5:
×
369
  case TEXFormatV2PS4::DXT5_YUV:
370
    retVal.type = TexelInputFormatType::BC3;
NEW
371
    break;
×
UNCOV
372
  case TEXFormatV2PS4::BC4:
×
373
    retVal.type = TexelInputFormatType::BC4;
NEW
374
    break;
×
UNCOV
375
  case TEXFormatV2PS4::BC5S:
×
376
    retVal.type = TexelInputFormatType::BC5;
377
    retVal.snorm = true;
NEW
378
    break;
×
UNCOV
379
  case TEXFormatV2PS4::BC7:
×
380
    retVal.type = TexelInputFormatType::BC7;
NEW
381
    break;
×
UNCOV
382
  case TEXFormatV2PS4::R8:
×
383
    retVal.type = TexelInputFormatType::R8;
NEW
384
    break;
×
385
  default:
×
386
    throw std::runtime_error("Unknown texture format!");
×
387
  }
388

NEW
389
  return retVal;
×
390
}
391

NEW
392
TexelInputFormat ConvertTEXFormat(TEXFormatA0 fmt) {
×
393
  TexelInputFormat retVal;
394

NEW
395
  switch (fmt) {
×
396
  case TEXFormatA0::BC1:
397
  case TEXFormatA0::BC1_NM:
398
    retVal.type = TexelInputFormatType::BC1;
399
    break;
NEW
400
  case TEXFormatA0::BC2:
×
401
    retVal.type = TexelInputFormatType::BC2;
NEW
402
    break;
×
NEW
403
  case TEXFormatA0::BC3:
×
404
  case TEXFormatA0::BC3_YUV:
405
    retVal.type = TexelInputFormatType::BC3;
NEW
406
    break;
×
NEW
407
  case TEXFormatA0::BC4:
×
408
    retVal.type = TexelInputFormatType::BC4;
NEW
409
    break;
×
NEW
410
  case TEXFormatA0::BC5:
×
411
    retVal.type = TexelInputFormatType::BC5;
412
    retVal.swizzle.g = TexelSwizzleType::DeriveZ;
NEW
413
    break;
×
NEW
414
  case TEXFormatA0::RGBA8:
×
415
    retVal.type = TexelInputFormatType::RGBA8;
NEW
416
    break;
×
NEW
417
  case TEXFormatA0::R8:
×
418
    retVal.type = TexelInputFormatType::R8;
NEW
419
    break;
×
420

NEW
421
  default:
×
NEW
422
    throw std::runtime_error("Unknown texture format!");
×
423
  }
424

NEW
425
  return retVal;
×
426
}
427

NEW
428
void ApplyModifications(NewTexelContextCreate &ctx, Platform platform) {
×
NEW
429
  if (ctx.baseFormat.type == TexelInputFormatType::RGBA8 &&
×
NEW
430
      platform == Platform::PS3 && IsPow2(ctx.width) && IsPow2(ctx.height)) {
×
NEW
431
    ctx.baseFormat.tile = TexelTile::Morton;
×
NEW
432
  } else if (platform == Platform::PS4) {
×
NEW
433
    ctx.baseFormat.tile = TexelTile::MortonForcePow2;
×
NEW
434
  } else if (platform == Platform::NSW) {
×
NEW
435
    ctx.baseFormat.tile = TexelTile::NX;
×
436
  }
437
}
438

439
TEX LoadTEXx56(BinReaderRef_e rd) {
×
440
  TEX main;
441
  TEXx56 header;
442
  rd.Read(header);
×
443

444
  if (header.layout == TEXx56::TextureLayout::Corrected) {
×
445
    rd.Read(main.color);
×
446
  }
447

448
  if (header.type == TextureType::Volume) {
×
449
    BinReaderRef rdn(rd);
450
    DDS_Header ddsHdr;
NEW
451
    DDS_PixelFormat ddsPf;
×
NEW
452
    DDS_HeaderEnd ddsFt;
×
453
    rdn.Read(ddsHdr);
454
    rdn.Read(ddsPf);
455
    rdn.Read(ddsFt);
456

NEW
457
    main.ctx.width = ddsHdr.width;
×
NEW
458
    main.ctx.height = ddsHdr.height;
×
NEW
459
    main.ctx.depth = ddsHdr.depth;
×
NEW
460
    main.ctx.numMipmaps = ddsHdr.mipMapCount;
×
461

NEW
462
    if (ddsPf == DDSFormat_DXT5) {
×
NEW
463
      main.ctx.baseFormat.type = TexelInputFormatType::BC3;
×
464
    } else {
NEW
465
      throw std::runtime_error("Unknown texture format!");
×
466
    }
467
  } else if (header.type == TextureType::Cubemap) {
×
468
    throw std::runtime_error("Cubemaps are not supported.");
×
469
  } else {
NEW
470
    main.ctx.width = header.width;
×
NEW
471
    main.ctx.height = header.height;
×
NEW
472
    main.ctx.depth = header.arraySize;
×
NEW
473
    main.ctx.numMipmaps = header.numMips;
×
NEW
474
    main.ctx.baseFormat = ConvertTEXFormat(header.fourcc);
×
475
  }
476

NEW
477
  size_t bufferSize = rd.GetSize() - rd.Tell();
×
478
  rd.ReadContainer(main.buffer, bufferSize);
×
479
  ApplyModifications(main.ctx, Platform::Win32);
480

481
  return main;
×
UNCOV
482
}
×
483

484
template <class header_type>
485
TEX LoadTEXx66(BinReaderRef_e rd, Platform platform) {
×
486
  TEX main;
487
  header_type header;
488
  rd.Read(header);
×
489

NEW
490
  main.ctx.width = header.width;
×
NEW
491
  main.ctx.height = header.height;
×
NEW
492
  main.ctx.depth = header.arraySize;
×
NEW
493
  main.ctx.numMipmaps = header.numMips;
×
NEW
494
  main.ctx.baseFormat = ConvertTEXFormat(header.fourcc);
×
UNCOV
495
  main.color = Vector4A16(header.colorCorrection);
×
496

497
  TextureType type = static_cast<TextureType>(
498
      header.type.template Get<typename header_type::TextureType>());
499

NEW
500
  if (type == TextureType::Cubemap) {
×
UNCOV
501
    throw std::runtime_error("Cubemaps are not supported.");
×
502
  }
503

NEW
504
  rd.ReadContainer(main.offsets, header.numFaces * header.numMips);
×
505

NEW
506
  size_t bufferSize = rd.GetSize() - rd.Tell();
×
507

508
  if (header.arraySize) {
×
509
    bufferSize *= header.arraySize;
×
510
  }
511

512
  rd.ReadContainer(main.buffer, bufferSize);
×
NEW
513
  ApplyModifications(main.ctx, platform);
×
514

515
  return main;
×
UNCOV
516
}
×
517

×
518
TEX LoadTEXx87(BinReaderRef_e rd, Platform) {
519
  TEX main;
520
  TEXx87 header;
×
521
  rd.Read(header);
522
  using t = TEXx87;
×
523

×
NEW
524
  main.ctx.width = header.tier0.Get<t::Width>();
×
NEW
525
  main.ctx.height = header.tier1.Get<t::Height>();
×
NEW
526
  main.ctx.depth = header.tier1.Get<t::Depth>();
×
NEW
527
  main.ctx.numMipmaps = header.tier0.Get<t::NumMips>();
×
528
  main.ctx.baseFormat = ConvertTEXFormat(header.format);
529

530
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
531

NEW
532
  if (type == TextureTypeV2::Cubemap) {
×
UNCOV
533
    throw std::runtime_error("Cubemaps are not supported.");
×
534
  }
535

NEW
536
  uint32 numOffsets = main.ctx.depth * main.ctx.numMipmaps;
×
537
  rd.ReadContainer(main.offsets, numOffsets);
UNCOV
538

×
539
  size_t bufferSize = rd.GetSize() - rd.Tell();
540

×
NEW
541
  if (main.ctx.depth) {
×
542
    bufferSize *= main.ctx.depth;
543
  }
544

×
UNCOV
545
  rd.ReadContainer(main.buffer, bufferSize);
×
546

UNCOV
547
  return main;
×
548
}
×
UNCOV
549

×
550
TEX LoadTEXx9D(BinReaderRef_e rd, Platform platform) {
551
  TEX main;
UNCOV
552
  TEXx9D header;
×
553
  rd.Read(header);
554
  using t = TEXx9D;
×
555

×
NEW
556
  main.ctx.width = header.tier1.Get<t::Width>();
×
NEW
557
  main.ctx.height = header.tier1.Get<t::Height>();
×
NEW
558
  main.ctx.depth = header.tier2.Get<t::Depth>();
×
NEW
559
  main.ctx.numMipmaps = header.tier1.Get<t::NumMips>();
×
560

561
  TextureTypeV2 type = (TextureTypeV2)header.tier0.Get<t::TextureType>();
562

563
  if (type == TextureTypeV2::Cubemap) {
UNCOV
564
    throw std::runtime_error("Cubemaps are not supported.");
×
UNCOV
565
  }
×
566

567
  uint32 numOffsets = main.ctx.depth * main.ctx.numMipmaps;
568

×
569
  auto fallback = [&] {
NEW
570
    rd.ReadContainer(main.offsets, numOffsets);
×
571
    main.ctx.baseFormat =
572
        ConvertTEXFormat((TEXFormatV2)header.tier2.Get<t::TextureFormat>());
×
573
  };
×
574

575
  if (!rd.SwappedEndian()) {
576
    uint32 offset0;
×
577
    rd.Push();
×
578
    rd.Read(offset0);
579
    rd.Pop();
×
UNCOV
580
    uint32 dataBeginPredict = (numOffsets * sizeof(uint32)) + rd.Tell();
×
581

582
    if (offset0 == dataBeginPredict) {
×
583
      fallback();
584
    } else {
585
      std::vector<uint64> offsets;
×
586
      rd.ReadContainer(offsets, numOffsets);
587
      main.offsets.assign(offsets.begin(), offsets.end());
588
      platform = Platform::PS4;
×
NEW
589
      main.ctx.baseFormat = ConvertTEXFormat(
×
590
          (TEXFormatV2PS4)header.tier2.Get<t::TextureFormat>());
×
591
    }
×
592
  } else {
×
593
    fallback();
594
  }
595

NEW
596
  size_t bufferSize = rd.GetSize() - rd.Tell();
×
UNCOV
597

×
598
  if (main.ctx.depth) {
599
    bufferSize *= main.ctx.depth;
UNCOV
600
  }
×
UNCOV
601

×
602
  rd.ReadContainer(main.buffer, bufferSize);
NEW
603
  ApplyModifications(main.ctx, platform);
×
604

605
  return main;
×
606
}
×
607

608
TEX LoadTEXx09(BinReaderRef_e rd_, Platform platform) {
609
  BinReaderRef rd(rd_);
×
610
  TEX main;
611
  TEXx09 header;
×
612
  rd.Read(header);
×
613

NEW
614
  main.ctx.width = header.width;
×
615
  main.ctx.height = header.height;
616
  main.ctx.numMipmaps = header.numMips;
NEW
617

×
618
  switch (header.format) {
619
  case TEXFormatAndr::PVRTC4:
NEW
620
    main.ctx.baseFormat.type = TexelInputFormatType::PVRTC4;
×
NEW
621
    break;
×
NEW
622
  case TEXFormatAndr::ETC1:
×
NEW
623
    main.ctx.baseFormat.type = TexelInputFormatType::ETC1;
×
624
    break;
625
  case TEXFormatAndr::RGBA4:
626
    main.ctx.baseFormat.type = TexelInputFormatType::RGBA4;
NEW
627
    break;
×
NEW
628
  case TEXFormatAndr::RGBA8:
×
629
    main.ctx.baseFormat.type = TexelInputFormatType::RGBA8;
630
    break;
NEW
631
  default:
×
632
    throw std::runtime_error("Unknown texture format!");
633
  }
×
UNCOV
634

×
635
  ApplyModifications(main.ctx, platform);
NEW
636

×
637
  return main;
638
}
NEW
639

×
640
TEX LoadTEXxA0(BinReaderRef_e rd, Platform platform) {
641
  TEX main;
NEW
642
  TEXx9D header;
×
643
  rd.Read(header);
NEW
644
  using t = TEXx9D;
×
645

NEW
646
  main.ctx.width = header.tier1.Get<t::Width>();
×
NEW
647
  main.ctx.height = header.tier1.Get<t::Height>();
×
648
  main.ctx.depth = header.tier2.Get<t::Depth>();
NEW
649
  main.ctx.numMipmaps = header.tier1.Get<t::NumMips>();
×
NEW
650

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

NEW
653
  if (type == TextureTypeV2::Cubemap) {
×
654
    main.ctx.numFaces = 6;
655
    rd.Read(main.harmonics);
656
  }
NEW
657

×
658
  uint32 numOffsets = main.ctx.depth * main.ctx.numMipmaps;
659

NEW
660
  uint32 bufferSize;
×
661
  rd.Read(bufferSize);
NEW
662
  rd.ReadContainer(main.offsets, numOffsets);
×
NEW
663
  main.ctx.baseFormat =
×
664
      ConvertTEXFormat((TEXFormatA0)header.tier2.Get<t::TextureFormat>());
665

NEW
666
  if (type == TextureTypeV2::Cubemap) {
×
NEW
667
    rd.Read(main.faceSize);
×
668
  }
NEW
669

×
NEW
670
  rd.ReadContainer(main.buffer, bufferSize);
×
671
  ApplyModifications(main.ctx, platform);
UNCOV
672

×
673
  return main;
674
}
675

676
static const std::map<uint16, TEX (*)(BinReaderRef_e, Platform)> texLoaders{
677
    {0x66, LoadTEXx66<TEXx66>}, {0x70, LoadTEXx66<TEXx70>}, {0x87, LoadTEXx87},
NEW
678
    {0x9D, LoadTEXx9D},         {0x09, LoadTEXx09},         {0xA0, LoadTEXxA0},
×
UNCOV
679
};
×
UNCOV
680

×
681
void TEX::Load(BinReaderRef_e rd, Platform platform) {
682
  struct {
×
UNCOV
683
    uint32 id;
×
684
    union {
×
685
      uint8 versionV10;
×
UNCOV
686
      uint16 versionV11;
×
UNCOV
687
      uint32 versionV20;
×
688
    };
×
689

×
UNCOV
690
    void NoSwap();
×
691
  } header{};
×
UNCOV
692

×
UNCOV
693
  rd.Read(header);
×
694
  rd.Seek(0);
×
UNCOV
695

×
UNCOV
696
  if (header.id == XETID) {
×
697
    rd.SwapEndian(true);
698
  } else if (header.id != TEXID && header.id != TEXSID) {
UNCOV
699
    throw es::InvalidHeaderError(header.id);
×
700
  }
701

×
702
  if (header.versionV10 == 0x56) {
×
703
    if (rd.SwappedEndian()) {
704
      throw std::runtime_error("X360 texture format is unsupported.");
×
705
    }
706

707
    *this = LoadTEXx56(rd);
×
708
    return;
709
  } else if (rd.SwappedEndian()) {
710
    FByteswapper(header.versionV11);
×
UNCOV
711
  }
×
UNCOV
712

×
713
  if (platform == Platform::Auto) {
×
714
    platform = rd.SwappedEndian() ? Platform::PS3 : Platform::Win32;
715
  }
716

717
  auto found = texLoaders.find(header.versionV11);
×
UNCOV
718

×
719
  if (!es::IsEnd(texLoaders, found)) {
×
720
    *this = found->second(rd, platform);
721
    return;
722
  }
×
723

724
  if (rd.SwappedEndian()) {
UNCOV
725
    FByteswapper(header.versionV20);
×
UNCOV
726
  }
×
727

728
  found = texLoaders.find(header.versionV10);
×
729

730
  if (es::IsEnd(texLoaders, found)) {
×
UNCOV
731
    throw es::InvalidVersionError();
×
732
  }
733

UNCOV
734
  *this = found->second(rd, platform);
×
735
  return;
×
736
}
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