3 Commits 4850196c43 ... dd3ecd3a6d

Author SHA1 Message Date
  Ivan Arkhipov dd3ecd3a6d Fixed incorrect whitespace for arguments 3 years ago
  Ivan Arkhipov 725e4f5927 Added functions - checkers if patched by legacy v1 and if updated by game 3 years ago
  Ivan Arkhipov a9342748f5 Added database create if not exist flag & ability for patcher to create new files in .dat 3 years ago
7 changed files with 48 additions and 14 deletions
  1. 1 1
      include/database.h
  2. 6 2
      include/datfile.h
  3. 2 2
      src/database.cpp
  4. 32 2
      src/datfile.cpp
  5. 1 1
      src/subfiles/textsubfile.cpp
  6. 5 5
      src/utils/extractor.cpp
  7. 1 1
      src/utils/inserter.cpp

+ 1 - 1
include/database.h

@@ -18,7 +18,7 @@ class Database {
 
   ~Database();
 
-  bool InitDatabase(const std::string &filename);
+  bool InitDatabase(const std::string &filename, bool create_if_not_exists=false);
 
   bool CloseDatabase();
 

+ 6 - 2
include/datfile.h

@@ -29,15 +29,19 @@ class DatFile {
   	bool Init(const std::string& filename);
 	void LoadAllFilesInfo();
   	void Deinit();
-
+	
+	static bool checkIfPatchedByLegacyV1(const std::string& filename);
+	
 	bool Initialized() const;
 	const std::string& GetFilename() const;
+	
+	int GetDatFileMaxIteration() const;
 	SubfileInfo getSubfileInfo(int file_id) const;
 
 	size_t GetFilesNumInDatFile();
 
   	size_t PatchAllFilesFromDatabase(Database& db);
-	void PatchFile(SubfileData file_data, int version = -1, int iteration = -1);
+	void PatchFile(SubfileData file_data, int version = -1, int iteration = -1, bool create = false);
   	void PatchFile(int file_id, FILE_TYPE type, std::string path_to_file, int version = -1, int iteration = -1);
 
 	FILE_TYPE GetExistingFileType(int file_id);

+ 2 - 2
src/database.cpp

@@ -43,9 +43,9 @@ Database::~Database() {
   CloseDatabase();
 }
 
-bool Database::InitDatabase(const std::string &filename) {
+bool Database::InitDatabase(const std::string &filename, bool create_if_not_exists) {
   LOG(DEBUG) << "Initializing database " << filename;
-  if (access(filename.c_str(), 0 ) != 0) {
+  if (!create_if_not_exists && access(filename.c_str(), 0 ) != 0) {
     LOG(ERROR) << "Cannot init database: file with name " << filename << " does not exist!";
     return false;
   }

+ 32 - 2
src/datfile.cpp

@@ -76,6 +76,29 @@ void DatFile::Deinit() {
     }
 }
 
+bool DatFile::checkIfPatchedByLegacyV1(const std::string& filename) {
+    FILE* file_handler = fopen(filename.c_str(), "r+b");
+    if (file_handler == nullptr) {
+        return false;
+    }
+    BinaryData data(1024);
+    fread(data.data(), 1024, 1, file_handler);
+    fclose(file_handler);
+    return (data.ToNumber<4>(0x128) != 0 || data.ToNumber<4>(0x12C) != 0);
+}
+
+int DatFile::GetDatFileMaxIteration() const {
+    int subfiles_num = api_.GetNumSubfiles(file_handle_);
+    int max_iteration = -1;
+    for (int i = 0; i < subfiles_num; ++i) {
+        SubfileInfo file_info;
+        api_.GetSubfileSizes(file_handle_, &file_info.file_id, &file_info.size, &file_info.iteration, i, 1);
+        max_iteration = std::max(max_iteration, file_info.iteration);
+    }
+
+    return max_iteration;
+}
+
 bool DatFile::Initialized() const{
     return initialized_;
 }
@@ -120,17 +143,24 @@ size_t DatFile::PatchAllFilesFromDatabase(Database& db) {
     return patched_files_num;
 }
 
-void DatFile::PatchFile(SubfileData file_data, int version, int iteration) {
+void DatFile::PatchFile(SubfileData file_data, int version, int iteration, bool create) {
     if (!file_data.options["fid"]) {
         LOG(ERROR) << "Trying to patch file, but file id is not specified, skipping!";
         return;
     }
     int file_id = file_data.options["fid"].as<int>();
 
-    if (files_info_.count(file_id) == 0) {
+    if (files_info_.count(file_id) == 0 && !create) {
         LOG(ERROR) << "Trying to patch file, not existing in files_info. File id = " << file_id;
         return;
     }
+
+    if (create) {
+        BinaryData file = file_data.binary_data;
+        api_.PutSubfileData(file_handle_, file_id, file.data(), 0, file.size(), version, iteration);
+        return;
+    }
+
     const SubfileInfo& file_info = files_info_[file_id];
 
     int existing_file_version = 0; // will be evaluated with api_.GetSubfileData

+ 1 - 1
src/subfiles/textsubfile.cpp

@@ -258,7 +258,7 @@ BinaryData Subfile<TEXT>::BuildPieces(const BinaryData& data, const TextFragment
     size_t next = text_data.find(DNT, prev);
 
     while (next != std::string::npos) {
-        std::u16string piece = (next - prev == 0) ? u" " : text_data.substr(prev, next - prev);
+        std::u16string piece = (next - prev == 0) ? u"" : text_data.substr(prev, next - prev);
         text_pieces.push_back(piece);
         prev = next + DNT.length();
         next = text_data.find(DNT, prev);

+ 5 - 5
src/utils/extractor.cpp

@@ -135,14 +135,14 @@ int main() {
             Database output_db;
 
             if (exportImagesToDb) {
-                output_db.InitDatabase(output_dir + std::string("Images.db"));
+                output_db.InitDatabase(output_dir + std::string("Images.db"), true);
                 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"));
+                output_db.InitDatabase(output_dir + std::string("Sounds.db"), true);
                 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;
@@ -151,21 +151,21 @@ int main() {
             }
 
             if (exportTextsToDb) {
-                output_db.InitDatabase(output_dir + std::string("Texts.db"));
+                output_db.InitDatabase(output_dir + std::string("Texts.db"), true);
                 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"));
+                output_db.InitDatabase(output_dir + std::string("Fonts.db"), true);
                 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"));
+                output_db.InitDatabase(output_dir + std::string("Textures.db"), true);
                 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();

+ 1 - 1
src/utils/inserter.cpp

@@ -40,7 +40,7 @@ int main() {
     setvbuf (stderr, nullptr, _IONBF, BUFSIZ);
 
     std::cout << "Hello! I'm a basic shell version of .dat file patcher. I can open .dat file directly, "
-            "if you write path to it (with name of file) in file \"dat_file_path.txt\"\n";
+                 "if you write path to it (with name of file) in file \"dat_file_path.txt\"\n";
     
     DatFile file(0);