DatFile.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. //
  2. // Created by Иван_Архипов on 31.10.2017.
  3. //
  4. #include "DatFile.h"
  5. #include "BinaryData.h"
  6. #include "DatException.h"
  7. #include "SubDirectory.h"
  8. #include "Subfile.h"
  9. #include <locale>
  10. extern "C++"
  11. {
  12. namespace LOTRO_DAT {
  13. DatFile::DatFile() {
  14. dat_state_ = CLOSED;
  15. }
  16. DatFile::DatFile(const char *filename, int dat_id) {
  17. dat_id_ = dat_id;
  18. dat_state_ = CLOSED;
  19. OpenDatFile(filename);
  20. ReadSuperBlock();
  21. MakeDirectories();
  22. try {
  23. MakeDictionary();
  24. } catch (...) {
  25. fprintf(stderr, "Unable to make dictionary!! Unable to init DatFile!!!");
  26. return;
  27. }
  28. if (dat_state_ == SUCCESS_DICTIONARY)
  29. dat_state_ = READY;
  30. else
  31. throw DatException("Bad DatFile initialization! Not all init states were successfully passed!",
  32. INIT_EXCEPTION);
  33. }
  34. DatFile::DatFile(const std::string &filename, int dat_id) {
  35. dat_id_ = dat_id;
  36. dat_state_ = CLOSED;
  37. OpenDatFile(filename.c_str());
  38. ReadSuperBlock();
  39. MakeDirectories();
  40. MakeDictionary();
  41. if (dat_state_ == SUCCESS_DICTIONARY)
  42. dat_state_ = READY;
  43. else
  44. throw DatException("Bad DatFile initialization! Not all init states were successfully passed!",
  45. INIT_EXCEPTION);
  46. }
  47. DatFile::~DatFile() {
  48. if (file_handler_ != nullptr)
  49. fclose(file_handler_);
  50. delete file_handler_;
  51. delete root_directory_;
  52. }
  53. void DatFile::OpenDatFile(const char *dat_name) {
  54. if (dat_state_ != CLOSED)
  55. throw DatException("Bad initialisation of DatFile - current DatFile isn't in correct state!",
  56. INIT_EXCEPTION);
  57. fopen_s(&file_handler_, dat_name, "r+b");
  58. if (file_handler_ == nullptr) {
  59. std::string err = "Bad DatFile::OpenDatFile. Unable to open file ";
  60. err += dat_name;
  61. throw DatException(err.c_str(), INIT_EXCEPTION);
  62. }
  63. _fseeki64(file_handler_, 0, SEEK_END);
  64. file_size_ = _ftelli64(file_handler_);
  65. _fseeki64(file_handler_, 0, SEEK_SET);
  66. dat_state_ = SUCCESS_OPENED;
  67. }
  68. void DatFile::ReadSuperBlock() {
  69. if (dat_state_ != SUCCESS_OPENED)
  70. throw DatException("Bad DatFile::ReadSuperBlock() - DatFile isn't in valid state!", INIT_EXCEPTION);
  71. BinaryData data(1024);
  72. ReadData(data, 1024);
  73. constant1_ = data.ToNumber<4>(0x100);
  74. constant2_ = data.ToNumber<4>(0x140);
  75. version1_ = data.ToNumber<4>(0x14C);
  76. version2_ = data.ToNumber<4>(0x150);
  77. root_directory_offset_ = data.ToNumber<4>(0x160);
  78. auto size1 = data.ToNumber<4>(0x148);
  79. if (constant1_ != 0x4C5000)
  80. throw DatException(
  81. "Bad DatFile::ReadSuperBlock - variable at position 0x100 is not equal to .dat file constant!",
  82. INIT_EXCEPTION);
  83. if (constant2_ != 0x5442)
  84. throw DatException(
  85. "Bad DatFile::ReadSuperBlock - variable at position 0x140 is not equal to .dat file constant!",
  86. INIT_EXCEPTION);
  87. if (file_size_ != size1)
  88. throw DatException(
  89. "Bad DatFile::ReadSuperBlock - variable at 0x148 position is not equal to .dat file size!",
  90. INIT_EXCEPTION);
  91. dat_state_ = SUCCESS_SUPERBLOCK;
  92. }
  93. void DatFile::MakeDirectories() {
  94. if (dat_state_ != SUCCESS_SUPERBLOCK)
  95. throw DatException("Bad DatFile::MakeDirectories() - DatFile isn't in valid state!", INIT_EXCEPTION);
  96. root_directory_ = new SubDirectory((unsigned) root_directory_offset_, this);
  97. dat_state_ = SUCCESS_DIRECTORIES;
  98. }
  99. void DatFile::MakeDictionary() {
  100. if (dat_state_ != SUCCESS_DIRECTORIES)
  101. throw DatException("Bad DatFile::MakeDictionary() - DatFile isn't in valid state!", INIT_EXCEPTION);
  102. try {
  103. root_directory_->MakeDictionary(dictionary_);
  104. } catch (...) {
  105. fprintf(stderr, "Bad DatFile::MakeDictionary() - File is corrupted?\n");
  106. return;
  107. }
  108. dat_state_ = SUCCESS_DICTIONARY;
  109. }
  110. void DatFile::ReadData(BinaryData &data, long long size, long long offset, long long data_offset) {
  111. if (dat_state_ == CLOSED)
  112. throw DatException("Bad DatFile::ReadData() - DatFile isn't in valid state!", READ_EXCEPTION);
  113. if (data_offset + size > data.size()) {
  114. std::string err = "Bad DatFile::ReadData - trying to read more than BinaryData size\n";
  115. err += std::string("Reading ") + std::to_string(size) + std::string(" bytes from ")
  116. + std::to_string(offset) + std::string(" position in dat file.");
  117. throw DatException(err.c_str(), READ_EXCEPTION);
  118. }
  119. if (offset + size > file_size()) {
  120. std::string err = "Bad DatFile::ReadData - trying to read more than DatFile size elapsed\n";
  121. err += std::string("Reading ") + std::to_string(size) + std::string(" bytes from ")
  122. + std::to_string(offset) + std::string(" position in dat file.");
  123. throw DatException(err.c_str(), READ_EXCEPTION);
  124. }
  125. _fseeki64(file_handler_, offset, SEEK_SET);
  126. fread(data.data() + data_offset, size, 1, file_handler_);
  127. data.CheckCompression();
  128. }
  129. void DatFile::WriteData(const BinaryData &data, long long size, long long offset, long long data_offset) {
  130. if (dat_state_ != READY)
  131. throw DatException("Bad DatFile::WriteData() - DatFile isn't in valid state!", WRITE_EXCEPTION);
  132. _fseeki64(file_handler_, offset, SEEK_SET);
  133. if (data_offset + size > data.size())
  134. throw DatException("Bad DatFile::WriteData - trying to write more than BinaryData size", WRITE_EXCEPTION);
  135. fwrite(data.data() + data_offset, size, 1, file_handler_);
  136. }
  137. long long DatFile::constant1() const {
  138. return constant1_;
  139. }
  140. long long DatFile::constant2() const {
  141. return constant2_;
  142. }
  143. long long DatFile::file_size() const {
  144. return file_size_;
  145. }
  146. long long DatFile::version1() const {
  147. return version1_;
  148. }
  149. long long DatFile::version2() const {
  150. return version2_;
  151. }
  152. const std::unordered_map<long long, Subfile *> &DatFile::dictionary() {
  153. return dictionary_;
  154. }
  155. }
  156. }