|
@@ -29,7 +29,8 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
try {
|
|
|
MakeDictionary();
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
fprintf(stderr, "Unable to make dictionary!! Unable to init DatFile!!!");
|
|
|
return;
|
|
|
}
|
|
@@ -44,7 +45,9 @@ namespace LOTRO_DAT {
|
|
|
if (patched_) {
|
|
|
std::cout << "There are some updated files. Rewriting dictionary..." << std::endl << std::flush;
|
|
|
UpdateHeader();
|
|
|
+ std::cout << "Updated header..." << std::endl << std::flush;
|
|
|
UpdateSubdirectories();
|
|
|
+ std::cout << "Updated subdirectories..." << std::endl << std::flush;
|
|
|
}
|
|
|
|
|
|
if (file_handler_ != nullptr)
|
|
@@ -61,7 +64,7 @@ namespace LOTRO_DAT {
|
|
|
/// Returns true, if file was successfully extracted;
|
|
|
/// Throws DatException() if undefined behaviour happened
|
|
|
|
|
|
- bool DatFile::ExtractFile(long long file_id, const std::string path) {
|
|
|
+ bool DatFile::ExtractFile(long long file_id, const std::string &path) {
|
|
|
if (dat_state_ != READY) {
|
|
|
throw DatException("Bad DatFile::ExtractFile() - invalid DatFile state!", EXPORT_EXCEPTION);
|
|
|
}
|
|
@@ -69,7 +72,9 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
try {
|
|
|
file_data = GetFileData(dictionary_[file_id], 8);
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+
|
|
|
fprintf(stderr, "Unable to extract file due to uncaught exception while getting file data. Passing...\n");
|
|
|
return false;
|
|
|
}
|
|
@@ -81,7 +86,9 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
try {
|
|
|
dictionary_[file_id]->PrepareForExport(file_data, export_size, binary_data, text_data, options);
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+
|
|
|
fprintf(stderr, "Unable to extract file due to uncaught exception while preparing file for export. Passing...\n");
|
|
|
return false;
|
|
|
}
|
|
@@ -108,7 +115,9 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
try {
|
|
|
file_data = GetFileData(dictionary_[file_id], 8);
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+
|
|
|
fprintf(stderr, "Unable to extract file due to uncaught exception while getting file data. Passing...\n");
|
|
|
return false;
|
|
|
}
|
|
@@ -120,7 +129,9 @@ namespace LOTRO_DAT {
|
|
|
|
|
|
try {
|
|
|
dictionary_[file_id]->PrepareForExport(file_data, export_size, binary_data, text_data, options);
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+
|
|
|
fprintf(stderr, "Unable to extract file due to uncaught exception while preparing file for export. Passing...\n");
|
|
|
return false;
|
|
|
}
|
|
@@ -130,7 +141,11 @@ namespace LOTRO_DAT {
|
|
|
option << options[i];
|
|
|
try {
|
|
|
db->PushFile(binary_data[i], text_data[i], option.str());
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+ printf("Caught %s exception.", e.what());
|
|
|
+ fflush(stdout);
|
|
|
+
|
|
|
fprintf(stderr, "Unable to put file or it's part to database. Continuing without this part. Database may be not complete\n");
|
|
|
}
|
|
|
}
|
|
@@ -179,6 +194,39 @@ namespace LOTRO_DAT {
|
|
|
return success;
|
|
|
}
|
|
|
|
|
|
+ /// TODO: Write desctiption
|
|
|
+ bool DatFile::PatchFile(const char *filename, YAML::Node options, long long dat_id) {
|
|
|
+ if (dat_id != dat_id_)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ BinaryData data;
|
|
|
+ data.ReadFromFile(filename);
|
|
|
+
|
|
|
+ auto file_id = options["fid"].as<long long>();
|
|
|
+ BinaryData old_data = GetFileData(dictionary_[file_id]);
|
|
|
+ data = dictionary_[file_id]->MakeForImport(old_data, data, u"", options);
|
|
|
+
|
|
|
+ try {
|
|
|
+ ApplyFilePatch(dictionary_[file_id], data);
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+
|
|
|
+ fprintf(stderr,
|
|
|
+ "Some errors happened while patching file with id = %lld. Continuing process without this file..\n"
|
|
|
+ "WARNING: DAT FILE CAN BE CORRUPTED!\n", file_id);
|
|
|
+ printf("Some errors happened while patching file with id = %lld. Continuing process without this file..\n"
|
|
|
+ "WARNING: DAT FILE CAN BE CORRUPTED!\n", file_id);
|
|
|
+ fflush(stdout);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// TODO: Write description
|
|
|
+ bool DatFile::PatchDatabase(Database *db) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
/// DatFile::WriteUnorderedDictionary(...);
|
|
|
/// Prints list of all found files with some information about them to file.
|
|
|
/// Gets std::string path - path to directory, where the file will be written with name "dict.txt"
|
|
@@ -330,7 +378,9 @@ namespace LOTRO_DAT {
|
|
|
throw DatException("Bad DatFile::MakeDictionary() - DatFile isn't in valid state!", INIT_EXCEPTION);
|
|
|
try {
|
|
|
root_directory_->MakeDictionary(dictionary_);
|
|
|
- } catch (...) {
|
|
|
+ } catch (std::exception &e) {
|
|
|
+ fprintf(stderr, "Caught %s exception.", e.what());
|
|
|
+
|
|
|
fprintf(stderr, "Bad DatFile::MakeDictionary() - File is corrupted?\n");
|
|
|
return;
|
|
|
}
|
|
@@ -374,22 +424,51 @@ namespace LOTRO_DAT {
|
|
|
/// Special functions used by patch process.
|
|
|
/// Shouldn't be used by any external class.
|
|
|
|
|
|
- void DatFile::ApplyFilePatch(const Subfile *file, const BinaryData &data) {
|
|
|
+ void DatFile::ApplyFilePatch(Subfile *file, const BinaryData &data) {
|
|
|
+ if (patched_list.count(file->file_id()) != 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
auto journal = GetFragmentationJournal();
|
|
|
|
|
|
- // TODO: write content
|
|
|
+ file->file_size_ = data.size() - 8;
|
|
|
+ file->fragments_count_ = 0;
|
|
|
+
|
|
|
+ if (data.size() > file->block_size()) {
|
|
|
+ file->file_offset_ = journal[0].second;
|
|
|
+ file->block_size_ = data.size();
|
|
|
+ journal[0].second += data.size();
|
|
|
|
|
|
+ if (journal[0].first < data.size()) {
|
|
|
+ UpdateFileSize();
|
|
|
+ journal[0].first = 0;
|
|
|
+ std::cout << "File size updated - new size is " << file_size_ << std::endl;
|
|
|
+ } else {
|
|
|
+ journal[0].first -= data.size();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ BinaryData fragments_count(4);
|
|
|
+ fragments_count.FromNumber<4>(file->fragments_count_);
|
|
|
+
|
|
|
+ BinaryData file_data = fragments_count + data.CutData(4);
|
|
|
+
|
|
|
+ if (file->file_id() != file_data.ToNumber<4>(8))
|
|
|
+ throw DatException("Bad DatFile::ApplyFilePatch() - Created data's file_id doesn't match to original! "
|
|
|
+ "Patch wasn't written to .dat file");
|
|
|
+
|
|
|
+ WriteData(file_data, file_data.size(), file->file_offset());
|
|
|
+ patched_list[file->file_id()] = new BinaryData(file->MakeHeaderData());
|
|
|
UpdateFragmentationJournal(journal);
|
|
|
- patched_ = true;
|
|
|
}
|
|
|
|
|
|
void DatFile::UpdateSubdirectories() {
|
|
|
- root_directory_ -> UpdateDirectories();
|
|
|
- return;
|
|
|
+ root_directory_->UpdateDirectories(patched_list);
|
|
|
}
|
|
|
|
|
|
std::vector<std::pair<long long, long long> > DatFile::GetFragmentationJournal() {
|
|
|
BinaryData data(8);
|
|
|
+ std::cout << "journal offset: " << fragmentation_journal_offset_ << std::endl;
|
|
|
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)));
|
|
@@ -405,6 +484,9 @@ namespace LOTRO_DAT {
|
|
|
data.FromNumber<4>(constant2_);
|
|
|
WriteData(data, 4, 0x140);
|
|
|
|
|
|
+ data.FromNumber<4>(file_size_);
|
|
|
+ WriteData(data, 4, 0x148);
|
|
|
+
|
|
|
data.FromNumber<4>(version1_);
|
|
|
WriteData(data, 4, 0x14C);
|
|
|
|
|
@@ -412,14 +494,14 @@ namespace LOTRO_DAT {
|
|
|
WriteData(data, 4, 0x150);
|
|
|
|
|
|
data.FromNumber<4>(fragmentation_journal_offset_);
|
|
|
- WriteData(data, 4, 0x150);
|
|
|
+ WriteData(data, 4, 0x154);
|
|
|
|
|
|
data.FromNumber<4>(root_directory_offset_);
|
|
|
- WriteData(data, 4, 0x150);
|
|
|
+ WriteData(data, 4, 0x160);
|
|
|
}
|
|
|
|
|
|
void DatFile::UpdateFragmentationJournal(const std::vector<std::pair<long long, long long> > &journal) {
|
|
|
- for (int i = 0; i < journal.size(); i++) {
|
|
|
+ for (unsigned i = 0; i < journal.size(); i++) {
|
|
|
long long size = journal[i].first;
|
|
|
long long offset = journal[i].second;
|
|
|
|
|
@@ -431,5 +513,10 @@ namespace LOTRO_DAT {
|
|
|
WriteData(data, 4, fragmentation_journal_offset_ + 8 * (i + 1) + 4);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ void DatFile::UpdateFileSize() {
|
|
|
+ _fseeki64(file_handler_, 0, SEEK_END);
|
|
|
+ file_size_ = _ftelli64(file_handler_);
|
|
|
+ }
|
|
|
}
|
|
|
}
|