Esempio n. 1
0
 public void SaveFileTo(int fileDataId, string fullName, string extractPath) => SaveFileTo(FileDataHash.ComputeHash(fileDataId), extractPath, fullName);
Esempio n. 2
0
        public WowRootHandler(BinaryReader stream, BackgroundWorker worker)
        {
            worker?.ReportProgress(0, "Loading root...");

            int numFilesRead = 0;

            var magic                = stream.ReadInt32();
            var numFilesTotal        = stream.ReadInt32();
            var numFilesWithNameHash = stream.ReadInt32();

            while (stream.BaseStream.Position < stream.BaseStream.Length)
            {
                int count = stream.ReadInt32();

                numFilesRead += count;

                ContentFlags contentFlags = (ContentFlags)stream.ReadUInt32();
                LocaleFlags  localeFlags  = (LocaleFlags)stream.ReadUInt32();

                if (localeFlags == LocaleFlags.None)
                {
                    throw new Exception("block.LocaleFlags == LocaleFlags.None");
                }

                if (contentFlags != ContentFlags.None && (contentFlags & (ContentFlags.F00000001 | ContentFlags.Windows | ContentFlags.MacOS | ContentFlags.Alternate | ContentFlags.F00020000 | ContentFlags.F00080000 | ContentFlags.F00100000 | ContentFlags.F00400000 | ContentFlags.F02000000 | ContentFlags.NotCompressed | ContentFlags.NoNameHash | ContentFlags.F20000000)) == 0)
                {
                    throw new Exception("block.ContentFlags != ContentFlags.None");
                }

                RootEntry[] entries     = new RootEntry[count];
                int[]       filedataIds = new int[count];

                int fileDataIndex = 0;

                for (var i = 0; i < count; ++i)
                {
                    entries[i].LocaleFlags  = localeFlags;
                    entries[i].ContentFlags = contentFlags;

                    filedataIds[i] = fileDataIndex + stream.ReadInt32();
                    fileDataIndex  = filedataIds[i] + 1;
                }

                //Debug.Log("Block: {0} {1} (size {2})", block.ContentFlags, block.LocaleFlags, count);

                ulong[] nameHashes = null;

                for (var i = 0; i < count; ++i)
                {
                    entries[i].MD5 = stream.Read <MD5Hash>();
                }

                if (numFilesRead > numFilesTotal - numFilesWithNameHash)
                {
                    nameHashes = new ulong[count];

                    for (var i = 0; i < count; ++i)
                    {
                        nameHashes[i] = stream.ReadUInt64();
                    }
                }

                //for (var i = 0; i < count; ++i)
                Parallel.For(0, count, i =>
                {
                    var fileDataId = filedataIds[i];
                    var hash       = 0UL;

                    if (nameHashes == null)
                    {
                        hash = FileDataHash.ComputeHash(fileDataId);
                    }
                    else
                    {
                        hash = nameHashes[i];
                    }

                    RootData.Add(fileDataId, entries[i]);
                    FileDataStore.TryAdd(fileDataId, hash);
                    FileDataStoreReverse.TryAdd(hash, fileDataId);

                    // if (nameHashes != null)
                    // {
                    //     // generate our custom hash as well so we can still find file without calling GetHashByFileDataId in some weird cases
                    //     var fileDataHash = FileDataHash.ComputeHash(fileDataId);
                    //     FileDataStoreReverse.TryAdd(fileDataHash, fileDataId);
                    // }
                });

                worker?.ReportProgress((int)(stream.BaseStream.Position / (float)stream.BaseStream.Length * 100), "Loading root...");
            }
        }
