|
@@ -0,0 +1,234 @@
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#define _CRT_SECURE_NO_WARNINGS
|
|
|
+#include <iostream>
|
|
|
+#include <ctime>
|
|
|
+#include <algorithm>
|
|
|
+
|
|
|
+#ifdef WIN32
|
|
|
+#include <direct.h>
|
|
|
+#define mkdir(dir, mode) _mkdir(dir)
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "LotroDatPatcher.h"
|
|
|
+using namespace LOTRO_DAT;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const std::string path = "E:\\SteamLibrary\\steamapps\\common\\";
|
|
|
+const std::string filename = "client_local_English.dat";
|
|
|
+
|
|
|
+
|
|
|
+const bool exportImagesToFiles = false;
|
|
|
+const bool exportFontsToFiles = true;
|
|
|
+const bool exportSoundsToFiles = false;
|
|
|
+const bool exportTexturesToFiles = false;
|
|
|
+const bool exportUnknownToFiles = true;
|
|
|
+
|
|
|
+
|
|
|
+const bool exportTextsToDb = true;
|
|
|
+const bool exportImagesToDb = false;
|
|
|
+const bool exportFontsToDb = false;
|
|
|
+const bool exportSoundsToDb = false;
|
|
|
+const bool exportTexturesToDb = false;
|
|
|
+const bool exportUnknownToDb = false;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+int main() {
|
|
|
+ const clock_t begin_time = clock();
|
|
|
+
|
|
|
+ std::time_t time = std::time(nullptr);
|
|
|
+ mkdir("Extracted data", 744);
|
|
|
+
|
|
|
+ std::time_t result = std::time(nullptr);
|
|
|
+ char *ttime = std::asctime(std::localtime(&result));
|
|
|
+ char *out_time = new char[25];
|
|
|
+ memcpy(out_time, ttime, 24);
|
|
|
+ out_time[24] = '\0';
|
|
|
+
|
|
|
+ std::string output_dir = std::string("Extracted data\\") + filename + " " + std::string(out_time) + "\\";
|
|
|
+ std::replace(output_dir.begin(), output_dir.end(), ':', '-');
|
|
|
+
|
|
|
+ mkdir(output_dir.c_str(), 744);
|
|
|
+ freopen((output_dir + std::string("errors.log")).c_str(), "w", stderr);
|
|
|
+
|
|
|
+ try {
|
|
|
+ std::string txt_dir = "txt\\";
|
|
|
+ std::string jpg_dir = "jpg\\";
|
|
|
+ std::string dds_dir = "dds\\";
|
|
|
+ std::string wav_dir = "wav\\";
|
|
|
+ std::string ogg_dir = "ogg\\";
|
|
|
+ std::string font_dir = "font\\";
|
|
|
+ std::string unk_dir = "unk\\";
|
|
|
+
|
|
|
+ int txt_all = 0, txt_suc = 0;
|
|
|
+ int jpg_all = 0, jpg_suc = 0;
|
|
|
+ int dds_all = 0, dds_suc = 0;
|
|
|
+ int wav_all = 0, wav_suc = 0;
|
|
|
+ int ogg_all = 0, ogg_suc = 0;
|
|
|
+ int font_all = 0, font_suc = 0;
|
|
|
+ int unk_all = 0, unk_suc = 0;
|
|
|
+
|
|
|
+ mkdir(output_dir.c_str(), 744);
|
|
|
+ mkdir((output_dir + txt_dir).c_str(), 744);
|
|
|
+ mkdir((output_dir + jpg_dir).c_str(), 744);
|
|
|
+ mkdir((output_dir + dds_dir).c_str(), 744);
|
|
|
+ mkdir((output_dir + wav_dir).c_str(), 744);
|
|
|
+ mkdir((output_dir + ogg_dir).c_str(), 744);
|
|
|
+ mkdir((output_dir + font_dir).c_str(), 744);
|
|
|
+ mkdir((output_dir + unk_dir).c_str(), 744);
|
|
|
+
|
|
|
+ Database *images = nullptr;
|
|
|
+ Database *sounds = nullptr;
|
|
|
+ Database *texts = nullptr;
|
|
|
+ Database *fonts = nullptr;
|
|
|
+ Database *textures = nullptr;
|
|
|
+ Database *unknown = nullptr;
|
|
|
+
|
|
|
+ if (exportImagesToDb) images = new Database(output_dir + std::string("Images.db"));
|
|
|
+ if (exportSoundsToDb) sounds = new Database(output_dir + std::string("Sounds.db"));
|
|
|
+ if (exportTextsToDb) texts = new Database(output_dir + std::string("Texts.db"));
|
|
|
+ if (exportFontsToDb) fonts = new Database(output_dir + std::string("Fonts.db"));
|
|
|
+ if (exportTexturesToDb) textures = new Database(output_dir + std::string("Textures.db"));
|
|
|
+ if (exportUnknownToDb) unknown = new Database(output_dir + std::string("Unknown.db"));
|
|
|
+
|
|
|
+ std::cout << "Starting search...\n";
|
|
|
+ DatFile a(path + filename, 0);
|
|
|
+ std::cout << "Total files found: " << a.dictionary().size() << std::endl;
|
|
|
+
|
|
|
+ std::cout << "Writing unordered dictionary:\n";
|
|
|
+ FILE *f;
|
|
|
+ fopen_s(&f, (output_dir + "dict.txt").c_str(), "w");
|
|
|
+ fprintf(f, "file_id offset size size2 extension\n");
|
|
|
+ for (auto i : a.dictionary()) {
|
|
|
+ std::string extension = "unk";
|
|
|
+ EXTENSION ext = i.second->ext();
|
|
|
+ if (ext == TXT) extension = "txt";
|
|
|
+ if (ext == JPG) extension = "jpg";
|
|
|
+ if (ext == DDS) extension = "dds";
|
|
|
+ if (ext == WAV) extension = "wav";
|
|
|
+ if (ext == OGG) extension = "ogg";
|
|
|
+ if (ext == FONT) extension = "font";
|
|
|
+ fprintf(f, "%lld %lld %lld %lld %s\n", i.second->file_id(), i.second->file_offset(), i.second->file_size(),
|
|
|
+ i.second->block_size(), extension.c_str());
|
|
|
+ }
|
|
|
+ fclose(f);
|
|
|
+
|
|
|
+ std::cout << "Beginning unpacking...\n";
|
|
|
+
|
|
|
+ long long all = a.dictionary().size();
|
|
|
+ long long counter = 0;
|
|
|
+
|
|
|
+ for (auto i : a.dictionary()) {
|
|
|
+ EXTENSION ext = i.second->ext();
|
|
|
+ if (ext == TXT) {
|
|
|
+ txt_all++;
|
|
|
+ if (exportTextsToDb)
|
|
|
+ txt_suc += i.second->ExportFile(
|
|
|
+ (output_dir + txt_dir + std::to_string(i.second->file_id())).c_str(), texts);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ext == JPG) {
|
|
|
+ jpg_all++;
|
|
|
+ if (exportImagesToDb)
|
|
|
+ jpg_suc += i.second->ExportFile(
|
|
|
+ (output_dir + jpg_dir + std::to_string(i.second->file_id())).c_str(), images);
|
|
|
+ if (exportImagesToFiles)
|
|
|
+ jpg_suc += i.second->ExportFile(
|
|
|
+ (output_dir + jpg_dir + std::to_string(i.second->file_id())).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ext == DDS) {
|
|
|
+ dds_all++;
|
|
|
+ if (exportTexturesToDb)
|
|
|
+ dds_suc += i.second->ExportFile(
|
|
|
+ (output_dir + dds_dir + std::to_string(i.second->file_id())).c_str(), textures);
|
|
|
+ if (exportTexturesToFiles)
|
|
|
+ dds_suc += i.second->ExportFile(
|
|
|
+ (output_dir + dds_dir + std::to_string(i.second->file_id())).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ext == WAV) {
|
|
|
+ wav_all++;
|
|
|
+ if (exportSoundsToDb)
|
|
|
+ wav_suc += i.second->ExportFile(
|
|
|
+ (output_dir + wav_dir + std::to_string(i.second->file_id())).c_str(), sounds);
|
|
|
+ if (exportSoundsToFiles)
|
|
|
+ wav_suc += i.second->ExportFile(
|
|
|
+ (output_dir + wav_dir + std::to_string(i.second->file_id())).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ext == OGG) {
|
|
|
+ ogg_all++;
|
|
|
+ if (exportSoundsToDb)
|
|
|
+ ogg_suc += i.second->ExportFile(
|
|
|
+ (output_dir + ogg_dir + std::to_string(i.second->file_id())).c_str(), sounds);
|
|
|
+ if (exportSoundsToFiles)
|
|
|
+ ogg_suc += i.second->ExportFile(
|
|
|
+ (output_dir + ogg_dir + std::to_string(i.second->file_id())).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ext == FONT) {
|
|
|
+ font_all++;
|
|
|
+ if (exportFontsToDb)
|
|
|
+ font_suc += i.second->ExportFile(
|
|
|
+ (output_dir + font_dir + std::to_string(i.second->file_id())).c_str(), fonts);
|
|
|
+ if (exportFontsToFiles)
|
|
|
+ font_suc += i.second->ExportFile(
|
|
|
+ (output_dir + font_dir + std::to_string(i.second->file_id())).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ext == UNKNOWN) {
|
|
|
+ unk_all++;
|
|
|
+ if (exportUnknownToDb)
|
|
|
+ unk_suc += i.second->ExportFile(
|
|
|
+ (output_dir + unk_dir + std::to_string(i.second->file_id())).c_str(), unknown);
|
|
|
+ if (exportUnknownToFiles)
|
|
|
+ unk_suc += i.second->ExportFile(
|
|
|
+ (output_dir + unk_dir + std::to_string(i.second->file_id())).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ counter++;
|
|
|
+ if ((counter - 1) * 100ll / all != counter * 100ll / all) {
|
|
|
+ fprintf(stdout, "Done: %lld%%\n", counter * 100ll / all);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ delete images;
|
|
|
+ delete sounds;
|
|
|
+ delete texts;
|
|
|
+ delete fonts;
|
|
|
+ delete textures;
|
|
|
+ delete unknown;
|
|
|
+
|
|
|
+ std::cout << "Total found:" << std::endl;
|
|
|
+ std::cout << "Txt: " << txt_all << std::endl
|
|
|
+ << "JPG: " << jpg_all << std::endl
|
|
|
+ << "DDS: " << dds_all << std::endl
|
|
|
+ << "WAV: " << wav_all << std::endl
|
|
|
+ << "OGG: " << ogg_all << std::endl
|
|
|
+ << "Fonts " << font_all << std::endl
|
|
|
+ << "Unknown: " << unk_all << std::endl;
|
|
|
+
|
|
|
+ std::cout << "Total exported (counted both to files and databases):" << std::endl;
|
|
|
+ std::cout << "Txt: " << txt_suc << std::endl
|
|
|
+ << "JPG: " << jpg_suc << std::endl
|
|
|
+ << "DDS: " << dds_suc << std::endl
|
|
|
+ << "WAV: " << wav_suc << std::endl
|
|
|
+ << "OGG: " << ogg_suc << std::endl
|
|
|
+ << "Fonts " << font_suc << std::endl
|
|
|
+ << "Unknown: " << unk_suc << std::endl;
|
|
|
+
|
|
|
+ fprintf(stdout, "Spent %f seconds on running unpacker! Thank you for your patience!\n",
|
|
|
+ float(clock() - begin_time) / CLOCKS_PER_SEC);
|
|
|
+ system("pause");
|
|
|
+ } catch (...) {
|
|
|
+ printf("Some critical errors occured. Need to stop execution. See information in errors.log file");
|
|
|
+ fprintf(stderr, "Some critical errors occured. Need to stop execution now...");
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|