|
@@ -3,6 +3,8 @@
|
|
|
#include <DatFile.h>
|
|
|
#include <SubFile.h>
|
|
|
|
|
|
+#define DAT_LOCALE_DICT_VERSION 102
|
|
|
+
|
|
|
namespace LOTRO_DAT {
|
|
|
DatLocaleManager::DatLocaleManager(DatFile *datFilePtr) : dat(datFilePtr), current_locale_(ORIGINAL) {
|
|
|
}
|
|
@@ -22,6 +24,7 @@ namespace LOTRO_DAT {
|
|
|
* 4 bytes for dict size (in bytes)
|
|
|
* 4 bytes for locale version
|
|
|
* 4 bytes for .dat file size (with patches)
|
|
|
+ * 4 bytes for header hash
|
|
|
* 15 bytes for "Hi from Gi1dor"
|
|
|
* 4 bytes for LOCALE mark ("PATC" or "ORIG")
|
|
|
* 4 bytes for orig_dict.size()
|
|
@@ -62,13 +65,25 @@ namespace LOTRO_DAT {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- BinaryData locale_info(12);
|
|
|
- dat->GetIO().ReadData(locale_info, 12, locale_offset);
|
|
|
+ BinaryData locale_info(16);
|
|
|
+ dat->GetIO().ReadData(locale_info, 16, locale_offset);
|
|
|
|
|
|
long long dict_size = locale_info.ToNumber<4>(0);
|
|
|
long long dict_version = locale_info.ToNumber<4>(4);
|
|
|
+ long long patched_file_end = locale_info.ToNumber<4>(8);
|
|
|
+ long long dat_file_header_hash = locale_info.ToNumber<4>(12);
|
|
|
|
|
|
- if (dict_version != 101) {
|
|
|
+ if (dict_version != DAT_LOCALE_DICT_VERSION) {
|
|
|
+ dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 300);
|
|
|
+ if (CheckLocaleCorrect())
|
|
|
+ return DatOperationResult<>(SUCCESS);
|
|
|
+ else
|
|
|
+ return DatOperationResult<>(ERROR,
|
|
|
+ "Version of locales' dictionary is incorrect, through patched mark is standing. Dat file may be corrupted");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dat_file_header_hash != dat->GetIO().GetHeaderHash()) {
|
|
|
+ LOG(INFO) << "Header hash, written after last patch apply doesn't match current hash. Seems like dat-file was modified somewhere else, so removing all patch data";
|
|
|
dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 300);
|
|
|
if (CheckLocaleCorrect())
|
|
|
return DatOperationResult<>(SUCCESS);
|
|
@@ -78,7 +93,7 @@ namespace LOTRO_DAT {
|
|
|
}
|
|
|
|
|
|
BinaryData dicts_data = BinaryData((unsigned) dict_size);
|
|
|
- dat->GetIO().ReadData(dicts_data, dict_size - 12, locale_offset + 12);
|
|
|
+ dat->GetIO().ReadData(dicts_data, dict_size - 16, locale_offset + 16);
|
|
|
|
|
|
if (dicts_data.size() < 15) {
|
|
|
dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 300);
|
|
@@ -135,9 +150,9 @@ namespace LOTRO_DAT {
|
|
|
LOG(INFO) << "Finished initialising locales";
|
|
|
|
|
|
if (CheckLocaleCorrect()) {
|
|
|
- dat->GetFileSystem().patched_file_end = locale_info.ToNumber<4>(8);
|
|
|
+ dat->GetFileSystem().patched_file_end = patched_file_end;
|
|
|
LOG(INFO) << "Locales initialisation success. Dictionary size is " << dict_size << ". Version is "
|
|
|
- << dict_version << ". Localed .dat size = " << dat->GetFileSystem().patched_file_end;
|
|
|
+ << dict_version << ". Localed .dat size = " << patched_file_end;
|
|
|
return DatOperationResult<>(SUCCESS);
|
|
|
} else {
|
|
|
orig_dict_.clear();
|
|
@@ -309,8 +324,8 @@ namespace LOTRO_DAT {
|
|
|
fprintf(file, "Locale status = %lld\n", locale_status);
|
|
|
|
|
|
if (locale_offset != 0) {
|
|
|
- BinaryData locale_info(12);
|
|
|
- dat->GetIO().ReadData(locale_info, 12, locale_offset);
|
|
|
+ BinaryData locale_info(16);
|
|
|
+ dat->GetIO().ReadData(locale_info, 16, locale_offset);
|
|
|
|
|
|
long long dict_size = locale_info.ToNumber<4>(0);
|
|
|
long long dict_version = locale_info.ToNumber<4>(4);
|
|
@@ -346,7 +361,7 @@ namespace LOTRO_DAT {
|
|
|
return locale_status == 0;
|
|
|
|
|
|
BinaryData dicts_data = BinaryData(4);
|
|
|
- auto operation = dat->GetIO().ReadData(dicts_data, 4, locale_offset + 12 + 15);
|
|
|
+ auto operation = dat->GetIO().ReadData(dicts_data, 4, locale_offset + 16 + 15);
|
|
|
if (operation.result == ERROR)
|
|
|
return locale_status == 0;
|
|
|
|
|
@@ -360,7 +375,7 @@ namespace LOTRO_DAT {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (locale_status != 0 && locale_status != dat->GetIO().getHeaderHash()){
|
|
|
+ if (locale_status != 0 && locale_status != dat->GetIO().GetHeaderHash()){
|
|
|
LOG(ERROR) << "CHCKLOCALECORRECT: Locale hash doesn't match!";
|
|
|
return false;
|
|
|
}
|
|
@@ -417,6 +432,7 @@ namespace LOTRO_DAT {
|
|
|
* 4 bytes for dict size (in bytes)
|
|
|
* 4 bytes for locale version
|
|
|
* 4 bytes for .dat file size (with patches)
|
|
|
+ * 4 bytes for dat file header hash
|
|
|
* 15 bytes for "Hi from Gi1dor"
|
|
|
* 4 bytes for LOCALE
|
|
|
* 4 bytes for orig_dict.size()
|
|
@@ -444,13 +460,13 @@ namespace LOTRO_DAT {
|
|
|
return DatOperationResult<>(SUCCESS);
|
|
|
}
|
|
|
|
|
|
- BinaryData binary_data = BinaryData(4 + 4 + 4 + 14 + 15 + 4
|
|
|
+ BinaryData binary_data = BinaryData(4 + 4 + 4 + 4 + 14 + 15 + 4
|
|
|
+ 4 + (32 + 4) * orig_dict_.size()
|
|
|
+ 4 + (32 + 4) * patch_dict_.size()
|
|
|
+ 4 + 4 * inactive_categories.size());
|
|
|
|
|
|
- // First 12 bytes will be filled just before writing data to file
|
|
|
- size_t current_size = 12;
|
|
|
+ // First 16 bytes will be filled just before writing data to file
|
|
|
+ size_t current_size = 16;
|
|
|
|
|
|
binary_data.Append(BinaryData("Hi from Gi1dor!", 15), current_size);
|
|
|
current_size += 15;
|
|
@@ -493,14 +509,14 @@ namespace LOTRO_DAT {
|
|
|
long long dict_size = dicts_data.ToNumber<4>(0);
|
|
|
|
|
|
if (binary_data.size() > dict_size || dict_offset == 0) {
|
|
|
- long long new_dict_offset = dat->GetFileSystem().patched_file_end + 12;
|
|
|
+ long long new_dict_offset = dat->GetFileSystem().patched_file_end + 16;
|
|
|
|
|
|
- // Updating first 12 bytes
|
|
|
+ // Updating first 16 bytes
|
|
|
binary_data.Append(BinaryData::FromNumber<4>(std::max(binary_data.size() + 4, 20u * 1024u * 1024u)), 0);
|
|
|
- binary_data.Append(BinaryData::FromNumber<4>(101), 4);
|
|
|
+ binary_data.Append(BinaryData::FromNumber<4>(DAT_LOCALE_DICT_VERSION), 4);
|
|
|
binary_data.Append(
|
|
|
BinaryData::FromNumber<4>(dat->GetFileSystem().patched_file_end + binary_data.size() + 20 * 1024 * 1024), 8);
|
|
|
-
|
|
|
+ binary_data.Append(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 12);
|
|
|
auto operation = dat->GetIO().WriteData(binary_data, binary_data.size(), new_dict_offset);
|
|
|
if (operation.result != SUCCESS) {
|
|
|
return DatOperationResult<>(ERROR, "LOCALEDEINIT: Cannot write locales");
|
|
@@ -509,7 +525,7 @@ namespace LOTRO_DAT {
|
|
|
dat->GetIO().WriteData(BinaryData::FromNumber<4>(new_dict_offset), 4, 300);
|
|
|
|
|
|
if (current_locale_ == PATCHED) {
|
|
|
- dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().getHeaderHash()), 4, 296);
|
|
|
+ dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 4, 296);
|
|
|
} else {
|
|
|
dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 296);
|
|
|
}
|
|
@@ -522,11 +538,12 @@ namespace LOTRO_DAT {
|
|
|
dat->GetFileSystem().patched_file_end += nulls.size();
|
|
|
} else {
|
|
|
binary_data.Append(BinaryData::FromNumber<4>(std::max(binary_data.size() + 4, 20u * 1024u * 1024u)), 0);
|
|
|
- binary_data.Append(BinaryData::FromNumber<4>(101), 4);
|
|
|
+ binary_data.Append(BinaryData::FromNumber<4>(DAT_LOCALE_DICT_VERSION), 4);
|
|
|
binary_data.Append(BinaryData::FromNumber<4>(dat->GetFileSystem().patched_file_end), 8);
|
|
|
+ binary_data.Append(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 12);
|
|
|
|
|
|
if (current_locale_ == PATCHED) {
|
|
|
- dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().getHeaderHash()), 4, 296);
|
|
|
+ dat->GetIO().WriteData(BinaryData::FromNumber<4>(dat->GetIO().GetHeaderHash()), 4, 296);
|
|
|
} else {
|
|
|
dat->GetIO().WriteData(BinaryData::FromNumber<4>(0), 4, 296);
|
|
|
}
|
|
@@ -538,7 +555,6 @@ namespace LOTRO_DAT {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
LOG(INFO) << "Locales committed successfully";
|
|
|
return DatOperationResult<>(SUCCESS);
|
|
|
}
|