示例#1
0
        public static bool ExtractTextureMap(string fileName, Forge forge)
        {
            using (Stream stream = new FileStream($"{fileName}-combined", FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    // this is omnipresent
                    DatafileHeader header = new DatafileHeader
                    {
                        ResourceType = reader.ReadInt32(),
                        FileSize     = reader.ReadInt32(),
                        FileNameSize = reader.ReadInt32()
                    };
                    header.FileName = reader.ReadChars(header.FileNameSize);

                    // ignore the 2 bytes, file ID, and resource type identifier
                    reader.BaseStream.Seek(14, SeekOrigin.Current);

                    // toppmip 0
                    TopMip mip0 = new TopMip
                    {
                        Width  = reader.ReadInt32(),
                        Height = reader.ReadInt32()
                    };
                    reader.BaseStream.Seek(8, SeekOrigin.Current);
                    mip0.DXTType = DXTExtensions.GetDXT(reader.ReadInt32());
                    reader.BaseStream.Seek(4, SeekOrigin.Current);
                    mip0.Mipmaps = reader.ReadInt32();

                    reader.BaseStream.Seek(81, SeekOrigin.Current);

                    // topmip 1
                    TopMip mip1 = new TopMip
                    {
                        Width  = reader.ReadInt32(),
                        Height = reader.ReadInt32()
                    };
                    reader.BaseStream.Seek(8, SeekOrigin.Current);
                    mip1.DXTType = DXTExtensions.GetDXT(reader.ReadInt32());
                    reader.BaseStream.Seek(4, SeekOrigin.Current);
                    mip1.Mipmaps = reader.ReadInt32();

                    // locate the two topmips, if they exist
                    if (forge.FileEntries.Where(x => x.NameTable.Name.Contains(Path.GetFileName(fileName) + "_TopMip")).Count() == 2)
                    {
                        Forge.FileEntry topMipEntry = forge.FileEntries.Where(x => x.NameTable.Name == Path.GetFileName(fileName) + "_TopMip_0").First();

                        // extract, read, and create DDS images with the first topmips
                        byte[] rawData = forge.GetRawData(topMipEntry);
                        Helpers.WriteToTempFile(topMipEntry.NameTable.Name, rawData);

                        ReadFile(Helpers.GetTempPath(topMipEntry.NameTable.Name));

                        ExtractTopMip(Helpers.GetTempPath(topMipEntry.NameTable.Name), mip0);
                    }
                    else // topmips do not exist. fear not! there is still image data found here. let us use that.
                    {
                        reader.BaseStream.Seek(25, SeekOrigin.Current);
                        TextureMap map = new TextureMap
                        {
                            DataSize = reader.ReadInt32()
                        };

                        byte[] mipmapData = reader.ReadBytes(map.DataSize);
                        Helpers.WriteTempDDS(fileName, mipmapData, mip0.Width, mip0.Height, mip0.Mipmaps, mip0.DXTType);
                    }
                }
            }

            return(true);
        }