Esempio n. 3
0
        public WowRootHandler(BinaryReader stream, BackgroundWorkerEx worker)
        {
            worker?.ReportProgress(0, "Loading \"root\"...");

            int magic = stream.ReadInt32();

            int numFilesTotal = 0, numFilesWithNameHash = 0, numFilesRead = 0;

            const int TSFMMagic = 0x4D465354;

            if (magic == TSFMMagic)
            {
                numFilesTotal        = stream.ReadInt32();
                numFilesWithNameHash = stream.ReadInt32();
            }
            else
            {
                stream.BaseStream.Position -= 4;
            }

            while (stream.BaseStream.Position < stream.BaseStream.Length)
            {
                int count = stream.ReadInt32();

                numFilesRead += count;

                ContentFlags contentFlags = (ContentFlags)stream.ReadUInt32();
                LocaleFlags  localeFlags  = (LocaleFlags)stream.ReadUInt32();

                if (localeFlags == LocaleFlags.None)
                {
                    throw new InvalidDataException("block.LocaleFlags == LocaleFlags.None");
                }

                if (contentFlags != ContentFlags.None && (contentFlags & (ContentFlags.F00000001 | ContentFlags.Windows | ContentFlags.MacOS | ContentFlags.Alternate | ContentFlags.F00020000 | ContentFlags.F00080000 | ContentFlags.F00100000 | ContentFlags.F00200000 | ContentFlags.F00400000 | ContentFlags.F02000000 | ContentFlags.NotCompressed | ContentFlags.NoNameHash | ContentFlags.F20000000)) == 0)
                {
                    throw new InvalidDataException("block.ContentFlags != ContentFlags.None");
                }

                RootEntry[] entries     = new RootEntry[count];
                int[]       filedataIds = new int[count];

                int fileDataIndex = 0;

                for (var i = 0; i < count; ++i)
                {
                    entries[i].LocaleFlags  = localeFlags;
                    entries[i].ContentFlags = contentFlags;

                    filedataIds[i] = fileDataIndex + stream.ReadInt32();
                    fileDataIndex  = filedataIds[i] + 1;
                }

                //Console.WriteLine("Block: {0} {1} (size {2})", block.ContentFlags, block.LocaleFlags, count);

                ulong[] nameHashes = null;

                if (magic == TSFMMagic)
                {
                    for (var i = 0; i < count; ++i)
                    {
                        entries[i].cKey = stream.Read <MD5Hash>();
                    }

                    if ((contentFlags & ContentFlags.NoNameHash) == 0)
                    {
                        nameHashes = new ulong[count];

                        for (var i = 0; i < count; ++i)
                        {
                            nameHashes[i] = stream.ReadUInt64();
                        }
                    }
                }
                else
                {
                    nameHashes = new ulong[count];

                    for (var i = 0; i < count; ++i)
                    {
                        entries[i].cKey = stream.Read <MD5Hash>();
                        nameHashes[i]   = stream.ReadUInt64();
                    }
                }

                for (var i = 0; i < count; ++i)
                {
                    int fileDataId = filedataIds[i];

                    //Logger.WriteLine("filedataid {0}", fileDataId);

                    ulong hash;

                    if (nameHashes == null)
                    {
                        hash = FileDataHash.ComputeHash(fileDataId);
                    }
                    else
                    {
                        hash = nameHashes[i];
                    }

                    RootData.Add(fileDataId, entries[i]);

                    //Console.WriteLine("File: {0:X8} {1:X16} {2}", entries[i].FileDataId, hash, entries[i].MD5.ToHexString());

                    if (FileDataStore.TryGetValue(fileDataId, out ulong hash2))
                    {
                        if (hash2 == hash)
                        {
                            // duplicate, skipping
                        }
                        else
                        {
                            Logger.WriteLine("ERROR: got miltiple hashes for filedataid {0}", fileDataId);
                        }
                        continue;
                    }

                    FileDataStore.Add(fileDataId, hash);
                    FileDataStoreReverse.Add(hash, fileDataId);

                    if (nameHashes != null)
                    {
                        // generate our custom hash as well so we can still find file without calling GetHashByFileDataId in some weird cases
                        ulong fileDataHash = FileDataHash.ComputeHash(fileDataId);
                        FileDataStoreReverse.Add(fileDataHash, fileDataId);
                    }
                }

                worker?.ReportProgress((int)(stream.BaseStream.Position / (float)stream.BaseStream.Length * 100));
            }
        }
        public WowRootHandler(BinaryReader stream)
        {
            int numFilesRead = 0;

            var magic                = stream.ReadInt32();
            var numFilesTotal        = stream.ReadInt32();
            var numFilesWithNameHash = stream.ReadInt32();

            while (stream.BaseStream.Position < stream.BaseStream.Length)
            {
                int count = stream.ReadInt32();

                numFilesRead += count;

                ContentFlags contentFlags = (ContentFlags)stream.ReadUInt32();
                LocaleFlags  localeFlags  = (LocaleFlags)stream.ReadUInt32();

                if (localeFlags == LocaleFlags.None)
                {
                    throw new Exception("block.LocaleFlags == LocaleFlags.None");
                }

                if (contentFlags != ContentFlags.None && (contentFlags & (ContentFlags.F00000001 | ContentFlags.Windows | ContentFlags.MacOS | ContentFlags.Alternate | ContentFlags.F00020000 | ContentFlags.F00080000 | ContentFlags.F00100000 | ContentFlags.F00400000 | ContentFlags.F02000000 | ContentFlags.NotCompressed | ContentFlags.NoNameHash | ContentFlags.F20000000)) == 0)
                {
                    throw new Exception("block.ContentFlags != ContentFlags.None");
                }

                RootEntry[] entries     = new RootEntry[count];
                int[]       filedataIds = new int[count];

                int fileDataIndex = 0;

                for (var i = 0; i < count; ++i)
                {
                    entries[i].LocaleFlags  = localeFlags;
                    entries[i].ContentFlags = contentFlags;

                    filedataIds[i] = fileDataIndex + stream.ReadInt32();
                    fileDataIndex  = filedataIds[i] + 1;
                }

                //Console.WriteLine("Block: {0} {1} (size {2})", block.ContentFlags, block.LocaleFlags, count);

                ulong[] nameHashes = null;

                for (var i = 0; i < count; ++i)
                {
                    entries[i].MD5 = stream.Read <MD5Hash>();
                }

                if (numFilesRead > numFilesTotal - numFilesWithNameHash)
                {
                    nameHashes = new ulong[count];

                    for (var i = 0; i < count; ++i)
                    {
                        nameHashes[i] = stream.ReadUInt64();
                    }
                }

                for (var i = 0; i < count; ++i)
                {
                    var fileDataId = filedataIds[i];
                    var hash       = 0UL;

                    if (nameHashes == null)
                    {
                        hash = FileDataHash.ComputeHash(fileDataId);
                    }
                    else
                    {
                        hash = nameHashes[i];
                    }

                    RootData.Add(fileDataId, entries[i]);
                    if (FileDataStore.TryGetValue(fileDataId, out ulong hash2))
                    {
                        if (hash2 != hash)
                        {
                            Console.WriteLine("ERROR: got multiple hashes for filedataid {0}", fileDataId);
                        }

                        continue;
                    }

                    FileDataStore.Add(fileDataId, hash);
                    FileDataStoreReverse.Add(hash, fileDataId);
                }
                ;
            }
        }