Example #1
0
        public void TestUnknownBlock()
        {
            var memStream = new MemoryStream();

            memStream.WriteByte(127);
            memStream.WriteByte(0);
            memStream.WriteByte(0);
            memStream.WriteByte(0);
            memStream.Position = 0;
            var block = new BinaryReader(memStream).ReadBlock();

            BlockDecompressor.Decompress(block);
        }
        private bool ReadNextBlock()
        {
            if (remainingBytesOffset != remainingBytes.Length) // todo: replace with proper assert
            {
                throw new ApplicationException("Assertion failed: remainingBytesOffset != remainingBytes.Length");
            }

            if (internalReader.BaseStream.Position == internalReader.BaseStream.Length)
            {
                return(false); // todo: more proper eof detection?
            }
            var block = internalReader.ReadBlock();

            remainingBytes       = BlockDecompressor.Decompress(block);
            remainingBytesOffset = 0;
            return(true);
        }
Example #3
0
        public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID)
        {
            bool   convertTextures = true;
            string convertType     = "dds";
            bool   lossless        = false;

            if (flags is ExtractFlags extractFlags)
            {
                convertTextures = extractFlags.ConvertTextures && !extractFlags.Raw;
                convertType     = extractFlags.ConvertTexturesType.ToLowerInvariant();
                lossless        = extractFlags.ConvertTexturesLossless;
                if (extractFlags.SkipTextures)
                {
                    return;
                }
            }
            path += Path.DirectorySeparatorChar;

            FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID];
            string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}");

            if (Program.Flags.Deduplicate)
            {
                if (ScratchDBInstance.HasRecord(textureGUID))
                {
                    return;
                }
                ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}");
            }

            CreateDirectoryFromFile(path);
            if (!convertTextures)
            {
                using (Stream textureStream = OpenFile(textureInfo.GUID)) {
                    teTexture texture = new teTexture(textureStream, true);
                    textureStream.Position = 0;
                    WriteFile(textureStream, $"{filePath}.004");

                    if (!texture.PayloadRequired)
                    {
                        return;
                    }
                    using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID)))
                        WriteFile(texturePayloadStream, $"{filePath}.04D");
                }
            }
            else
            {
                using (Stream textureStream = OpenFile(textureGUID)) {
                    if (textureStream == null)
                    {
                        return;
                    }
                    teTexture texture = new teTexture(textureStream);

                    if (texture.PayloadRequired)
                    {
                        texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID)));
                    }

                    using (Stream convertedStream = texture.SaveToDDS()) {
                        convertedStream.Position = 0;
                        if (convertType == "dds" || convertedStream.Length == 0)
                        {
                            WriteFile(convertedStream, $"{filePath}.dds");
                            return;
                        }

                        uint fourCC      = texture.Header.GetFormat().ToPixelFormat().FourCC;
                        bool isBcffValid = TextureConfig.DXGI_BC4.Contains((int)texture.Header.Format) ||
                                           TextureConfig.DXGI_BC5.Contains((int)texture.Header.Format) ||
                                           fourCC == TextureConfig.FOURCC_ATI1 || fourCC == TextureConfig.FOURCC_ATI2;


                        ImageFormat imageFormat = null;
                        if (convertType == "tif")
                        {
                            imageFormat = ImageFormat.Tiff;
                        }
                        // if (convertType == "tga") imageFormat = Im.... oh
                        // so there is no TGA image format.
                        // guess the TGA users are stuck with the DirectXTex stuff for now.

                        if (isBcffValid && imageFormat != null)
                        {
                            BlockDecompressor decompressor = new BlockDecompressor(convertedStream);
                            decompressor.CreateImage();
                            decompressor.Image.Save($"{filePath}.{convertType}", imageFormat);
                            return;
                        }

                        string losslessFlag = lossless ? "-wiclossless" : string.Empty;

                        Process pProcess = new Process {
                            StartInfo =
                            {
                                FileName               = "Third Party\\texconv.exe",
                                UseShellExecute        = false,
                                RedirectStandardOutput = true,
                                RedirectStandardInput  = true,
                                RedirectStandardError  = true,
                                CreateNoWindow         = true,
                                Arguments              =
                                    $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{path}"
                            },
                            EnableRaisingEvents = true
                        };

                        // erm, so if you add an end quote to this then it breaks.
                        // but start one on it's own is fine (we need something for "Winged Victory")
                        pProcess.Start();
                        convertedStream.Position = 0;
                        convertedStream.CopyTo(pProcess.StandardInput.BaseStream);
                        pProcess.StandardInput.BaseStream.Close();

                        // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care
                        // when texconv writes with to the console -nologo is has done/failed conversion
                        string line = pProcess.StandardOutput.ReadLine();
                        if (line?.Contains("FAILED") == true)
                        {
                            convertedStream.Position = 0;
                            WriteFile(convertedStream, $"{filePath}.dds");
                        }
                    }
                }
            }
        }
