DdsSubfile.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. ///
  2. // Created by Иван_Архипов on 24.11.2017.
  3. //
  4. #include "DdsSubfile.h"
  5. #include "../../include/BinaryData.h"
  6. #include "../../include/DatFile.h"
  7. #include "../../include/DatException.h"
  8. #include "../../include/SubfileData.h"
  9. namespace LOTRO_DAT {
  10. DdsSubfile::DdsSubfile() = default;
  11. DdsSubfile::DdsSubfile(DatFile *dat, long long dictionary_offset, long long fragments_count, long long unknown1,
  12. long long file_id, long long file_offset, long long file_size,
  13. long long timestamp, long long version, long long block_size)
  14. : Subfile(dat, dictionary_offset, fragments_count, unknown1, file_id, file_offset, file_size,
  15. timestamp, version, block_size) {
  16. }
  17. FILE_TYPE DdsSubfile::FileType() const {
  18. return DDS;
  19. }
  20. std::string DdsSubfile::Extension() const {
  21. return ".dds";
  22. }
  23. SubfileData DdsSubfile::PrepareForExport(const BinaryData &file_data) {
  24. BinaryData data = file_data;
  25. if (data.CheckCompression())
  26. data = data.DecompressData(4);
  27. BinaryData ddsData(data.size() - 24 + 128);
  28. for (int i = 0; i < 128; i++)
  29. ddsData[i] = 0;
  30. memcpy(ddsData.data() + 128, data.data() + 24, data.size() - 24);
  31. ddsData[0] = 0x44; // D
  32. ddsData[1] = 0x44; // D
  33. ddsData[2] = 0x53; // S
  34. ddsData[3] = 0x20;
  35. ddsData[4] = 0x7C;
  36. ddsData[8] = 7;
  37. ddsData[9] = 0x10;
  38. // width, height
  39. ddsData[12] = data[12];
  40. ddsData[13] = data[13];
  41. ddsData[14] = data[14];
  42. ddsData[15] = data[15];
  43. ddsData[16] = data[8];
  44. ddsData[17] = data[9];
  45. ddsData[18] = data[10];
  46. ddsData[19] = data[11];
  47. long long compression = data.ToNumber<4>(0x10);
  48. switch (compression) {
  49. case 20: // 14 00 00 00 - 888 (R8G8B8)
  50. ddsData[0x4C] = 0x20; // ?
  51. ddsData[0x50] = 0x40; // compressed or not
  52. ddsData[0x58] = 0x18; // bytes per pixel
  53. ddsData[0x5E] = 0xFF;
  54. ddsData[0x61] = 0xFF;
  55. ddsData[0x64] = 0xFF;
  56. break;
  57. case 21: // 15 00 00 00 - 8888 (R8G8B8A8)
  58. ddsData[0x4C] = 0x20; // ?
  59. ddsData[0x50] = 0x40; // compressed or not
  60. ddsData[0x58] = 0x20; // bytes per pixel
  61. ddsData[0x5E] = 0xFF;
  62. ddsData[0x61] = 0xFF;
  63. ddsData[0x64] = 0xFF;
  64. ddsData[0x6B] = 0xFF;
  65. break;
  66. case 28: // 1C 00 00 00 - 332 (?)
  67. ddsData[0x4C] = 0x20; // ?
  68. ddsData[0x50] = 0x40; // compressed or not
  69. ddsData[0x58] = 0x08; // bytes per pixel
  70. ddsData[0x5E] = 0xFF;
  71. ddsData[0x61] = 0xFF;
  72. ddsData[0x64] = 0xFF;
  73. break;
  74. case 827611204: // 44 58 54 31 - DXT1
  75. ddsData[76] = 32;
  76. ddsData[80] = 4;
  77. ddsData[84] = 68;
  78. ddsData[85] = 88;
  79. ddsData[86] = 84;
  80. ddsData[87] = 49;
  81. break;
  82. case 861165636: // 44 58 54 33 - DXT3
  83. ddsData[22] = 1;
  84. ddsData[76] = 32;
  85. ddsData[80] = 4;
  86. ddsData[84] = 68;
  87. ddsData[85] = 88;
  88. ddsData[86] = 84;
  89. ddsData[87] = 51;
  90. ddsData[108] = 8;
  91. ddsData[109] = 16;
  92. ddsData[110] = 64;
  93. break;
  94. case 894720068: // 44 58 54 35 - DXT5
  95. ddsData[10] = 8;
  96. ddsData[22] = 1;
  97. ddsData[28] = 1;
  98. ddsData[76] = 32;
  99. ddsData[80] = 4;
  100. ddsData[84] = 68;
  101. ddsData[85] = 88;
  102. ddsData[86] = 84;
  103. ddsData[87] = 53;
  104. ddsData[88] = 32;
  105. ddsData[94] = 255;
  106. ddsData[97] = 255;
  107. ddsData[100] = 255;
  108. ddsData[107] = 255;
  109. ddsData[109] = 16;
  110. break;
  111. default:
  112. throw DatException("Bad DdsSubfile::PrepareAsBinary() - unknown header format.", EXPORT_EXCEPTION);
  113. }
  114. SubfileData result;
  115. result.binary_data = ddsData;
  116. result.options["fid"] = file_id();
  117. result.options["ext"] = Extension();
  118. return result;
  119. }
  120. BinaryData DdsSubfile::MakeForImport(const BinaryData &old_data, const SubfileData &data) {
  121. if (!data.options["ext"] || data.options["ext"].as<std::string>() != Extension() ||
  122. !data.options["fid"] || data.options["fid"].as<long long>() != file_id()) {
  123. throw DatException("Bad DdsSubfile::MakeForImport() - invalid options data!", IMPORT_EXCEPTION);
  124. }
  125. // TODO: COMPRESSED TEXTURES
  126. if (old_data.CheckCompression())
  127. return old_data.CutData(0, 4) +
  128. (old_data.DecompressData(12).CutData(12, 16) + data.binary_data.CutData(128)).CompressData();
  129. else {
  130. BinaryData file_size;
  131. file_size.FromNumber<4>(data.binary_data.size() - 128);
  132. return old_data.CutData(0, 28) + file_size + data.binary_data.CutData(128);
  133. }
  134. }
  135. };