|
@@ -16,11 +16,13 @@ extern "C++"
|
|
|
namespace LOTRO_DAT {
|
|
|
DatFile::DatFile() {
|
|
|
dat_state_ = CLOSED;
|
|
|
+ patched_ = false;
|
|
|
}
|
|
|
|
|
|
DatFile::DatFile(const char *filename, int dat_id) {
|
|
|
dat_id_ = dat_id;
|
|
|
dat_state_ = CLOSED;
|
|
|
+ patched_ = false;
|
|
|
OpenDatFile(filename);
|
|
|
ReadSuperBlock();
|
|
|
MakeDirectories();
|
|
@@ -39,6 +41,12 @@ namespace LOTRO_DAT {
|
|
|
}
|
|
|
|
|
|
DatFile::~DatFile() {
|
|
|
+ if (patched_) {
|
|
|
+ std::cout << "There are some updated files. Rewriting dictionary..." << std::endl << std::flush;
|
|
|
+ UpdateHeader();
|
|
|
+ UpdateSubdirectories();
|
|
|
+ }
|
|
|
+
|
|
|
if (file_handler_ != nullptr)
|
|
|
fclose(file_handler_);
|
|
|
delete file_handler_;
|
|
@@ -79,7 +87,7 @@ namespace LOTRO_DAT {
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < export_size; ++i) {
|
|
|
- binary_data[i].WriteToFile(path + "_" + std::to_string(i) + options[i]["extension"].as<std::string>());
|
|
|
+ binary_data[i].WriteToFile(path + "_" + std::to_string(i) + options[i]["ext"].as<std::string>());
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
@@ -231,6 +239,7 @@ namespace LOTRO_DAT {
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/// DatFile constants' getters.
|
|
|
|
|
|
long long DatFile::constant1() const {
|
|
@@ -287,6 +296,7 @@ namespace LOTRO_DAT {
|
|
|
constant2_ = data.ToNumber<4>(0x140);
|
|
|
version1_ = data.ToNumber<4>(0x14C);
|
|
|
version2_ = data.ToNumber<4>(0x150);
|
|
|
+ fragmentation_journal_offset_ = data.ToNumber<4>(0x154);
|
|
|
root_directory_offset_ = data.ToNumber<4>(0x160);
|
|
|
auto size1 = data.ToNumber<4>(0x148);
|
|
|
|
|
@@ -360,5 +370,66 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
fwrite(data.data() + data_offset, unsigned(size), 1, file_handler_);
|
|
|
}
|
|
|
+
|
|
|
+ /// Special functions used by patch process.
|
|
|
+ /// Shouldn't be used by any external class.
|
|
|
+
|
|
|
+ void DatFile::ApplyFilePatch(const Subfile *file, const BinaryData &data) {
|
|
|
+ auto journal = GetFragmentationJournal();
|
|
|
+
|
|
|
+ // TODO: write content
|
|
|
+
|
|
|
+ UpdateFragmentationJournal(journal);
|
|
|
+ patched_ = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ void DatFile::UpdateSubdirectories() {
|
|
|
+ root_directory_ -> UpdateDirectories();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<std::pair<long long, long long> > DatFile::GetFragmentationJournal() {
|
|
|
+ BinaryData data(8);
|
|
|
+ ReadData(data, 8, fragmentation_journal_offset_ + 8);
|
|
|
+ std::vector<std::pair<long long, long long> > result;
|
|
|
+ result.emplace_back(std::make_pair(data.ToNumber<4>(0), data.ToNumber<4>(4)));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ void DatFile::UpdateHeader() {
|
|
|
+ BinaryData data(4);
|
|
|
+
|
|
|
+ data.FromNumber<4>(constant1_);
|
|
|
+ WriteData(data, 4, 0x100);
|
|
|
+
|
|
|
+ data.FromNumber<4>(constant2_);
|
|
|
+ WriteData(data, 4, 0x140);
|
|
|
+
|
|
|
+ data.FromNumber<4>(version1_);
|
|
|
+ WriteData(data, 4, 0x14C);
|
|
|
+
|
|
|
+ data.FromNumber<4>(version2_);
|
|
|
+ WriteData(data, 4, 0x150);
|
|
|
+
|
|
|
+ data.FromNumber<4>(fragmentation_journal_offset_);
|
|
|
+ WriteData(data, 4, 0x150);
|
|
|
+
|
|
|
+ data.FromNumber<4>(root_directory_offset_);
|
|
|
+ WriteData(data, 4, 0x150);
|
|
|
+ }
|
|
|
+
|
|
|
+ void DatFile::UpdateFragmentationJournal(const std::vector<std::pair<long long, long long> > &journal) {
|
|
|
+ for (int i = 0; i < journal.size(); i++) {
|
|
|
+ long long size = journal[i].first;
|
|
|
+ long long offset = journal[i].second;
|
|
|
+
|
|
|
+ BinaryData data(4);
|
|
|
+ data.FromNumber<4>(size);
|
|
|
+ WriteData(data, 4, fragmentation_journal_offset_ + 8 * (i + 1));
|
|
|
+
|
|
|
+ data.FromNumber<4>(offset);
|
|
|
+ WriteData(data, 4, fragmentation_journal_offset_ + 8 * (i + 1) + 4);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|