示例#2
0
        public static void ExtractTextureMap(string fileName, EntryTreeNode node, Action <string> completionAction)
        {
            string name = Path.GetFileNameWithoutExtension(fileName);

            using (Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                if (stream.Length == 0)
                {
                    return;
                }

                using (BinaryReader reader = new BinaryReader(stream))
                {
                    DatafileHeader header = new DatafileHeader
                    {
                        ResourceType = reader.ReadInt32(),
                        FileSize     = reader.ReadInt32(),
                        FileNameSize = reader.ReadInt32()
                    };
                    header.FileName = reader.ReadChars(header.FileNameSize);

                    // ignore the 1 byte, file ID, resource type, and 1 extra byte
                    reader.BaseStream.Seek(14, SeekOrigin.Current);

                    // mip 0
                    Mip mip0 = new Mip
                    {
                        Width  = reader.ReadInt32(),
                        Height = reader.ReadInt32()
                    };
                    reader.BaseStream.Seek(8, SeekOrigin.Current);
                    mip0.DXTType = DXTExtensions.GetDXT(reader.ReadInt32());
                    reader.BaseStream.Seek(4, SeekOrigin.Current);
                    mip0.Mipmaps = reader.ReadInt32();

                    reader.BaseStream.Seek(39, SeekOrigin.Current); // go to next mip

                    // mip 1
                    Mip mip1 = new Mip
                    {
                        Width  = reader.ReadInt32(),
                        Height = reader.ReadInt32()
                    };
                    reader.BaseStream.Seek(8, SeekOrigin.Current);
                    mip1.DXTType = DXTExtensions.GetDXT(reader.ReadInt32());
                    reader.BaseStream.Seek(4, SeekOrigin.Current);
                    mip1.Mipmaps = reader.ReadInt32();

                    // locate the two mips, if they exist
                    if (node.GetForge().FileEntries.Where(x => x.NameTable.Name.Contains(Path.GetFileNameWithoutExtension(fileName) + "_Mip")).Count() == 2)
                    {
                        Forge.FileEntry[] mipEntries = node.GetForge().FileEntries.Where(x => x.NameTable.Name == Path.GetFileNameWithoutExtension(fileName) + "_Mip0").ToArray();
                        if (mipEntries.Length > 0)
                        {
                            Forge.FileEntry mipEntry = mipEntries[0];

                            // extract, read, and create a DDS image with the first mip
                            byte[] rawTopMipData = node.GetForge().GetRawData(mipEntry);
                            //Helpers.WriteToFile(mipEntry.NameTable.Name, rawData, true);

                            // read
                            //ReadFile(Helpers.GetTempPath(mipEntry.NameTable.Name));
                            byte[] topMipData = ReadFile(rawTopMipData);

                            // extract
                            //ExtractTopMip(Helpers.GetTempPath(mipEntry.NameTable.Name), mip0, completionAction);
                            ExtractTopMip(topMipData, mipEntry.NameTable.Name, mip0, completionAction);
                        }
                    }
                    else // mips do not exist. fear not! there is still image data found here. let us use that.
                    {
                        reader.BaseStream.Seek(12, SeekOrigin.Current);

                        TextureMap map = new TextureMap
                        {
                            DataSize = reader.ReadInt32()
                        };
                        byte[] mipmapData = reader.ReadBytes(map.DataSize);

                        // write DDS file
                        Helpers.WriteTempDDS(name, mipmapData, mip1.Width, mip1.Height, mip1.Mipmaps, mip1.DXTType, () =>
                        {
                            Helpers.ConvertDDS($"{Helpers.GetTempPath(name)}.dds", (bool error) => {
                                if (error)
                                {
                                    completionAction("FAILED");
                                }
                                else
                                {
                                    completionAction($"{Helpers.GetTempPath(name)}.png");
                                }
                            });
                        });
                    }
                }
            }
        }
