DatFile.cpp 5.9 KB

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