예제 #1
0
        private int UnpackTPF(TPF tpf, string relOutputDir, UnpackReport report)
        {
            if (tpf.Platform != TPF.TPFPlatform.PC)
            {
                return(0);
            }

            foreach (TPF.Texture texture in tpf)
            {
                try
                {
                    string dir  = $@"{Game.Settings.UnpackDirectory.TrimEnd('\\')}\{relOutputDir}";
                    string path = $@"{dir}\{texture.Name}.dds";

                    Directory.CreateDirectory(dir);
                    File.WriteAllBytes(path, texture.Bytes);
                    report.Files.Add(new UnpackReportFile(texture));
                }
                catch (Exception ex)
                {
                    throw new Exception($"Error in texture \"{texture.Name}\"", ex);
                }
            }
            return(tpf.Textures.Count);
        }
예제 #2
0
        private int UnpackBinder(IBinder binder, string relOutputDir, UnpackReport report, CancellationToken cancelToken)
        {
            int textureCount = 0;

            foreach (BinderFile file in binder.Files)
            {
                if (cancelToken.IsCancellationRequested)
                {
                    return(textureCount);
                }

                if (TPUtil.HasValidExtension(file.Name))
                {
                    try
                    {
                        byte[] bytes = file.Bytes;
                        if (DCX.Is(bytes))
                        {
                            bytes = DCX.Decompress(bytes);
                        }

                        if (TPF.IsRead(bytes, out TPF tpf))
                        {
                            textureCount += UnpackTPF(tpf, relOutputDir, report);
                        }
                        else if (BND4.IsRead(bytes, out BND4 bnd))
                        {
                            textureCount += UnpackBinder(bnd, relOutputDir, report, cancelToken);
                        }
                        else
                        {
                            throw new NotSupportedException("Unknown file type.");
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception($"Error in binder file \"{file.Name}\"", ex);
                    }
                }
            }
            return(textureCount);
        }
예제 #3
0
        private int UnpackVirtualFile(VirtualFile vf, CancellationToken cancelToken)
        {
            byte[] bytes;
            long   baseMemory;

            lock (this)
            {
                while (BaseMemoryCommitted > TPUtil.MAX_BASE_MEMORY)
                {
                    Thread.Sleep(10);
                }

                if (cancelToken.IsCancellationRequested)
                {
                    return(0);
                }

                bytes      = vf.Load();
                baseMemory = bytes.Length;
                Interlocked.Add(ref BaseMemoryCommitted, baseMemory);
            }

            try
            {
                string relOutputDir = TPUtil.GetRelativeOutputDir(vf.Path);
                if (DCX.Is(bytes))
                {
                    bytes = DCX.Decompress(bytes);
                }

                int textureCount;
                var report = new UnpackReport();
                if (TPF.IsRead(bytes, out TPF tpf))
                {
                    textureCount = UnpackTPF(tpf, relOutputDir, report);
                }
                else if (BND4.IsRead(bytes, out BND4 bnd))
                {
                    textureCount = UnpackBinder(bnd, relOutputDir, report, cancelToken);
                }
                else if (BXF4.IsBDT(bytes))
                {
                    string      ext      = Path.GetExtension(vf.Path).Replace("bdt", "bhd");
                    string      bhdPath  = Path.ChangeExtension(vf.Path, ext);
                    VirtualFile vfHeader = VirtualFS.Files[bhdPath];
                    byte[]      bhdBytes = vfHeader.Load();
                    var         bxf      = BXF4.Read(bhdBytes, bytes);
                    textureCount = UnpackBinder(bxf, relOutputDir, report, cancelToken);
                }
                else
                {
                    throw new NotSupportedException("Unknown file type.");
                }

                if (report.Files.Count > 0)
                {
                    File.WriteAllText($@"{Game.Settings.UnpackDirectory.TrimEnd('\\')}\{relOutputDir}\_report.txt", report.Write());
                }
                return(textureCount);
            }
            finally
            {
                Interlocked.Add(ref BaseMemoryCommitted, -baseMemory);
            }
        }