示例#3
0
        /// <summary>
        /// Writes an entire .dds file to the temporary path using the fileName
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="imageData"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mipmapCount"></param>
        /// <param name="dxtType"></param>
        /// <param name="completedAction"></param>
        public static void WriteTempDDS(string fileName, byte[] imageData, int width, int height, int mipmapCount, DXT dxtType, Action completedAction)
        {
            Console.WriteLine("DXT: " + dxtType.ToString());

            char[] dxtArr = { 'D', 'X', '\x0', '\x0' };
            int    pls    = imageData.Length; //Math.Max(1, (width + 3) / 4) * 8

            try
            {
                using (FileStream stream = new FileStream($"{GetTempPath(fileName)}.dds", FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    using (BinaryWriter writer = new BinaryWriter(stream))
                    {
                        foreach (char c in new char[] { 'D', 'D', 'S', ' ' }) // DDS magic
                        {
                            writer.Write(c);
                        }
                        writer.Write(124);           // size of DDS header
                        writer.Write(659463);        // flags
                        writer.Write(height);        // height
                        writer.Write(width);         // width
                        writer.Write(pls);           // pitch or linear size
                        writer.Write(0);             // depth
                        writer.Write(1);             // mipmap count, "1" for now
                        for (int i = 0; i < 11; i++) // reserved
                        {
                            writer.Write(0);
                        }
                        writer.Write(32);                             // size of PIXELFORMAT chunk
                        if (dxtType == 0 ? false : (int)dxtType != 7) // flags
                        {
                            writer.Write(4);
                        }
                        else
                        {
                            writer.Write(64);
                        }
                        foreach (char c in DXTExtensions.GetDXTAsChars((int)dxtType)) // DXT type/four CC
                        {
                            writer.Write(c);
                        }
                        for (int n = 0; n < 5; n++) // RGBBitCount, RBitMask, GBitMask, BBitMask, ABitMask
                        {
                            writer.Write(0);
                        }
                        writer.Write(4198408);      // caps
                        for (int i = 0; i < 4; i++) // caps2, caps3, caps4, reserved2
                        {
                            writer.Write(0);
                        }
                        if (dxtType.ToString().Contains("DX10")) // add the DX10 header, if necessary
                        {
                            string fileNameNoExt = Path.GetFileNameWithoutExtension(fileName);
                            if (fileNameNoExt.Contains("NormalMap") || fileNameNoExt.EndsWith("_Map")) // this stays until I devise a better tactic
                            {
                                writer.Write(98);                                                      // normal maps
                            }
                            else
                            {
                                writer.Write(72); // all others use BC1_UNORM_SRGB
                            }
                            writer.Write(3);      // resourceDimension
                            writer.Write(0);      // miscFlags
                            writer.Write(1);      // array size
                            writer.Write(0);      // miscFlags2
                        }
                        writer.Write(imageData);  // image data
                    }
                }
            }
            catch (IOException e)
            {
                MessageBox.Show($"Could not create a dds file due an error:\n{e.Message}", "Failure");
            }

            completedAction();
        }
示例#4
0
        /// <summary>
        /// Writes an entire .dds file to the temporary path using the fileName
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="imageData"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mipmapCount"></param>
        /// <param name="dxtType"></param>
        /// <param name="completedAction"></param>
        public static void WriteTempDDS(string fileName, byte[] imageData, int width, int height, int mipmapCount, DXT dxtType, Action completedAction)
        {
            Console.WriteLine("DXT: " + dxtType.ToString());

            char[] dxtArr = { 'D', 'X', '\x0', '\x0' };
            try
            {
                using (FileStream stream = new FileStream($"{GetTempPath(fileName)}.dds", FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    using (BinaryWriter writer = new BinaryWriter(stream))
                    {
                        foreach (char c in new char[] { 'D', 'D', 'S', ' ' }) // DDS magic
                        {
                            writer.Write(c);
                        }
                        writer.Write(BitConverter.GetBytes(124));         // size of DDS header
                        writer.Write(new byte[] { 0x7, 0x10, 0x8, 0x0 }); // flags
                        writer.Write(height);                             // height
                        writer.Write(width);                              // width
                        writer.Write(BitConverter.GetBytes(2048));        // pitch or linear size
                        writer.Write(1);                                  // depth
                        writer.Write(1);                                  // mipmap count, "1" for now
                        for (int i = 0; i < 11; i++)                      // reserved
                        {
                            writer.Write(0);
                        }

                        // DDS_PIXELFORMAT
                        writer.Write(32);                             // size of PIXELFORMAT
                        if (dxtType == 0 ? false : (int)dxtType != 7) // flags
                        {
                            writer.Write(BitConverter.GetBytes(4));
                        }
                        else
                        {
                            writer.Write(BitConverter.GetBytes(64));
                        }
                        foreach (char c in DXTExtensions.GetDXTAsChars((int)dxtType)) // DXT type/four CC
                        {
                            writer.Write(c);
                        }
                        for (int n = 0; n < 5; n++) // RGBBitCount, RBitMask, GBitMask, BBitMask, ABitMask
                        {
                            writer.Write(0);
                        }

                        writer.Write(4198408);      // caps
                        for (int i = 0; i < 4; i++) // caps2, caps3, caps4, reserved2
                        {
                            writer.Write(0);
                        }

                        // DDS_HEADER_DX10
                        if (dxtType.ToString().Contains("DX10")) // add the DX10 header, if necessary
                        {
                            string fileNameNoExt = Path.GetFileNameWithoutExtension(fileName);
                            if (fileNameNoExt.Contains("NormalMap") || fileNameNoExt.EndsWith("_Map")) // this stays until I devise a better tactic
                            {
                                writer.Write(BitConverter.GetBytes(98));                               // BC7_UNORM (normal maps)
                            }
                            else if (false)
                            {
                                writer.Write(BitConverter.GetBytes(71)); // BC1_UNORM (mask maps)
                            }
                            else
                            {
                                writer.Write(BitConverter.GetBytes(72)); // BC1_UNORM_SRGB
                            }
                            writer.Write(BitConverter.GetBytes(3));      // resource dimension
                            writer.Write(0);                             // misc flags
                            writer.Write(BitConverter.GetBytes(1));      // array size
                            writer.Write(0);                             // misc flags 2
                        }

                        // image data
                        writer.Write(imageData);
                    }
                }
            }
            catch (IOException e)
            {
                Message.Fail("Could not create a DDS file. " + e.Message + e.StackTrace);
            }

            completedAction();
        }