|
@@ -0,0 +1,302 @@
|
|
|
+#include <iostream>
|
|
|
+#include <fstream>
|
|
|
+#include <ctime>
|
|
|
+#include <algorithm>
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+#include <direct.h>
|
|
|
+#define mkdir(dir, mode) _mkdir(dir)
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "datfile.h"
|
|
|
+using namespace LOTRO_DAT;
|
|
|
+
|
|
|
+// Change these variables to true if you want export category to files.
|
|
|
+bool exportTextsToFiles = false;
|
|
|
+bool exportImagesToFiles = false;
|
|
|
+bool exportFontsToFiles = false;
|
|
|
+bool exportSoundsToFiles = false;
|
|
|
+bool exportTexturesToFiles = false;
|
|
|
+bool exportUnknownToFiles = false;
|
|
|
+
|
|
|
+bool exportTextsToDb = false;
|
|
|
+bool exportImagesToDb = false;
|
|
|
+bool exportFontsToDb = false;
|
|
|
+bool exportSoundsToDb = false;
|
|
|
+bool exportTexturesToDb = false;
|
|
|
+bool exportUnknownToDb = false;
|
|
|
+
|
|
|
+void InitializeFileLoop(DatFile& file) {
|
|
|
+ while (!file.Initialized()) {
|
|
|
+ std::cout << "Please, tell, where the .dat file is\n";
|
|
|
+ std::cout << "Enter path to file (including filename): ";
|
|
|
+ std::string filename;
|
|
|
+ std::getline(std::cin, filename);
|
|
|
+
|
|
|
+ // std::cout << "Enter file id: ";
|
|
|
+ // std::string file_id_str;
|
|
|
+ // std::getline(std::cin, file_id_str);
|
|
|
+ // int file_id = 0;
|
|
|
+ // try {
|
|
|
+ // file_id = stoi(file_id_str);
|
|
|
+ // } catch (std::invalid_argument) {
|
|
|
+ // std::cout << "Invalid dat file id entered!\n\n";
|
|
|
+ // continue;
|
|
|
+ // }
|
|
|
+
|
|
|
+ std::cout << "Opening file " << filename << std::endl;
|
|
|
+
|
|
|
+ bool result = file.Init(filename); // TODO: INIT WITH DAT FILE ID
|
|
|
+ if (!result) {
|
|
|
+ std::cout << "Dat initialisation failed.\nPlease enter path to .dat file once more\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int main() {
|
|
|
+ std::cout.precision(1);
|
|
|
+ std::cout << std::fixed;
|
|
|
+ std::cout << "Endevir's LotRO .dat extractor ver. 1.0.0" << std::endl;
|
|
|
+
|
|
|
+ std::cout << "Hello! I'm a basic shell version of .dat file extractor. I can open .dat file directly, "
|
|
|
+ "if you write path to it (with name of file) in file \"dat_file_path.txt\"\n";
|
|
|
+
|
|
|
+ DatFile file(0);
|
|
|
+
|
|
|
+ std::ifstream in_stream("dat_file_path.txt");
|
|
|
+ if (!in_stream.fail()) {
|
|
|
+ std::string filename;
|
|
|
+ std::getline(in_stream, filename);
|
|
|
+
|
|
|
+ // std::string file_id_str;
|
|
|
+ // std::getline(in_stream, file_id_str);
|
|
|
+ // int file_id = 0;
|
|
|
+ // try {
|
|
|
+ // file_id = stoi(file_id_str);
|
|
|
+ // } catch (std::invalid_argument) {
|
|
|
+ // file_id = -1;
|
|
|
+ // std::cout << "Invalid file_id on second line of file dat_file_path.txt!\n\n";
|
|
|
+ // }
|
|
|
+
|
|
|
+ // if (file_id != -1) {
|
|
|
+ std::cout << "Using .dat file from dat_file_path.txt...\n";
|
|
|
+ std::cout << "Opening file " << filename << std::endl;
|
|
|
+ bool result = file.Init(filename);
|
|
|
+ if (!result) {
|
|
|
+ std::cout << "Dat initialisation failed!\n";
|
|
|
+ }
|
|
|
+ // }
|
|
|
+ }
|
|
|
+
|
|
|
+ InitializeFileLoop(file);
|
|
|
+ std::cout << "Great! File initialised successfully!\n";
|
|
|
+ while (true) {
|
|
|
+ std::cout << "Please, choose, what should I do. I can extract .dat file to files (press 1), "
|
|
|
+ "open another .dat file (press 2), or configure, what should I extract. Choose, what to do or exit (press -1)\n";
|
|
|
+
|
|
|
+ std::cout << "Enter number of command (1-3): ";
|
|
|
+ std::string command;
|
|
|
+ std::getline(std::cin, command);
|
|
|
+
|
|
|
+ int cmd = -10;
|
|
|
+ try {
|
|
|
+ cmd = stoi(command);
|
|
|
+ } catch (std::invalid_argument) {
|
|
|
+ std::cout << "Invalid command entered!\n\n";
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd == -1) {
|
|
|
+ std::cout << "Exiting. Thanks for using me!\n";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd == 1) {
|
|
|
+ const clock_t begin_time = clock();
|
|
|
+
|
|
|
+ mkdir("Extracted data", 744);
|
|
|
+
|
|
|
+ std::time_t result = std::time(nullptr);
|
|
|
+ char *ttime = std::asctime(std::localtime(&result));
|
|
|
+ auto *out_time = new char[25];
|
|
|
+ memcpy(out_time, ttime, 24);
|
|
|
+ out_time[24] = '\0';
|
|
|
+
|
|
|
+ std::string filename = file.GetFilename();
|
|
|
+ std::cout << "FILENAME = " << filename << std::endl;
|
|
|
+ std::string output_dir = std::string("Extracted data\\") + filename.substr(std::max(filename.length() - 16, 0u), 16) + " " + std::string(out_time) + "\\";
|
|
|
+ std::replace(output_dir.begin(), output_dir.end(), ':', '-');
|
|
|
+
|
|
|
+ mkdir(output_dir.c_str(), 744);
|
|
|
+
|
|
|
+ std::cout << "Beginning unpacking... Please, wait for some minutes."
|
|
|
+ "\nMaybe it's a good idea to have a cup of tea, while unpacker is working...\n" << std::flush;
|
|
|
+
|
|
|
+ Database output_db;
|
|
|
+
|
|
|
+ if (exportImagesToDb) {
|
|
|
+ output_db.InitDatabase(output_dir + std::string("Images.db"));
|
|
|
+ int extracted_jpg_files_num = file.ExportFilesByType(JPG, output_db);
|
|
|
+ std::cout << "Extracted " << extracted_jpg_files_num << " .jpg files to Images.db" << std::endl << std::flush;
|
|
|
+ output_db.CloseDatabase();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportSoundsToDb) {
|
|
|
+ output_db.InitDatabase(output_dir + std::string("Sounds.db"));
|
|
|
+ int extracted_wav_files_num = file.ExportFilesByType(WAV, output_db);
|
|
|
+ int extracted_ogg_files_num = file.ExportFilesByType(OGG, output_db);
|
|
|
+ std::cout << "Extracted " << extracted_wav_files_num << " .wav files to Sounds.db" << std::endl << std::flush;
|
|
|
+ std::cout << "Extracted " << extracted_ogg_files_num << " .ogg files to Sounds.db" << std::endl << std::flush;
|
|
|
+ output_db.CloseDatabase();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportTextsToDb) {
|
|
|
+ output_db.InitDatabase(output_dir + std::string("Texts.db"));
|
|
|
+ int extracted_text_files_num = file.ExportFilesByType(TEXT, output_db);
|
|
|
+ std::cout << "Extracted " << extracted_text_files_num << " text files to Texts.db" << std::endl << std::flush;
|
|
|
+ output_db.CloseDatabase();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportFontsToDb) {
|
|
|
+ output_db.InitDatabase(output_dir + std::string("Fonts.db"));
|
|
|
+ int extracted_font_files_num = file.ExportFilesByType(FONT, output_db);
|
|
|
+ std::cout << "Extracted " << extracted_font_files_num << " font files to Fonts.db" << std::endl << std::flush;
|
|
|
+ output_db.CloseDatabase();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportTexturesToDb) {
|
|
|
+ output_db.InitDatabase(output_dir + std::string("Textures.db"));
|
|
|
+ int extracted_dds_files_num = file.ExportFilesByType(DDS, output_db);
|
|
|
+ std::cout << "Extracted " << extracted_dds_files_num << " .dds files to Textures.db" << std::endl << std::flush;
|
|
|
+ output_db.CloseDatabase();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportImagesToFiles) {
|
|
|
+ mkdir((output_dir + "jpg").c_str(), 744);
|
|
|
+ int extracted_jpg_files_num = file.ExportFilesByType(JPG, output_dir + "jpg\\");
|
|
|
+ std::cout << "Extracted " << extracted_jpg_files_num << " .jpg files to directory" << std::endl << std::flush;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportTexturesToFiles) {
|
|
|
+ mkdir((output_dir + "dds").c_str(), 744);
|
|
|
+ int extracted_dds_files_num = file.ExportFilesByType(DDS, output_dir + "dds\\");
|
|
|
+ std::cout << "Extracted " << extracted_dds_files_num << " .dds files to directory" << std::endl << std::flush;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportSoundsToFiles) {
|
|
|
+ mkdir((output_dir + "wav").c_str(), 744);
|
|
|
+ int extracted_wav_files_num = file.ExportFilesByType(WAV, output_dir + "wav\\");
|
|
|
+ std::cout << "Extracted " << extracted_wav_files_num << " .wav files to directory" << std::endl << std::flush;
|
|
|
+ mkdir((output_dir + "ogg").c_str(), 744);
|
|
|
+ int extracted_ogg_files_num = file.ExportFilesByType(OGG, output_dir + "ogg\\");
|
|
|
+ std::cout << "Extracted " << extracted_ogg_files_num << " .ogg files to directory" << std::endl << std::flush;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportFontsToFiles) {
|
|
|
+ mkdir((output_dir + "fonts").c_str(), 744);
|
|
|
+ int extracted_font_files_num = file.ExportFilesByType(FONT, output_dir + "fonts\\");
|
|
|
+ std::cout << "Extracted " << extracted_font_files_num << " font files to directory" << std::endl << std::flush;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportUnknownToFiles) {
|
|
|
+ mkdir((output_dir + "unknown").c_str(), 744);
|
|
|
+ int extracted_unknown_files_num = file.ExportFilesByType(UNKNOWN, output_dir + "unknown\\");
|
|
|
+ std::cout << "Extracted " << extracted_unknown_files_num << " unknown files to directory" << std::endl << std::flush;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exportTextsToFiles) {
|
|
|
+ mkdir((output_dir + "texts").c_str(), 744);
|
|
|
+ int extracted_text_files_num = file.ExportFilesByType(TEXT, output_dir + "texts\\");
|
|
|
+ std::cout << "Extracted " << extracted_text_files_num << " text files to directory" << std::endl << std::flush;
|
|
|
+ }
|
|
|
+
|
|
|
+ fprintf(stdout, "Spent %f seconds on running unpacker! Thank you for your patience!\n",
|
|
|
+ float(clock() - begin_time) / CLOCKS_PER_SEC);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd == 2) {
|
|
|
+ std::cout << "Closing file...\n";
|
|
|
+ file.Deinit();
|
|
|
+ InitializeFileLoop(file);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd == 3) {
|
|
|
+ std::cout << "Current parameters:\n";
|
|
|
+ std::cout << "(01) Export texts to files - " << (exportTextsToFiles ? "true\n" : "false\n");
|
|
|
+ std::cout << "(02) Export texts to database - " << (exportTextsToDb ? "true\n" : "false\n");
|
|
|
+
|
|
|
+ std::cout << "(11) Export images to files - " << (exportImagesToFiles ? "true\n" : "false\n");
|
|
|
+ std::cout << "(12) Export images to database - " << (exportImagesToDb ? "true\n" : "false\n");
|
|
|
+
|
|
|
+ std::cout << "(21) Export fonts to files - " << (exportFontsToFiles ? "true\n" : "false\n");
|
|
|
+ std::cout << "(22) Export fonts to database - " << (exportFontsToDb ? "true\n" : "false\n");
|
|
|
+
|
|
|
+ std::cout << "(31) Export sounds to files - " << (exportSoundsToFiles ? "true\n" : "false\n");
|
|
|
+ std::cout << "(32) Export sounds to database - " << (exportSoundsToDb ? "true\n" : "false\n");
|
|
|
+
|
|
|
+ std::cout << "(41) Export textures to files - " << (exportTexturesToFiles ? "true\n" : "false\n");
|
|
|
+ std::cout << "(42) Export textures to database - " << (exportTexturesToDb ? "true\n" : "false\n");
|
|
|
+
|
|
|
+ std::cout << "(51) Export unknown files to files - " << (exportUnknownToFiles ? "true\n" : "false\n");
|
|
|
+ std::cout << "(52) Export unknown files to database - " << (exportUnknownToDb ? "true\n" : "false\n");
|
|
|
+
|
|
|
+ std::cout << "Enter number of parameter to change (or -1 to exit this menu): ";
|
|
|
+
|
|
|
+ int number = 0;
|
|
|
+
|
|
|
+ std::cin >> number;
|
|
|
+ std::string tmp;
|
|
|
+ std::getline(std::cin, tmp);
|
|
|
+
|
|
|
+ if (number == -1) {
|
|
|
+ std::cout << "Returning to main menu..\n";
|
|
|
+ cmd = 0;
|
|
|
+ } else {
|
|
|
+ switch (number) {
|
|
|
+ case 01:
|
|
|
+ exportTextsToFiles = !exportTextsToFiles;
|
|
|
+ break;
|
|
|
+ case 02:
|
|
|
+ exportTextsToDb = !exportTextsToDb;
|
|
|
+ break;
|
|
|
+ case 11:
|
|
|
+ exportImagesToFiles = !exportImagesToFiles;
|
|
|
+ break;
|
|
|
+ case 12:
|
|
|
+ exportImagesToDb = !exportImagesToDb;
|
|
|
+ break;
|
|
|
+ case 21:
|
|
|
+ exportFontsToFiles = !exportFontsToFiles;
|
|
|
+ break;
|
|
|
+ case 22:
|
|
|
+ exportFontsToDb = !exportFontsToDb;
|
|
|
+ break;
|
|
|
+ case 31:
|
|
|
+ exportSoundsToFiles = !exportSoundsToFiles;
|
|
|
+ break;
|
|
|
+ case 32:
|
|
|
+ exportSoundsToDb = !exportSoundsToDb;
|
|
|
+ break;
|
|
|
+ case 41:
|
|
|
+ exportTexturesToFiles = !exportTexturesToFiles;
|
|
|
+ break;
|
|
|
+ case 42:
|
|
|
+ exportTexturesToDb = !exportTexturesToDb;
|
|
|
+ break;
|
|
|
+ case 51:
|
|
|
+ exportUnknownToFiles = !exportTexturesToFiles;
|
|
|
+ break;
|
|
|
+ case 52:
|
|
|
+ exportUnknownToDb = !exportTexturesToDb;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ std::cout << "Incorrect number. Returning to main menu..\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ file.Deinit();
|
|
|
+ system("pause");
|
|
|
+ return 0;
|
|
|
+}
|