Example #4
0
            public override void Run(WorkerThread thread)
            {
                const string convertType = "tif";

                Stream headerStream = OpenFile(HeaderGUID);
                Stream dataStream   = null;

                if (DataGUID != 0)
                {
                    dataStream = OpenFile(DataGUID);
                }

                string filePath = System.IO.Path.Combine(Path, $"{GUID.Index(HeaderGUID)}");

                CreateDirectoryFromFile(filePath);

                TextureHeader header;
                Stream        convertedStream;

                if (dataStream != null)
                {
                    Texture textObj = new Texture(headerStream, dataStream);
                    convertedStream = textObj.Save();
                    header          = textObj.Header;
                    headerStream.Dispose();
                    dataStream.Dispose();
                }
                else
                {
                    TextureLinear textObj = new TextureLinear(headerStream);
                    convertedStream = textObj.Save();
                    header          = textObj.Header;
                    headerStream.Dispose();
                }
                uint fourCC      = header.Format().ToPixelFormat().fourCC;
                bool isBcffValid = Combo.TextureConfig.DXGI_BC4.Contains((int)header.format) ||
                                   Combo.TextureConfig.DXGI_BC5.Contains((int)header.format) ||
                                   fourCC == Combo.TextureConfig.FOURCC_ATI1 || fourCC == Combo.TextureConfig.FOURCC_ATI2;

                ImageFormat imageFormat = null;

                if (convertType == "tif")
                {
                    imageFormat = ImageFormat.Tiff;
                }

                convertedStream.Position = 0;

                if (isBcffValid && imageFormat != null && convertedStream.Length != 0)
                {
                    BlockDecompressor decompressor = new BlockDecompressor(convertedStream);
                    decompressor.CreateImage();
                    decompressor.Image.Save($"{filePath}.{convertType}", imageFormat);
                    return;
                }

                convertedStream.Position = 0;
                if (convertType == "tga" || convertType == "tif" || convertType == "dds")
                {
                    // we need the dds for tif conversion
                    WriteFile(convertedStream, $"{filePath}.dds");
                }

                convertedStream.Close();

                if (convertType != "tif" && convertType != "tga")
                {
                    return;
                }
                Process pProcess = new Process {
                    StartInfo =
                    {
                        FileName               = "Third Party\\texconv.exe",
                        UseShellExecute        = false,
                        RedirectStandardOutput = true,
                        Arguments              =
                            $"\"{filePath}.dds\" -y -wicmulti -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{Path}"
                    }
                };

                // -wiclossless?

                // erm, so if you add an end quote to this then it breaks.
                // but start one on it's own is fine (we need something for "Winged Victory")
                pProcess.Start();
                // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care
                // when texconv writes with to the console -nologo is has done/failed conversion

                // string line = pProcess.StandardOutput.ReadLine();
                // if (line?.Contains($"{filePath}.dds FAILED") == false) {
                // fallback if convert fails
                File.Delete($"{filePath}.dds");
                // }
            }
