TextSubfile.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //
  2. // Created by Иван_Архипов on 24.11.2017.
  3. //
  4. #include "TextSubfile.h"
  5. #include "../BinaryData.h"
  6. #include "../DatFile.h"
  7. #include "../Common/DatException.h"
  8. namespace LOTRO_DAT {
  9. TextSubfile::TextSubfile() = default;
  10. TextSubfile::TextSubfile(DatFile *dat, long long fragments_count, long long unknown1,
  11. long long file_id, long long file_offset, long long file_size,
  12. long long timestamp,
  13. long long version, long long block_size)
  14. : Subfile(dat, fragments_count, unknown1, file_id, file_offset, file_size, timestamp, version, block_size) {
  15. }
  16. FILE_TYPE TextSubfile::FileType() const {
  17. return TEXT;
  18. }
  19. bool TextSubfile::PrepareForExport(const BinaryData &file_data, long long &export_size, std::vector<BinaryData> &binary_data,
  20. std::vector<std::u16string> &text_data, std::vector<YAML::Node> &options) {
  21. export_size = 0;
  22. binary_data.clear();
  23. text_data.clear();
  24. options.clear();
  25. if (file_size() <= 10) // File is empty, nothing to do;
  26. return false;
  27. long long offset = 9; // first 4 bytes - file_id, then 4 bytes - unknown, then 1 byte - unknown
  28. long long text_fragment_num = file_data.ToNumber<1>(offset);
  29. if ((text_fragment_num & 0x80) != 0) {
  30. text_fragment_num = (((text_fragment_num ^ 0x80) << 8) | file_data.ToNumber<1>(offset + 1));
  31. offset += 1;
  32. }
  33. offset += 1;
  34. for (long long i = 0; i < text_fragment_num; i++) {
  35. long long fragment_id = file_data.ToNumber<8>(offset);
  36. offset += 8;
  37. std::vector<std::u16string> text_pieces = MakePieces(file_data, offset);
  38. std::vector<long long> arg_references = MakeArgumentReferences(file_data, offset);
  39. std::vector<std::vector<BinaryData>> arg_strings = MakeArgumentStrings(file_data, offset);
  40. std::u16string text = u"[";
  41. for (int j = 0; j + 1 < text_pieces.size(); j++)
  42. text += text_pieces[j] + u"<--DO_NOT_TOUCH!-->";
  43. text += text_pieces[text_pieces.size() - 1] + u"]";
  44. std::string arguments;
  45. for (int j = 0; j + 1 < arg_references.size(); j++)
  46. arguments += std::to_string(arg_references[j]) + "-";
  47. if (!arg_references.empty())
  48. arguments += std::to_string(arg_references[arg_references.size() - 1]);
  49. binary_data.emplace_back(BinaryData());
  50. text_data.emplace_back(text);
  51. options.emplace_back(YAML::Node());
  52. options[export_size]["file_id"] = file_id();
  53. options[export_size]["gossip_id"] = fragment_id;
  54. options[export_size]["extension"] = Extension();
  55. options[export_size]["arguments"] = arguments;
  56. ++export_size;
  57. }
  58. return true;
  59. }
  60. BinaryData TextSubfile::MakeForImport(const BinaryData &old_data, const BinaryData &binary_data, const std::u16string &text_data,
  61. const YAML::Node &options) {
  62. return Subfile::MakeForImport(old_data, binary_data, text_data, options);
  63. }
  64. std::vector<std::u16string> TextSubfile::MakePieces(const BinaryData &data, long long &offset) {
  65. long long num_pieces = data.ToNumber<4>(offset);
  66. offset += 4;
  67. std::vector<std::u16string> text_pieces;
  68. for (long long j = 0; j < num_pieces; j++) {
  69. long long piece_size = data.ToNumber<1>(offset);
  70. if ((piece_size & 128) != 0) {
  71. piece_size = (((piece_size ^ 128) << 8) | data.ToNumber<1>(offset + 1));
  72. offset += 1;
  73. }
  74. offset += 1;
  75. BinaryData piece_data = data.CutData(offset, offset + piece_size * 2);
  76. std::u16string piece;
  77. for (long long k = 0; k < piece_size; k++) {
  78. char16_t c = char16_t(((short(piece_data[2 * k + 1])) << 8) | (short(piece_data[2 * k])));
  79. piece += c;
  80. }
  81. text_pieces.push_back(piece);
  82. offset += piece_size * 2;
  83. }
  84. return text_pieces;
  85. }
  86. std::vector<long long> TextSubfile::MakeArgumentReferences(const BinaryData &data, long long &offset) {
  87. std::vector<long long> arg_references;
  88. long long num_references = data.ToNumber<4>(offset);
  89. offset += 4;
  90. for (long long j = 0; j < num_references; j++) {
  91. arg_references.emplace_back(data.ToNumber<4>(offset));
  92. offset += 4;
  93. }
  94. return arg_references;
  95. }
  96. std::vector<std::vector<BinaryData>> TextSubfile::MakeArgumentStrings(const BinaryData &data, long long &offset) {
  97. std::vector<std::vector<BinaryData> > arg_strings;
  98. long long num_arg_strings = data.ToNumber<1>(offset);
  99. offset += 1;
  100. for (long long j = 0; j < num_arg_strings; j++) {
  101. long long num_args = data.ToNumber<4>(offset);
  102. offset += 4;
  103. arg_strings.emplace_back();
  104. for (long long k = 0; k < num_args; k++) {
  105. long long string_size = data.ToNumber<1>(offset);
  106. if ((string_size & 0x80) != 0) {
  107. string_size = (((string_size ^ 0x80) << 8) | data.ToNumber<1>(offset + 1));
  108. offset += 1;
  109. }
  110. offset += 1;
  111. arg_strings[j].emplace_back(data.CutData(offset, offset + string_size * 2));
  112. offset += string_size * 2;
  113. }
  114. }
  115. return arg_strings;
  116. }
  117. };