Jelajahi Sumber

Patching dat correctness checker

Ivan Arkhipov 5 tahun lalu
induk
melakukan
72580396ab
2 mengubah file dengan 47 tambahan dan 15 penghapusan
  1. 8 5
      src/DatFile.cpp
  2. 39 10
      src/DatSubsystems/DatLocaleManager.cpp

+ 8 - 5
src/DatFile.cpp

@@ -12,7 +12,7 @@
 #define ftell _ftelli64
 #endif
 
-#define VERSION "7.0.0"
+#define VERSION "7.1.0"
 
 INITIALIZE_EASYLOGGINGPP
 
@@ -99,26 +99,29 @@ namespace LOTRO_DAT {
         if (initialized_ && io_->GetFilename().result == SUCCESS && io_->GetFilename().value == filename)
             return DatOperationResult<>();
 
+        initialized_ = true;
 
         auto operation = io_->Init(filename);
         if (operation.result != SUCCESS) {
+            Deinitialize();
             status_->ClearAll();
-            return DatOperationResult<>(ERROR, "DATINIT: Error, cannot initialize dat");
+            return DatOperationResult<>(ERROR, "DATINIT: Error, cannot initialize dat due to internal IO error");
         }
 
         operation = fileSystem_->Init();
         if (operation.result != SUCCESS) {
+            Deinitialize();
             status_->ClearAll();
-            return DatOperationResult<>(ERROR, "DATINIT: Error, cannot initialize dat");
+            return DatOperationResult<>(ERROR, "DATINIT: Error, cannot initialize dat due to filesystem parsing error");
         }
 
         operation = localeManager_->Init();
         if (operation.result != SUCCESS) {
+            Deinitialize();
             status_->ClearAll();
-            return DatOperationResult<>(ERROR, "DATINIT: Error, cannot initialize dat");
+            return DatOperationResult<>(ERROR, "DATINIT: Error, cannot initialize dat due to locale manager initialisation error");
         }
 
-        initialized_ = true;
         status_->ClearAll();
         return DatOperationResult<>();
     }

+ 39 - 10
src/DatSubsystems/DatLocaleManager.cpp

@@ -121,8 +121,14 @@ namespace LOTRO_DAT {
             dat->GetIO().file_size = locale_info.ToNumber<4>(8);
             LOG(INFO) << "Locales initialisation success. Dictionary size is " << dict_size << ". Version is " << dict_version << ". Localed .dat size = " << dat->GetIO().file_size;
             return DatOperationResult<>(SUCCESS);
-        } else
-            return DatOperationResult<>(ERROR, "Locale dict is incorrect, through patched mark is standing. Dat file may be corrupted");
+        } else {
+            orig_dict_.clear();
+            patch_dict_.clear();
+            inactive_categories.clear();
+            current_locale_ = ORIGINAL;
+            return DatOperationResult<>(ERROR,
+                                        "Locale dict is incorrect, through patched mark is standing. Dat file may be corrupted");
+        }
     }
 
 
@@ -217,7 +223,10 @@ namespace LOTRO_DAT {
      * 4 * inactive_categories.size()   bytes for inactive_categories data
      * ========================================
      * Помимо этого:
-     * 0x128-0x12C - Флаг, является ли активной альтернативная версия (PATCHED)
+     * 0x128-0x12C - 0, если выбрана локаль ORIGINAL и обновление клиентом игры не испортит .dat file
+     *               значение переменной-размера .dat файла (оффсет 0x148), в противном случае.
+     *               Отличие значения в 0x128 от 0 и значения в 0x148 => файл ресурсов мог быть повреждён
+     *
      * 0x12C-0x130 - Офсет начала словаря локализации
      */
 
@@ -292,7 +301,14 @@ namespace LOTRO_DAT {
                 return DatOperationResult<>(ERROR, "LOCALEDEINIT: Cannot write locales");
 
             dat->GetIO().WriteData(BinaryData::FromNumber<4>(new_dict_offset), 4, 300);
-            dat->GetIO().WriteData(BinaryData::FromNumber<4>(current_locale_), 4, 296);
+
+            if (current_locale_ == PATCHED) {
+                BinaryData file_size_flag(4);
+                dat->GetIO().ReadData(file_size_flag, 4, 0x148);
+                dat->GetIO().WriteData(file_size_flag, 4, 296);
+            } else {
+                dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 296);
+            }
 
             dat->GetIO().file_size += binary_data.size();
 
@@ -312,7 +328,7 @@ namespace LOTRO_DAT {
                 return DatOperationResult<>(ERROR, "LOCALEDEINIT: Cannot write locales. ERRMSG: " + operation.msg);
         }
 
-        LOG(INFO) << "Locales commited successfully";
+        LOG(INFO) << "Locales committed successfully";
 
 
         return DatOperationResult<>(SUCCESS);
@@ -405,7 +421,8 @@ namespace LOTRO_DAT {
      * \date 06.07.2018
      * Осуществляет проверку корректности dat файла с позиции локалей
      * Файл считается некорректным, если активной является альтернативная локаль, причём нет возможности вернуть оригинальную (блок локалей неверный/повреждён)
-     * Байты 0x128-0x12C показывают активную локаль на момент закрытия dat файла.
+     * Байты 0x128-0x12C равны 0, если на момент пользования патчером активна оригинальная локаль, и DatIO::file_size, если нет
+     * Отличие значения в 0x128 от 0 и значения в 0x148 => файл ресурсов мог быть повреждён
      */
 
     bool DatLocaleManager::CheckLocaleCorrect() {
@@ -413,9 +430,6 @@ namespace LOTRO_DAT {
         dat->GetIO().ReadData(locale_info, 4, 296);
         long long locale_status = locale_info.ToNumber<4>(0);
 
-        if (locale_status == ORIGINAL)
-            return true;
-
         BinaryData locale_offset_data(4);
         dat->GetIO().ReadData(locale_offset_data, 4, 300);
         long long locale_offset = locale_offset_data.ToNumber<4>(0);
@@ -432,7 +446,22 @@ namespace LOTRO_DAT {
         std::string locale((char *)(locale_data.data()));
 
         LOCALE dat_locale = (locale == "PATC" ? PATCHED : ORIGINAL);
-        return locale_status == dat_locale;
+
+        if ((locale_status == 0 && dat_locale == PATCHED) || (locale_status != 0 && dat_locale == ORIGINAL)) {
+            LOG(ERROR) << "CHCKLOCALECORRECT: Locale status and current_locale doesn't match!";
+            return false;
+        }
+
+        BinaryData original_filesize_variable(4);
+        dat->GetIO().ReadData(original_filesize_variable, 4, 0x148);
+        long long original_filesize = original_filesize_variable.ToNumber<4>(0);
+
+        if (locale_status != original_filesize) {
+            LOG(ERROR) << "CHCKLOCALECORRECT: locale & file size values doesn't match!";
+            return false;
+        }
+
+        return true;
     }