Example #5
0
        private static void ConvertTexture(string convertType, string filePath, string path, Stream headerStream, Stream dataStream)
        {
            CreateDirectoryFromFile(path);
            Stream        convertedStream;
            TextureHeader header;

            if (dataStream != null)
            {
                Texture textObj = new Texture(headerStream, dataStream);
                convertedStream = textObj.Save();
                header          = textObj.Header;
                headerStream.Dispose();
                dataStream.Dispose();
            }
            else
            {
                TextureLinear textObj = new TextureLinear(headerStream);
                convertedStream = textObj.Save();
                header          = textObj.Header;
                headerStream.Dispose();
            }

            uint fourCC      = header.Format().ToPixelFormat().fourCC;
            bool isBcffValid = TextureConfig.DXGI_BC4.Contains((int)header.format) ||
                               TextureConfig.DXGI_BC5.Contains((int)header.format) ||
                               fourCC == TextureConfig.FOURCC_ATI1 || fourCC == TextureConfig.FOURCC_ATI2;

            ImageFormat imageFormat = null;

            if (convertType == "tif")
            {
                imageFormat = ImageFormat.Tiff;
            }

            // if (convertType == "tga") imageFormat = Im.... oh
            // so there is no TGA image format.
            // guess the TGA users are stuck with the DirectXTex stuff for now.

            if (convertedStream.Length == 0)
            {
                WriteFile(Stream.Null, $"{filePath}.{convertType}");
                return;
            }

            convertedStream.Position = 0;
            if (isBcffValid && imageFormat != null)
            {
                BlockDecompressor decompressor = new BlockDecompressor(convertedStream);
                decompressor.CreateImage();
                decompressor.Image.Save($"{filePath}.{convertType}", imageFormat);
                return;
            }

            convertedStream.Position = 0;
            if (convertType == "tga" || convertType == "tif" || convertType == "dds")
            {
                // we need the dds for tif conversion
                WriteFile(convertedStream, $"{filePath}.dds");
            }

            convertedStream.Close();

            if (convertType != "tif" && convertType != "tga")
            {
                return;
            }
            Process pProcess = new Process {
                StartInfo =
                {
                    FileName               = "Third Party\\texconv.exe",
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    Arguments              =
                        $"\"{filePath}.dds\" -y -wicmulti -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{path}"
                }
            };

            // -wiclossless?

            // erm, so if you add an end quote to this then it breaks.
            // but start one on it's own is fine (we need something for "Winged Victory")
            pProcess.Start();
            // pProcess.WaitForExit(); // not using this is kinda dangerous but I don't care
            // when texconv writes with to the console -nologo is has done/failed conversion
            string line = pProcess.StandardOutput.ReadLine();

            if (line?.Contains($"{filePath}.dds FAILED") == false)
            {
                // fallback if convert fails
                File.Delete($"{filePath}.dds");
            }
        }
