DdsSubFile.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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(DatFile &dat, SubFile preinit_file) : SubFile(preinit_file) {
  11. }
  12. FILE_TYPE DdsSubFile::FileType() const {
  13. return DDS;
  14. }
  15. std::string DdsSubFile::Extension() const {
  16. return ".dds";
  17. }
  18. SubfileData DdsSubFile::PrepareForExport(const BinaryData &file_data) {
  19. if (file_data.Empty() || file_data.size() < 256) {
  20. return SubfileData();
  21. }
  22. BinaryData data = file_data;
  23. if (data.CheckCompression())
  24. data = data.DecompressData(4);
  25. BinaryData ddsData(data.size() - 24 + 128);
  26. for (int i = 0; i < 128; i++)
  27. ddsData[i] = 0;
  28. memcpy(ddsData.data() + 128, data.data() + 24, data.size() - 24);
  29. ddsData[0] = 0x44; // D
  30. ddsData[1] = 0x44; // D
  31. ddsData[2] = 0x53; // S
  32. ddsData[3] = 0x20;
  33. ddsData[4] = 0x7C;
  34. ddsData[8] = 7;
  35. ddsData[9] = 0x10;
  36. // width, height
  37. ddsData[12] = data[12];
  38. ddsData[13] = data[13];
  39. ddsData[14] = data[14];
  40. ddsData[15] = data[15];
  41. ddsData[16] = data[8];
  42. ddsData[17] = data[9];
  43. ddsData[18] = data[10];
  44. ddsData[19] = data[11];
  45. long long compression = data.ToNumber<4>(0x10);
  46. switch (compression) {
  47. case 20: // 14 00 00 00 - 888 (R8G8B8)
  48. ddsData[0x4C] = 0x20; // ?
  49. ddsData[0x50] = 0x40; // compressed or not
  50. ddsData[0x58] = 0x18; // bytes per pixel
  51. ddsData[0x5E] = 0xFF;
  52. ddsData[0x61] = 0xFF;
  53. ddsData[0x64] = 0xFF;
  54. break;
  55. case 21: // 15 00 00 00 - 8888 (R8G8B8A8)
  56. ddsData[0x4C] = 0x20; // ?
  57. ddsData[0x50] = 0x40; // compressed or not
  58. ddsData[0x58] = 0x20; // bytes per pixel
  59. ddsData[0x5E] = 0xFF;
  60. ddsData[0x61] = 0xFF;
  61. ddsData[0x64] = 0xFF;
  62. ddsData[0x6B] = 0xFF;
  63. break;
  64. case 28: // 1C 00 00 00 - 332 (?)
  65. ddsData[0x4C] = 0x20; // ?
  66. ddsData[0x50] = 0x40; // compressed or not
  67. ddsData[0x58] = 0x08; // bytes per pixel
  68. ddsData[0x5E] = 0xFF;
  69. ddsData[0x61] = 0xFF;
  70. ddsData[0x64] = 0xFF;
  71. break;
  72. case 827611204: // 44 58 54 31 - DXT1
  73. ddsData[76] = 32;
  74. ddsData[80] = 4;
  75. ddsData[84] = 68;
  76. ddsData[85] = 88;
  77. ddsData[86] = 84;
  78. ddsData[87] = 49;
  79. break;
  80. case 861165636: // 44 58 54 33 - DXT3
  81. ddsData[22] = 1;
  82. ddsData[76] = 32;
  83. ddsData[80] = 4;
  84. ddsData[84] = 68;
  85. ddsData[85] = 88;
  86. ddsData[86] = 84;
  87. ddsData[87] = 51;
  88. ddsData[108] = 8;
  89. ddsData[109] = 16;
  90. ddsData[110] = 64;
  91. break;
  92. case 894720068: // 44 58 54 35 - DXT5
  93. ddsData[10] = 8;
  94. ddsData[22] = 1;
  95. ddsData[28] = 1;
  96. ddsData[76] = 32;
  97. ddsData[80] = 4;
  98. ddsData[84] = 68;
  99. ddsData[85] = 88;
  100. ddsData[86] = 84;
  101. ddsData[87] = 53;
  102. ddsData[88] = 32;
  103. ddsData[94] = 255;
  104. ddsData[97] = 255;
  105. ddsData[100] = 255;
  106. ddsData[107] = 255;
  107. ddsData[109] = 16;
  108. break;
  109. default:
  110. LOG(ERROR) << "Unknown header format.";
  111. return SubfileData();
  112. }
  113. SubfileData result;
  114. result.binary_data = ddsData;
  115. result.options["fid"] = file_id();
  116. result.options["ext"] = Extension();
  117. return result;
  118. }
  119. BinaryData DdsSubFile::MakeForImport(const BinaryData &old_data, const SubfileData &data) {
  120. if (!data.options["ext"] || data.options["ext"].as<std::string>() != Extension() ||
  121. !data.options["fid"] || data.options["fid"].as<long long>() != file_id()) {
  122. LOG(ERROR) << "Invalid options data!";
  123. return BinaryData(0);
  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 = BinaryData::FromNumber<4>(data.binary_data.size() - 128);
  131. return old_data.CutData(0, 28) + file_size + data.binary_data.CutData(128);
  132. }
  133. }
  134. };