DdsSubfile.cpp 5.3 KB

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