소스 검색

ver 2.1.0

Changed structure of project in order to use it as library. Added basic API functions for easier library management
Ivan Arkhipov 6 년 전
부모
커밋
c8c15181bd
12개의 변경된 파일137개의 추가작업 그리고 100개의 파일을 삭제
  1. 12 1
      CHANGELOG
  2. 20 17
      CMakeLists.txt
  3. 11 7
      include/DatFile.h
  4. 2 2
      include/Database.h
  5. 0 0
      include/LotroDat.h
  6. 4 0
      include/SubfileData.h
  7. BIN
      lib/libLotroDat.dll.a
  8. BIN
      lib/libLotroDat_static.a
  9. 31 14
      src/DatFile.cpp
  10. 11 6
      src/Database.cpp
  11. 24 31
      src/Examples/extractor_example.cpp
  12. 22 22
      src/Examples/patcher_example.cpp

+ 12 - 1
CHANGELOG

@@ -5,4 +5,15 @@ Version 1.0.0
 Version 1.0.2
     * Fixed issue when some text files were patched but didn't appear in game ("<string error DID.." error due to incomplete dictionary update)
 ----------------------------------------------------------------------
-    
+Version 1.0.5
+    * Fixed issue when some files were replaced by new files, because of incorrect fragmentation journal, which cause "Unable to send request" error in game launcher
+----------------------------------------------------------------------
+Version 2.0.0
+    * Added support for maintaining both original and patched versions of subfiles in .dat file, and switching between these versions.
+----------------------------------------------------------------------
+Version 2.1.0
+    * Changed structure of project in order to use it as library. Added basic API functions for easier library management
+----------------------------------------------------------------------
+
+
+    

+ 20 - 17
CMakeLists.txt

@@ -22,33 +22,36 @@ include_directories(${CMAKE_SOURCE_DIR}/Third_party)
 SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_OUTPUT_DIR})
 SET(LIBRARY_OUTPUT_PATH ${CMAKE_OUTPUT_DIR})
 
