Преглед изворни кода

Major bug fixes, files with many pieces are now correctly extracted (needs testing)

Gi1dor (Ivan Arkhipov) пре 7 година
родитељ
комит
84736576d5
4 измењених фајлова са 48 додато и 38 уклоњено
  1. 4 4
      SubDirectory.cpp
  2. 32 22
      Subfile.cpp
  3. 9 9
      Subfile.h
  4. 3 3
      test.cpp

+ 4 - 4
SubDirectory.cpp

@@ -72,14 +72,14 @@ void LOTRO_DAT::SubDirectory::MakeSubFiles() {
         subfiles_.emplace_back(
             Subfile(
                     dat_,
-                    data.ToNumber<4>(i), // unknown0
+                    data.ToNumber<4>(i), // fragments_count
                     data.ToNumber<4>(i + 4), // unknown1
                     data.ToNumber<4>(i + 8), // file_id
                     data.ToNumber<4>(i + 12), // file_offset
-                    data.ToNumber<4>(i + 16), // size1
+                    data.ToNumber<4>(i + 16), // block_size
                     data.ToNumber<4>(i + 20), // timestamp
                     data.ToNumber<4>(i + 24), // version
-                    data.ToNumber<4>(i + 28) // size2
+                    data.ToNumber<4>(i + 28) // block_size
             )
         );
     }
@@ -90,7 +90,7 @@ void LOTRO_DAT::SubDirectory::MakeDictionary(std::unordered_map<long long, Subfi
         //if (dict.count(i.file_id()) != 0 && dict[i.file_id()]->file_offset() != i.file_offset())
         //    throw DatException("Bad SubDirectory::MakeDictionary() - found 2 files with different offset!!!", SUBFILE_EXCEPTION);
         if (dict.count(i.file_id()) == 0 || dict[i.file_id()]->timestamp() < i.timestamp()
-            || (dict[i.file_id()]->timestamp() == i.timestamp() && dict[i.file_id()]->size1() < i.size1()))
+            || (dict[i.file_id()]->timestamp() == i.timestamp() && dict[i.file_id()]->block_size() < i.block_size()))
 			dict[i.file_id()] = &i;
     }
     for (SubDirectory &i : subdirs_)

+ 32 - 22
Subfile.cpp

@@ -18,22 +18,22 @@ LOTRO_DAT::Subfile::Subfile() {
     compressed_ = false;
 }
 