Example #6
0
        public static void SaveTexture(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong textureGUID)
        {
            bool   convertTextures         = true;
            string convertType             = "tif";
            string multiSurfaceConvertType = "tif";
            bool   createMultiSurfaceSheet = false;
            bool   lossless = false;
            int    maxMips  = 1;

            if (flags is ExtractFlags extractFlags)
            {
                if (extractFlags.SkipTextures)
                {
                    return;
                }
                createMultiSurfaceSheet = extractFlags.SheetMultiSurface;
                convertTextures         = !extractFlags.RawTextures && !extractFlags.Raw;
                convertType             = extractFlags.ConvertTexturesType.ToLowerInvariant();
                lossless = extractFlags.ConvertTexturesLossless;

                multiSurfaceConvertType = convertType;
                if (extractFlags.ForceDDSMultiSurface)
                {
                    multiSurfaceConvertType = "dds";
                }

                if (convertType == "dds" && extractFlags.SaveMips)
                {
                    maxMips = 0xF;
                }
            }
            path += Path.DirectorySeparatorChar;

            FindLogic.Combo.TextureInfoNew textureInfo = info.Textures[textureGUID];
            string filePath = Path.Combine(path, $"{textureInfo.GetNameIndex()}");

            if (teResourceGUID.Type(textureGUID) != 0x4)
            {
                filePath += $".{teResourceGUID.Type(textureGUID):X3}";
            }

            if (Program.Flags.Deduplicate)
            {
                if (ScratchDBInstance.HasRecord(textureGUID))
                {
                    return;
                }
                ScratchDBInstance[textureGUID] = new ScratchDB.ScratchPath($"{filePath}.{convertType}");
            }

            CreateDirectoryFromFile(path);
            if (!convertTextures)
            {
                using (Stream textureStream = OpenFile(textureGUID)) {
                    teTexture texture = new teTexture(textureStream, true);
                    textureStream.Position = 0;
                    WriteFile(textureStream, $"{filePath}.004");

                    if (!texture.PayloadRequired)
                    {
                        return;
                    }
                    for (int i = 0; i < texture.Payloads.Length; ++i)
                    {
                        using (Stream texturePayloadStream = OpenFile(texture.GetPayloadGUID(textureGUID, i)))
                            WriteFile(texturePayloadStream, $"{filePath}_{i}.04D");
                    }
                }
            }
            else
            {
                using (Stream textureStream = OpenFile(textureGUID)) {
                    if (textureStream == null)
                    {
                        return;
                    }
                    teTexture texture = new teTexture(textureStream);

                    //if (texture.Header.Flags.HasFlag(teTexture.Flags.CUBEMAP)) return;
                    // for diffing when they add/regen loads of cubemaps

                    if (texture.PayloadRequired)
                    {
                        for (int i = 0; i < texture.Payloads.Length; ++i)
                        {
                            texture.LoadPayload(OpenFile(texture.GetPayloadGUID(textureGUID, i)), i);
                            if (maxMips == 1)
                            {
                                break;
                            }
                        }
                    }

                    uint?width    = null;
                    uint?height   = null;
                    uint?surfaces = null;
                    if (texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces)
                    {
                        if (createMultiSurfaceSheet)
                        {
                            TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as a sheet because it has more than one surface");
                            height               = (uint)(texture.Header.Height * texture.Header.Surfaces);
                            surfaces             = 1;
                            texture.Header.Flags = 0;
                        }
                        else
                        {
                            TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as {multiSurfaceConvertType} because it has more than one surface");
                            convertType = multiSurfaceConvertType;
                        }
                    }

                    using (Stream convertedStream = texture.SaveToDDS(maxMips == 1 ? 1 : texture.Header.MipCount, width, height, surfaces)) {
                        convertedStream.Position = 0;
                        if (convertType == "dds" || convertedStream.Length == 0)
                        {
                            WriteFile(convertedStream, $"{filePath}.dds");
                            return;
                        }

                        bool isBcffValid = teTexture.DXGI_BC4.Contains(texture.Header.Format) ||
                                           teTexture.DXGI_BC5.Contains(texture.Header.Format) ||
                                           teTexture.ATI2.Contains(texture.Header.GetTextureType());

                        ImageFormat imageFormat = null;
                        if (convertType == "tif")
                        {
                            imageFormat = ImageFormat.Tiff;
                        }
                        if (convertType == "png")
                        {
                            imageFormat = ImageFormat.Png;
                        }
                        if (convertType == "jpg")
                        {
                            imageFormat = ImageFormat.Jpeg;
                        }
                        // if (convertType == "tga") imageFormat = Im.... oh
                        // so there is no TGA image format.
                        // guess the TGA users are stuck with the DirectXTex stuff for now.

                        if (isBcffValid && imageFormat != null && !(texture.Header.IsCubemap || texture.Header.IsArray || texture.HasMultipleSurfaces))
                        {
                            BlockDecompressor decompressor = new BlockDecompressor(convertedStream);
                            decompressor.CreateImage();
                            decompressor.Image.Save($"{filePath}.{convertType}", imageFormat);
                            return;
                        }

                        string losslessFlag = lossless ? "-wiclossless" : string.Empty;

                        Process pProcess = new Process {
                            StartInfo =
                            {
                                FileName               = "Third Party\\texconv.exe",
                                UseShellExecute        = false,
                                RedirectStandardOutput = true,
                                RedirectStandardInput  = true,
                                RedirectStandardError  = true,
                                CreateNoWindow         = true,
                                Arguments              =
                                    $"-- \"{Path.GetFileName(filePath)}.dds\" -y -wicmulti {losslessFlag} -nologo -m 1 -ft {convertType} -f R8G8B8A8_UNORM -o \"{(path.EndsWith(@"/") || path.EndsWith("\\") ? path.Substring(0, path.Length - 1) : path)}"
                            },
                            EnableRaisingEvents = true
                        };

                        pProcess.Start();
                        convertedStream.Position = 0;
                        convertedStream.CopyTo(pProcess.StandardInput.BaseStream);
                        pProcess.StandardInput.BaseStream.Flush();
                        pProcess.StandardInput.BaseStream.Close();
                        pProcess.WaitForExit();
                        // when texconv writes with to the console -nologo is has done/failed conversion
                        string line = pProcess.StandardOutput.ReadToEnd();
                        if (line.Contains("FAILED"))
                        {
                            convertedStream.Position = 0;
                            TankLib.Helpers.Logger.Debug("Combo", $"Saving {Path.GetFileName(filePath)} as dds because texconv failed.");
                            WriteFile(convertedStream, $"{filePath}.dds");
                        }
                    }
                }
            }
        }