+
+set(HEADER_FILES
+    ${CMAKE_SOURCE_DIR}/include/BinaryData.h
+    ${CMAKE_SOURCE_DIR}/include/CommonFunctions.h
+    ${CMAKE_SOURCE_DIR}/include/Database.h
+    ${CMAKE_SOURCE_DIR}/include/DatException.h
+    ${CMAKE_SOURCE_DIR}/include/DatFile.h
+    ${CMAKE_SOURCE_DIR}/include/LotroDat.h
+    ${CMAKE_SOURCE_DIR}/include/SubDirectory.h
+    ${CMAKE_SOURCE_DIR}/include/Subfile.h
+    ${CMAKE_SOURCE_DIR}/include/SubfileData.h
+)
+
 set(SOURCE_FILES
         ${CMAKE_SOURCE_DIR}/src/DatFile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/BinaryData.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Database.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/SubDirectory.cpp
 
-        ${CMAKE_SOURCE_DIR}/Third_party/SQLite/sqlite3.c
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/TextSubfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/JpgSubfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/DdsSubfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/OggSubfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/FontSubfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/WavSubfile.cpp
-
         ${CMAKE_SOURCE_DIR}/src/Subfiles/UnknownSubfile.cpp
-)
+
+        ${CMAKE_SOURCE_DIR}/Third_party/SQLite/sqlite3.c
+        )
 
 set(CompilerFlags
         CMAKE_CXX_FLAGS
@@ -68,13 +71,13 @@ foreach(CompilerFlag ${CompilerFlags})
 endforeach()
 
 # STATIC LIBRARY
-add_library(LotroDat_static STATIC ${SOURCE_FILES})
+add_library(LotroDat_static STATIC ${SOURCE_FILES} ${HEADER_FILES})
 # SHARED LIBRARY
-add_library(LotroDat SHARED ${SOURCE_FILES})
+add_library(LotroDat SHARED ${SOURCE_FILES} ${HEADER_FILES})
 # CONSOLE EXTRACTOR TOOL
-add_executable(LotRO_dat_extract_tester ${SOURCE_FILES} ${CMAKE_SOURCE_DIR}/src/Examples/extractor_example.cpp)
+add_executable(LotRO_dat_extract_tester ${SOURCE_FILES} ${HEADER_FILES} ${CMAKE_SOURCE_DIR}/src/Examples/extractor_example.cpp)
 # CONSOLE PATCHER TOOL
-add_executable(LotRO_dat_pat_tester ${SOURCE_FILES} ${CMAKE_SOURCE_DIR}/src/Examples/patcher_example.cpp)
+add_executable(LotRO_dat_pat_tester ${SOURCE_FILES} ${HEADER_FILES} ${CMAKE_SOURCE_DIR}/src/Examples/patcher_example.cpp)
 
 foreach(TARGET LotroDat_static LotroDat LotRO_dat_extract_tester LotRO_dat_pat_tester)
     if(MSVC)

+ 11 - 7
include/DatFile.h

@@ -72,7 +72,9 @@ namespace LOTRO_DAT {
     public:
         DatFile();
 
-        explicit DatFile(const char *filename, int dat_id);
+        void InitDatFile(const char *filename, int dat_id);
+
+        DAT_STATE DatFileState() const;
 
         virtual ~DatFile();
 
@@ -98,6 +100,8 @@ namespace LOTRO_DAT {
 
         void CommitChanges();
 
+        void CloseDatFile();
+
     private:
         // INIT SECTION
         void OpenDatFile(const char *dat_name);
@@ -108,10 +112,6 @@ namespace LOTRO_DAT {
 
         void MakeDictionary();
 
-        bool CheckIfUpdated();
-
-        void RepairPatches(Database *db);
-
         // READ-WRITE SECTION
 
         void ReadData(BinaryData &data, long long size, long long offset = 0, long long data_offset = 0);
@@ -131,16 +131,20 @@ namespace LOTRO_DAT {
         void UpdateFragmentationJournal(const std::vector<std::pair<long long, long long> > &journal);
 
         // LOCALE MANAGING SECTION
-
-    public:
+    private:
         void InitLocale(LOCALE locale, const char* dict_name);
 
         void SaveLocale(LOCALE locale, const char* filename);
 
+    public:
         void SetLocale(LOCALE locale);
 
         void CommitLocales();
 
+        bool CheckIfUpdatedByGame();
+
+        void RepairPatches(Database *db);
+
         LOCALE current_locale();
 
     private:

+ 2 - 2
include/Database.h

@@ -20,12 +20,12 @@ namespace LOTRO_DAT
     public:
         Database();
 
-        explicit Database(const std::string &filename);
-
         ~Database();
 
         void InitDatabase(const std::string &filename);
 
+        void CloseDatabase();
+
         void PushFile(const SubfileData &data);
 
         SubfileData GetNextFile();

+ 0 - 0
include/LotroDatPatcher.h → include/LotroDat.h


+ 4 - 0
include/SubfileData.h

@@ -24,6 +24,10 @@ namespace LOTRO_DAT {
             options = options_;
         }
 
+        bool Empty() const {
+            return binary_data.size() == 0 && text_data.length() == 0;
+        }
+
         bool operator == (const SubfileData &other) {
             return binary_data == other.binary_data && text_data == other.text_data;
         }

BIN
lib/libLotroDat.dll.a


BIN
lib/libLotroDat_static.a


+ 31 - 14
src/DatFile.cpp

@@ -18,7 +18,10 @@ extern "C++"
 namespace LOTRO_DAT {
     DatFile::DatFile() : dat_state_(CLOSED) {}
 
-    DatFile::DatFile(const char *filename, int dat_id) : dat_id_(dat_id) , dat_state_(CLOSED) {
+    void DatFile::InitDatFile(const char *filename, int dat_id) {
+        dat_id_ = dat_id;
+        dat_state_ = CLOSED;
+
         filename_ = std::string(filename);
         OpenDatFile(filename);
         ReadSuperBlock();
@@ -54,14 +57,12 @@ namespace LOTRO_DAT {
                                INIT_EXCEPTION);
     }
 
-    DatFile::~DatFile() {
-        CommitChanges();
-        CommitLocales();
+    DAT_STATE DatFile::DatFileState() const {
+        return dat_state_;
+    }
 
-        if (file_handler_ != nullptr)
-		    fclose(file_handler_);
-        delete file_handler_;
-        delete root_directory_;
+    DatFile::~DatFile() {
+        CloseDatFile();
     }
 
     /// Extracts file with file_id.
@@ -282,7 +283,6 @@ namespace LOTRO_DAT {
             }
         }
         CommitChanges();
-        CommitLocales();
         return true;
     }
 
@@ -567,10 +567,12 @@ namespace LOTRO_DAT {
         std::cout << "There are some updated files. Rewriting dictionary..." << std::endl << std::flush;
 
         auto journal = GetFragmentationJournal();
-        journal[0].second = file_size_;
-        BinaryData nulls(size_t(journal[0].first));
-        WriteData(nulls, nulls.size(), file_size_);
-        file_size_ += journal[0].first;
+        if (!patched_list.empty()) {
+            journal[0].second = file_size_;
+            BinaryData nulls(size_t(journal[0].first));
+            WriteData(nulls, nulls.size(), file_size_);
+            file_size_ += journal[0].first;
+        }
         UpdateFragmentationJournal(journal);
         std::cout << "Updated fragmentation journal..." << std::endl << std::flush;
 
@@ -580,9 +582,25 @@ namespace LOTRO_DAT {
         std::cout << "Updated subdirectories..." << std::endl << std::flush;
         std::cout << "Changed " << patched_list.size() << " files..." << std::endl << std::flush;
         patched_list.clear();
+        std::cout << "Updating locales..." << std::endl;
+        CommitLocales();
         dat_state_ = READY;
     }
 
+    void DatFile::CloseDatFile() {
+        if (dat_state_ == CLOSED)
+            return;
+
+        if (dat_state_ == UPDATED) {
+            CommitChanges();
+        }
+
+        if (file_handler_ != nullptr)
+            fclose(file_handler_);
+        delete file_handler_;
+        delete root_directory_;
+        dat_state_ = CLOSED;
+    }
     // LOCALE MANAGING SECTION
 
     void DatFile::InitLocale(LOCALE locale, const char* filename) {
@@ -654,7 +672,6 @@ namespace LOTRO_DAT {
         }
         current_locale_ = locale;
         CommitChanges();
-        CommitLocales();
     }
 
     void DatFile::SaveLocale(LOCALE locale, const char *filename) {

+ 11 - 6
src/Database.cpp

@@ -18,19 +18,24 @@ namespace LOTRO_DAT {
         db_ = nullptr;
     }
 
-    Database::Database(const std::string &filename) {
-        InitDatabase(filename.c_str());
-    }
-
-    Database::~Database() {
+    void Database::CloseDatabase() {
         if (db_ != nullptr) {
             ExecSql("COMMIT TRANSACTION");
             sqlite3_finalize(insert_request_);
-            sqlite3_close(db_);
+            sqlite3_finalize(fetch_one_request_);
+            sqlite3_finalize(get_rows_number_request_);
+            if (sqlite3_close_v2(db_) != SQLITE_OK)
+                fprintf(stderr, "ERROR: Bad Database::CloseDatabase() - Error when closing: %s\n", sqlite3_errmsg(db_));
+            db_ = nullptr;
         }
     }
 
+    Database::~Database() {
+        CloseDatabase();
+    }
+
     void Database::InitDatabase(const std::string &filename) {
+        CloseDatabase();
         if (sqlite3_open(filename.c_str(), &db_) != SQLITE_OK) {
             sqlite3_close(db_);
             throw DatException("Bad Database::InitDatabase() - sqlite3_open returned an error..."

+ 24 - 31
src/Examples/extractor_example.cpp

@@ -11,7 +11,7 @@
 #define mkdir(dir, mode) _mkdir(dir)
 #endif
 
-#include "../../include/LotroDatPatcher.h"
+#include "LotroDat.h"
 using namespace LOTRO_DAT;
 
 
@@ -36,7 +36,7 @@ const bool exportUnknownToDb = false;
 // There is no need to change anything else
 
 int main() {
-
+    std::cout << "Gi1dor's LotRO .dat extractor ver. 2.1.0" << std::endl;
     const clock_t begin_time = clock();
 
     mkdir("Extracted data", 744);
@@ -58,53 +58,44 @@ int main() {
     setvbuf (stderr, NULL, _IONBF, BUFSIZ);
     try {
         std::cout << "Starting search...\n" << std::flush;
-        DatFile a((path + filename).c_str(), 0);
+        DatFile a;
+        a.InitDatFile((path + filename).c_str(), 0);
         std::cout << "Total files found: " << a.files_number() << std::endl << std::flush;
         a.WriteUnorderedDictionary(output_dir);
         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 *out = new Database("out.db");
+        Database output_db;
+
         if (exportImagesToDb) {
-            //Database *images = out;//new Database(output_dir + std::string("Images.db"));
-            Database *images = new Database(output_dir + std::string("Images.db"));
-            std::cout << "Extracted " << a.ExtractAllFilesByType(JPG, images) << " .jpg files to Images.db" << std::endl << std::flush;
-            delete images;
+            output_db.InitDatabase(output_dir + std::string("Images.db"));
+            std::cout << "Extracted " << a.ExtractAllFilesByType(JPG, &output_db) << " .jpg files to Images.db" << std::endl << std::flush;
+            output_db.CloseDatabase();
         }
 
         if (exportSoundsToDb) {
-//            Database *sounds = out;//new Database(output_dir + std::string("Sounds.db"));
-            Database *sounds = new Database(output_dir + std::string("Sounds.db"));
-            std::cout << "Extracted " << a.ExtractAllFilesByType(WAV, sounds) << " .wav files to Sounds.db" << std::endl << std::flush;
-            std::cout << "Extracted " << a.ExtractAllFilesByType(OGG, sounds) << " .ogg files to Sounds.db" << std::endl << std::flush;
-            delete sounds;
+            output_db.InitDatabase(output_dir + std::string("Sounds.db"));
+            std::cout << "Extracted " << a.ExtractAllFilesByType(WAV, &output_db) << " .wav files to Sounds.db" << std::endl << std::flush;
+            std::cout << "Extracted " << a.ExtractAllFilesByType(OGG, &output_db) << " .ogg files to Sounds.db" << std::endl << std::flush;
+            output_db.CloseDatabase();
         }
 
         if (exportTextsToDb) {
-//            Database *texts = out;//new Database(output_dir + std::string("Texts.db"));
-            Database *texts = new Database(output_dir + std::string("Texts.db"));
-            std::cout << "Extracted " << a.ExtractAllFilesByType(TEXT, texts) << " text files to Texts.db" << std::endl << std::flush;
-            delete texts;
+            output_db.InitDatabase(output_dir + std::string("Texts.db"));
+            std::cout << "Extracted " << a.ExtractAllFilesByType(TEXT, &output_db) << " text files to Texts.db" << std::endl << std::flush;
+            output_db.CloseDatabase();
         }
 
         if (exportFontsToDb) {
-//            Database *fonts = out;//new Database(output_dir + std::string("Fonts.db"));
-            Database *fonts = new Database(output_dir + std::string("Fonts.db"));
-            std::cout << "Extracted " << a.ExtractAllFilesByType(FONT, fonts) << " font files to Fonts.db" << std::endl << std::flush;
-            delete fonts;
+            output_db.InitDatabase(output_dir + std::string("Fonts.db"));
+            std::cout << "Extracted " << a.ExtractAllFilesByType(FONT, &output_db) << " font files to Fonts.db" << std::endl << std::flush;
+            output_db.CloseDatabase();
         }
 
         if (exportTexturesToDb) {
-//            Database *textures = out;//new Database(output_dir + std::string("Textures.db"));
-            Database *textures = new Database(output_dir + std::string("Textures.db"));
-            std::cout << "Extracted " << a.ExtractAllFilesByType(DDS, textures) << " .dds files to Textures.db" << std::endl << std::flush;
-            delete textures;
-        }
-        delete out;
-
-        if (exportUnknownToDb) {
-            Database *unknown = new Database(output_dir + std::string("Unknown.db"));
-            std::cout << "Extracted " << a.ExtractAllFilesByType(UNKNOWN, unknown) << " unknown files to Unknown.db" << std::endl << std::flush;
+            output_db.InitDatabase(output_dir + std::string("Textures.db"));
+            std::cout << "Extracted " << a.ExtractAllFilesByType(DDS, &output_db) << " .dds files to Textures.db" << std::endl << std::flush;
+            output_db.CloseDatabase();
         }
 
         if (exportImagesToFiles) {
@@ -133,6 +124,8 @@ int main() {
             mkdir((output_dir + "unknown").c_str(), 744);
             std::cout << "Extracted " << a.ExtractAllFilesByType(FONT, output_dir + "unknown\\") << " unknown files to directory" << std::endl << std::flush;
         }
+
+        a.CloseDatFile();
     } catch (std::exception &e) {
         fprintf(stderr, "Caught %s exception.", e.what());
         printf("Some critical errors occured. Need to stop execution. See information in errors.log file\n");

+ 22 - 22
src/Examples/patcher_example.cpp

@@ -11,12 +11,12 @@
 #define mkdir(dir, mode) _mkdir(dir)
 #endif
 
-#include "../../include/LotroDatPatcher.h"
+#include "LotroDat.h"
 using namespace LOTRO_DAT;
 using namespace std;
 
 int main() {
-    std::cout << "Gi1dor's LotRO .dat patcher ver. 2.0.0" << std::endl;
+    std::cout << "Gi1dor's LotRO .dat patcher ver. 2.1.0" << std::endl;
     freopen("errors.log", "w", stderr);
 
    // setbuf(stdout, NULL);
@@ -27,7 +27,8 @@ int main() {
 
     try {
         std::cout << "Hello! I'm a basic shell version of .dat file patcher.\n";
-        DatFile *a = nullptr;
+        DatFile file;
+        
         ifstream in("dat_file_path.txt");
         if (!in.fail()) {
             std::string filename;
@@ -35,14 +36,13 @@ int main() {
             try {
                 std::cout << "Using .dat file from dat_file_path.txt...\n";
                 std::cout << "Opening file " << filename << std::endl;
-
-                a = new DatFile(filename.c_str(), 0);
+                file.InitDatFile(filename.c_str(), 0);
             } catch (DatException &e) {
                 std::cout << "Dat file path from dat_file_path.txt - " << filename << " may be incorrect (cannot open DatFile there)\n";
             }
         }
 
-        while (a == nullptr) {
+        while (file.DatFileState() == CLOSED) {
             std::cout << "Please, tell, where the .dat file is\n";
             std::cout << "Enter path to file (including filename): ";
             std::string filename;
@@ -51,22 +51,22 @@ int main() {
             std::cout << "Opening file " << filename << std::endl;
 
             try {
-                a = new DatFile(filename.c_str(), 0);
+                file.InitDatFile(filename.c_str(), 0);
             } catch (DatException &e) {
                 if (e.type() == NOFILE_EXCEPTION)
                     std::cout << "Cannot find file... Could you enter .dat filename once more?" << std::endl;
                 else
                     std::cout << "Some error caused while opening the file... "
                             "Could you enter .dat filename once more?" << std::endl;
-                delete a;
+                file.CloseDatFile();
             }
         }
 
         std::cout << "Great! File initialised successfully!\n";
-        std::cout << "Files number: " << a->files_number() << std::endl;
+        std::cout << "Files number: " << file.files_number() << std::endl;
 
         while (true) {
-            std::cout << "Please, choose, what should I do. I can patch data from database to .dat file (enter 1), "
+            std::cout << "Please, choose, what should I do. I can patch datfile from database to .dat file (enter 1), "
                     "change locale (enter 2), print current locale (enter 3) or exit (enter -1)\n";
             int cmd = 0;
             std::cout << "Enter number of command (1-4): ";
@@ -112,19 +112,19 @@ int main() {
                     size_t all = db.CountRows();
                     size_t now = 0;
 
-                    SubfileData data;
+                    SubfileData subfile;
 
                     try {
-                        data = db.GetNextFile();
+                        subfile = db.GetNextFile();
                     } catch (std::exception &e) {
                         fprintf(stderr, "Caught %s exception.\n", e.what());
                         fprintf(stderr, "DatFile::PatchAllDatabase() error! Caught exception while fetching "
                                 "file from database! Stopping...\n");
                         return false;
                     }
-                    while (data != SubfileData()) {
+                    while (!subfile.Empty()) {
                         try {
-                            a->PatchFile(data);
+                            file.PatchFile(subfile);
                         } catch (std::exception &e) {
                             fprintf(stderr, "Caught %s exception.\n", e.what());
                             fprintf(stderr, "DatFile::PatchAllDatabase() error! Caught exception while "
@@ -132,7 +132,7 @@ int main() {
                         }
 
                         try {
-                            data = db.GetNextFile();
+                            subfile = db.GetNextFile();
                         } catch (std::exception &e) {
                             fprintf(stderr, "Caught %s exception.\n", e.what());
                             fprintf(stderr,"DatFile::PatchAllDatabase() error! Caught exception while fetching "
@@ -144,8 +144,8 @@ int main() {
                             std::cout << now * 100 / all << "%\n";
                     }
 
-                    a->CommitChanges();
-                    a->CommitLocales();
+                    db.CloseDatabase();
+                    file.CommitChanges();
 
                     fprintf(stdout, "Spent %f seconds on patching! Thank you for your patience!\n",
                             float(clock() - begin_time) / CLOCKS_PER_SEC);
@@ -155,17 +155,17 @@ int main() {
                 }
             }
             if (cmd == 2) {
-                std::cout << "Old locale is " << (a->current_locale() == PATCHED ? "RU" : "Original") << endl;
+                std::cout << "Old locale is " << (file.current_locale() == PATCHED ? "RU" : "Original") << endl;
                 std::cout << "Changing locale..." << std::endl;
-                a->SetLocale(a->current_locale() == PATCHED ? ORIGINAL : PATCHED);
-                std::cout << "New locale is " << (a->current_locale() == PATCHED ? "RU" : "Original") << endl << endl;
+                file.SetLocale(file.current_locale() == PATCHED ? ORIGINAL : PATCHED);
+                std::cout << "New locale is " << (file.current_locale() == PATCHED ? "RU" : "Original") << endl << endl;
             }
 
             if (cmd == 3) {
-                std::cout << "Current locale is " << (a->current_locale() == PATCHED ? "RU" : "Original") << endl << endl;
+                std::cout << "Current locale is " << (file.current_locale() == PATCHED ? "RU" : "Original") << endl << endl;
             }
         }
-        delete a;
+        file.CloseDatFile();
     } catch (std::exception &e) {
         fprintf(stderr, "Caught %s exception.", e.what());
         printf("Caught %s exception.", e.what());