-LOTRO_DAT::Subfile::Subfile(DatFile *dat, long long unknown0, long long unknown1, long long file_id, long long file_offset, long long size1,
-                            long long timestamp, long long version, long long size2) :
-        dat_(dat), unknown0_(unknown0), unknown1_(unknown1), file_id_(file_id), file_offset_(file_offset),
-        size1_(size1), timestamp_(timestamp), version_(version), size2_(size2) {
+LOTRO_DAT::Subfile::Subfile(DatFile *dat, long long fragments_count, long long unknown1, long long file_id, long long file_offset,
+                            long long file_size, long long timestamp, long long version, long long block_size) :
+        dat_(dat), fragments_count_(fragments_count), unknown1_(unknown1), file_id_(file_id), file_offset_(file_offset),
+        file_size_(file_size), timestamp_(timestamp), version_(version), block_size_(block_size) {
 
-    if (size1_ > MAXSIZE)
+    if (file_size_ > MAXSIZE)
 		throw DatException("Bad Subfile::Subfile() - File size is too much... Maybe it's incorrect..?", SUBFILE_EXCEPTION);
 	ext_ = GetExtension();
 
     BinaryData header(20);
-    dat_->ReadData(header, 10, file_offset_);
+    dat_->ReadData(header, 10, file_offset_ + 8);
     compressed_ = header.CheckCompression();
 }
 
-long long LOTRO_DAT::Subfile::unknown0() const {
-    return unknown0_;
+long long LOTRO_DAT::Subfile::fragments_count() const {
+    return fragments_count_;
 }
 
 long long LOTRO_DAT::Subfile::unknown1() const {
@@ -48,8 +48,8 @@ long long LOTRO_DAT::Subfile::file_offset() const {
     return file_offset_;
 }
 
-long long LOTRO_DAT::Subfile::size1() const {
-    return size1_;
+long long LOTRO_DAT::Subfile::file_size() const {
+    return file_size_;
 }
 
 long long LOTRO_DAT::Subfile::timestamp() const {
@@ -60,8 +60,8 @@ long long LOTRO_DAT::Subfile::version() const {
     return version_;
 }
 
-long long LOTRO_DAT::Subfile::size2() const {
-    return size2_;
+long long LOTRO_DAT::Subfile::block_size() const {
+    return block_size_;
 }
 
 LOTRO_DAT::EXTENSION LOTRO_DAT::Subfile::GetExtension() const {
@@ -177,22 +177,32 @@ bool LOTRO_DAT::Subfile::ExportFileAsTXT(const char *filename, Database *db) con
     throw DatException("ExportAsTXT function is not implemented yet", EXPORT_EXCEPTION);
 }
 
-LOTRO_DAT::BinaryData LOTRO_DAT::Subfile::GetFileData() const {
-    BinaryData data((unsigned)size1());
-    if (size2() >= size1() + 8) {
-        dat_->ReadData(data, size1(), file_offset() + 8);
+LOTRO_DAT::BinaryData LOTRO_DAT::Subfile::GetFileData(long long offset) const {
+    BinaryData data((unsigned)(file_size()));
+    if (block_size() >= file_size() + 8) {
+        dat_->ReadData(data, file_size(), file_offset() + offset);
         return data;
     }
 
-    long long first_block_size = size2() - 8 - 4;
+    BinaryData fragments_count(4);
+    dat_->ReadData(fragments_count, 4, file_offset());
+    long long fragments_number = fragments_count.ToNumber<4>(0);
+    
+    long long current_block_size = block_size() - offset - 8 * fragments_number;
 
-    dat_->ReadData(data, first_block_size, file_offset() + 8);
+    dat_->ReadData(data, current_block_size , file_offset() + offset);
 
-    BinaryData newFragmentOffset(4);
-    dat_->ReadData(newFragmentOffset, 4, file_offset() + size2() - 4);
-    long long part_offset = newFragmentOffset.ToNumber<4>(0);
+    BinaryData FragmentsDictionary(8 * unsigned(fragments_number));
+    dat_->ReadData(FragmentsDictionary, 8 * unsigned(fragments_number), file_offset() + block_size() - 8 * fragments_number);
+
+
+    for (long long i = 0; i < fragments_number; i++) {
+        long long fragment_size = FragmentsDictionary.ToNumber<4>(8 * i);
+        long long fragment_offset = FragmentsDictionary.ToNumber<4>(8 * i + 4);
+        dat_->ReadData(data, std::min(fragment_size, file_size() - current_block_size), fragment_offset, current_block_size );
+        current_block_size += fragment_size;
+    }
 
-    dat_->ReadData(data, size1() - first_block_size, part_offset, first_block_size);
     return data;
 }
 

+ 9 - 9
Subfile.h

@@ -24,8 +24,8 @@ namespace LOTRO_DAT
     public:
         Subfile();
 
-        Subfile(DatFile *dat, long long unknown0, long long unknown1, long long file_id, long long file_offset, long long size1,
-                long long timestamp, long long version, long long size2);
+        Subfile(DatFile *dat, long long fragments_count, long long unknown1, long long file_id, long long file_offset, long long file_size,
+                long long timestamp, long long version, long long block_size);
 
         bool ExportFile(const char* filename, Database *db = nullptr) const;
 		
@@ -33,7 +33,7 @@ namespace LOTRO_DAT
 																						 // as TXT file consisits of more than 1 file
 		bool PatchFile();
 
-        long long unknown0() const;
+        long long fragments_count() const;
 
         long long unknown1() const;
 
@@ -41,25 +41,25 @@ namespace LOTRO_DAT
 
         long long file_offset() const;
 
-        long long size1() const;
+        long long file_size() const;
 
         long long timestamp() const;
 
         long long version() const;
 
-        long long size2() const;
+        long long block_size() const;
 
 		EXTENSION ext() const;
     
 	private:
-        long long unknown0_;
+        long long fragments_count_;
         long long unknown1_;
         long long file_id_;
         long long file_offset_;
-        long long size1_;
+        long long file_size_;
         long long timestamp_;
         long long version_;
-        long long size2_;
+        long long block_size_;
 
         bool compressed_;
 
@@ -69,7 +69,7 @@ namespace LOTRO_DAT
 		EXTENSION GetExtension() const;
 		std::string ExtensionToString(LOTRO_DAT::EXTENSION ext) const;
 
-		BinaryData GetFileData() const;
+		BinaryData GetFileData(long long offset = 8) const;
 
 		const BinaryData PrepareAsJPG() const;
 		const BinaryData PrepareAsDDS() const;

+ 3 - 3
test.cpp

@@ -15,7 +15,7 @@ int main() {
 
 	// Change these 2 variables to your path and name of .dat file
     std::string path = "E:\\SteamLibrary\\steamapps\\common\\Lord of the Rings Online\\";
-    std::string filename = "client_local_English.dat";
+    std::string filename = "client_highres.dat";
 
     bool exportTextsToFiles = false; // Not implemented yet - do not turn to true;
     bool exportImagesToFiles = true;
@@ -25,7 +25,7 @@ int main() {
     bool exportUnknownToFiles = false; // Not implemented yet - do not turn to true;
 
     bool exportTextsToDb = false; // Not implemented yet - do not turn to true;
-    bool exportImagesToDb = true;
+    bool exportImagesToDb = false;
     bool exportFontsToDb = false; // Not implemented yet - do not turn to true;
     bool exportSoundsToDb = false;
     bool exportTexturesToDb = false;
@@ -93,7 +93,7 @@ int main() {
 		if (ext == OGG) extension = "ogg";
 		if (ext == FONT) extension = "font";
 		fprintf(f, "%lld %lld %lld %lld %s\n", i.second->file_id(), i.second->file_offset()
-                , i.second->size1(), i.second->size2(), extension.c_str());
+                , i.second->file_size(), i.second->block_size(), extension.c_str());
 	}
 	fclose(f);