Exemplo n.º 1
0
        /// <summary>
        /// Creates a DDS file for the given Texture
        /// </summary>
        /// <param name="saveDirectory">The directory to save the dds file to</param>
        /// <param name="xivTex">The Texture information</param>
        public static void MakeDDS(XivTex xivTex, string savePath)
        {
            var DDS = new List <byte>();

            switch (xivTex.TextureTypeAndPath.Type)
            {
            case XivTexType.ColorSet:
                DDS.AddRange(CreateColorDDSHeader());
                DDS.AddRange(xivTex.TexData);
                break;

            case XivTexType.Vfx:
            case XivTexType.Diffuse:
            case XivTexType.Specular:
            case XivTexType.Normal:
            case XivTexType.Multi:
            case XivTexType.Mask:
            case XivTexType.Skin:
            case XivTexType.Map:
            case XivTexType.Icon:
            default:
                DDS.AddRange(CreateDDSHeader(xivTex));

                var data = xivTex.TexData;
                if (xivTex.TextureFormat == XivTexFormat.A8R8G8B8 && xivTex.Layers > 1)
                {
                    data = ShiftLayers(data);
                }
                DDS.AddRange(data);
                break;
            }

            File.WriteAllBytes(savePath, DDS.ToArray());
        }
Exemplo n.º 2
0
        public async Task SetMaterial(XivMtrl mtrl, StainingTemplateFile dyeFile)
        {
            _mtrl           = mtrl;
            DyeTemplateFile = dyeFile;

            _viewport = _view.ColorsetRowViewport;
            _viewport.BackgroundColor = System.Windows.Media.Colors.Gray;
            _viewport.Background      = Brushes.Gray;

            if (_NeedLights)
            {
                _NeedLights = false;
            }

            _viewport.Camera.UpDirection   = new System.Windows.Media.Media3D.Vector3D(0, 1, 0);
            _viewport.Camera.LookDirection = new System.Windows.Media.Media3D.Vector3D(0, 0, -1);
            _viewport.Camera.Position      = new System.Windows.Media.Media3D.Point3D(0, 0, 3);



            if (TileTextureNormal == null)
            {
                var _tex = new Tex(XivCache.GameInfo.GameDirectory);
                TileTextureNormal = await _tex.GetTexData("chara/common/texture/-tile_n.tex");

                TileTextureDiffuse = await _tex.GetTexData("chara/common/texture/-tile_d.tex");
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Gets the ATex data
        /// </summary>
        /// <param name="offset">The offset to the ATex file</param>
        /// <returns>An XivTex with all the texture data</returns>
        public XivTex GetATexData(int offset)
        {
            var dat      = new Dat(_gameDirectory);
            var atexData = dat.GetType2Data(offset, _dataFile);

            var xivTex = new XivTex();

            using (var br = new BinaryReader(new MemoryStream(atexData)))
            {
                var signature = br.ReadInt32();
                xivTex.TextureFormat = Dat.TextureTypeDictionary[br.ReadInt32()];
                xivTex.Width         = br.ReadInt16();
                xivTex.Height        = br.ReadInt16();

                br.ReadBytes(2);

                xivTex.MipMapCount = br.ReadInt16();

                br.ReadBytes(64);

                xivTex.TexData = br.ReadBytes(atexData.Length - 80);
            }

            return(xivTex);
        }
Exemplo n.º 4
0
        public XivTex GetTexData(TexTypePath ttp)
        {
            var xivTex = new XivTex {
                TextureTypeAndPath = ttp
            };

            var folder = Path.GetDirectoryName(ttp.Path);

            folder = folder.Replace("\\", "/");
            var file = Path.GetFileName(ttp.Path);

            var index = new Index(_gameDirectory);
            var dat   = new Dat(_gameDirectory);

            var offset = index.GetDataOffset(HashGenerator.GetHash(folder), HashGenerator.GetHash(file), ttp.DataFile);

            if (offset == 0)
            {
                throw new Exception($"Could not find offest for {ttp.Path}");
            }

            dat.GetType4Data(offset, ttp.DataFile, xivTex);

            return(xivTex);
        }
Exemplo n.º 5
0
        public void SaveTexAsDDS(IItem item, XivTex xivTex, DirectoryInfo saveDirectory, XivRace race = XivRace.All_Races)
        {
            var path = IOUtil.MakeItemSavePath(item, saveDirectory, race);

            Directory.CreateDirectory(path);

            var savePath = Path.Combine(path, Path.GetFileNameWithoutExtension(xivTex.TextureTypeAndPath.Path) + ".dds");

            DDS.MakeDDS(xivTex, savePath);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Gets the original or modded data for type 4 files based on the path specified.
        /// </summary>
        /// <remarks>
        /// Type 4 files are used for Textures
        /// </remarks>
        /// <param name="internalPath">The internal file path of the item</param>
        /// <param name="forceOriginal">Flag used to get original game data</param>
        /// <param name="xivTex">The XivTex container to fill</param>
        public void GetType4Data(string internalPath, bool forceOriginal, XivTex xivTex)
        {
            var index = new Index(_gameDirectory);

            ModInfo modInfo   = null;
            var     inModList = false;

            var dataFile = GetDataFileFromPath(internalPath);

            if (forceOriginal)
            {
                // Checks if the item being imported already exists in the modlist
                using (var streamReader = new StreamReader(_modListDirectory.FullName))
                {
                    string line;
                    while ((line = streamReader.ReadLine()) != null)
                    {
                        modInfo = JsonConvert.DeserializeObject <ModInfo>(line);
                        if (modInfo.fullPath.Equals(internalPath))
                        {
                            inModList = true;
                            break;
                        }
                    }
                }

                // If the file exists in the modlist, get the data from the original data
                if (inModList)
                {
                    GetType4Data(modInfo.originalOffset, dataFile, xivTex);
                    return;
                }
            }

            // If it doesn't exist in the modlist(the item is not modded) or force original is false,
            // grab the data directly from them index file.

            var folder = Path.GetDirectoryName(internalPath);

            folder = folder.Replace("\\", "/");
            var file = Path.GetFileName(internalPath);

            var offset = index.GetDataOffset(HashGenerator.GetHash(folder), HashGenerator.GetHash(file),
                                             dataFile);

            if (offset == 0)
            {
                throw new Exception($"Could not find offest for {internalPath}");
            }

            GetType4Data(offset, dataFile, xivTex);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Gets the raw pixel data for the texture
        /// </summary>
        /// <param name="xivTex">The texture data</param>
        /// <returns>A byte array with the image data</returns>
        public Task <byte[]> GetImageData(XivTex xivTex)
        {
            return(Task.Run(async() =>
            {
                byte[] imageData = null;

                switch (xivTex.TextureFormat)
                {
                case XivTexFormat.DXT1:
                    imageData = DxtUtil.DecompressDxt1(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.DXT3:
                    imageData = DxtUtil.DecompressDxt3(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.DXT5:
                    imageData = DxtUtil.DecompressDxt5(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.A4R4G4B4:
                    imageData = await Read4444Image(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.A1R5G5B5:
                    imageData = await Read5551Image(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.A8R8G8B8:
                    imageData = await SwapRBColors(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.L8:
                case XivTexFormat.A8:
                    imageData = await Read8bitImage(xivTex.TexData, xivTex.Width, xivTex.Height);
                    break;

                case XivTexFormat.X8R8G8B8:
                case XivTexFormat.R32F:
                case XivTexFormat.G16R16F:
                case XivTexFormat.G32R32F:
                case XivTexFormat.A16B16G16R16F:
                case XivTexFormat.A32B32G32R32F:
                case XivTexFormat.D16:
                default:
                    imageData = xivTex.TexData;
                    break;
                }

                return imageData;
            }));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Gets the raw pixel data for the texture
        /// </summary>
        /// <param name="xivTex">The texture data</param>
        /// <returns>A byte array with the image data</returns>
        public byte[] GetImageData(XivTex xivTex)
        {
            byte[] imageData = null;

            switch (xivTex.TextureFormat)
            {
            case XivTexFormat.DXT1:
                imageData = DxtUtil.DecompressDxt1(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.DXT3:
                imageData = DxtUtil.DecompressDxt3(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.DXT5:
                imageData = DxtUtil.DecompressDxt5(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.A4R4G4B4:
                imageData = Read4444Image(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.A1R5G5B5:
                imageData = Read5551Image(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.A8R8G8B8:
                imageData = SwapRBColors(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.L8:
            case XivTexFormat.A8:
                imageData = Read8bitImage(xivTex.TexData, xivTex.Width, xivTex.Heigth);
                break;

            case XivTexFormat.X8R8G8B8:
            case XivTexFormat.R32F:
            case XivTexFormat.G16R16F:
            case XivTexFormat.G32R32F:
            case XivTexFormat.A16B16G16R16F:
            case XivTexFormat.A32B32G32R32F:
            case XivTexFormat.D16:
            default:
                imageData = xivTex.TexData;
                break;
            }

            return(imageData);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Gets the raw pixel data for the texture
        /// </summary>
        /// <param name="xivTex">The texture data</param>
        /// <returns>A byte array with the image data</returns>
        public Task <byte[]> GetImageData(XivTex xivTex, int layer = -1)
        {
            return(Task.Run(async() =>
            {
                byte[] imageData = null;

                var layers = xivTex.Layers;
                if (layers == 0)
                {
                    layers = 1;
                }

                switch (xivTex.TextureFormat)
                {
                case XivTexFormat.DXT1:
                    imageData = DxtUtil.DecompressDxt1(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.DXT3:
                    imageData = DxtUtil.DecompressDxt3(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.DXT5:
                    imageData = DxtUtil.DecompressDxt5(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.A4R4G4B4:
                    imageData = await Read4444Image(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.A1R5G5B5:
                    imageData = await Read5551Image(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.A8R8G8B8:
                    imageData = await SwapRBColors(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.L8:
                case XivTexFormat.A8:
                    imageData = await Read8bitImage(xivTex.TexData, xivTex.Width, xivTex.Height * layers);
                    break;

                case XivTexFormat.X8R8G8B8:
                case XivTexFormat.R32F:
                case XivTexFormat.G16R16F:
                case XivTexFormat.G32R32F:
                case XivTexFormat.A16B16G16R16F:
                case XivTexFormat.A32B32G32R32F:
                case XivTexFormat.D16:
                default:
                    imageData = xivTex.TexData;
                    break;
                }

                if (layer >= 0)
                {
                    var bytesPerLayer = imageData.Length / xivTex.Layers;
                    var offset = bytesPerLayer * layer;

                    byte[] nData = new byte[bytesPerLayer];
                    Array.Copy(imageData, offset, nData, 0, bytesPerLayer);

                    imageData = nData;
                }

                return imageData;
            }));
        }
Exemplo n.º 10
0
        /// <summary>
        /// Converts a DDS file into a TEX file then returns the raw data
        /// </summary>
        /// <param name="xivTex">The texture data</param>
        /// <param name="item">The item who's texture we are importing</param>
        /// <param name="ddsFileDirectory">The directory of the dds file being imported</param>
        /// <returns>The offset to the new imported data</returns>
        public async Task <byte[]> DDStoTexData(XivTex xivTex, IItem item, DirectoryInfo ddsFileDirectory)
        {
            if (File.Exists(ddsFileDirectory.FullName))
            {
                using (var br = new BinaryReader(File.OpenRead(ddsFileDirectory.FullName)))
                {
                    br.BaseStream.Seek(12, SeekOrigin.Begin);

                    var newHeight = br.ReadInt32();
                    var newWidth  = br.ReadInt32();
                    br.ReadBytes(8);
                    var newMipCount = br.ReadInt32();

                    if (newHeight % 2 != 0 || newWidth % 2 != 0)
                    {
                        throw new Exception("Resolution must be a multiple of 2");
                    }

                    br.BaseStream.Seek(80, SeekOrigin.Begin);

                    var          textureFlags = br.ReadInt32();
                    var          texType      = br.ReadInt32();
                    XivTexFormat textureType;

                    if (DDSType.ContainsKey(texType))
                    {
                        textureType = DDSType[texType];
                    }
                    else
                    {
                        throw new Exception($"DDS Type ({texType}) not recognized.");
                    }

                    switch (textureFlags)
                    {
                    case 2 when textureType == XivTexFormat.A8R8G8B8:
                        textureType = XivTexFormat.A8;
                        break;

                    case 65 when textureType == XivTexFormat.A8R8G8B8:
                        var bpp = br.ReadInt32();
                        if (bpp == 32)
                        {
                            textureType = XivTexFormat.A8R8G8B8;
                        }
                        else
                        {
                            var red = br.ReadInt32();

                            switch (red)
                            {
                            case 31744:
                                textureType = XivTexFormat.A1R5G5B5;
                                break;

                            case 3840:
                                textureType = XivTexFormat.A4R4G4B4;
                                break;
                            }
                        }

                        break;
                    }

                    if (textureType == xivTex.TextureFormat)
                    {
                        var uncompressedLength = (int)new FileInfo(ddsFileDirectory.FullName).Length - 128;
                        var newTex             = new List <byte>();

                        if (!xivTex.TextureTypeAndPath.Path.Contains(".atex"))
                        {
                            var DDSInfo = await DDS.ReadDDS(br, xivTex, newWidth, newHeight, newMipCount);

                            newTex.AddRange(_dat.MakeType4DatHeader(xivTex, DDSInfo.mipPartOffsets, DDSInfo.mipPartCounts, uncompressedLength, newMipCount, newWidth, newHeight));
                            newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                            newTex.AddRange(DDSInfo.compressedDDS);

                            return(newTex.ToArray());
                        }
                        else
                        {
                            br.BaseStream.Seek(128, SeekOrigin.Begin);
                            newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                            newTex.AddRange(br.ReadBytes(uncompressedLength));

                            return(newTex.ToArray());
                        }
                    }
                    else
                    {
                        throw new Exception($"Incorrect file type. Expected: {xivTex.TextureFormat}  Given: {textureType}");
                    }
                }
            }
            else
            {
                throw new IOException($"Could not find file: {ddsFileDirectory.FullName}");
            }
        }
Exemplo n.º 11
0
        public async Task <int> TexBMPImporter(XivTex xivTex, IItem item, DirectoryInfo bmpFileDirectory, string source)
        {
            var offset = 0;

            var modding = new Modding(_gameDirectory);

            if (File.Exists(bmpFileDirectory.FullName))
            {
                // Check if the texture being imported has been imported before
                var modEntry = await modding.TryGetModEntry(xivTex.TextureTypeAndPath.Path);

                var ddsContainer = new DDSContainer();
                CompressionFormat compressionFormat;

                switch (xivTex.TextureFormat)
                {
                case XivTexFormat.DXT1:
                    compressionFormat = CompressionFormat.BC1;
                    break;

                case XivTexFormat.DXT5:
                    compressionFormat = CompressionFormat.BC3;
                    break;

                case XivTexFormat.A8R8G8B8:
                    compressionFormat = CompressionFormat.BGRA;
                    break;

                default:
                    throw new Exception($"Format {xivTex.TextureFormat} is not currently supported for BMP import\n\nPlease use the DDS import option instead.");
                }

                using (var surface = Surface.LoadFromFile(bmpFileDirectory.FullName))
                {
                    surface.FlipVertically();

                    using (var compressor = new Compressor())
                    {
                        compressor.Input.GenerateMipmaps = true;
                        compressor.Input.SetData(surface);
                        compressor.Compression.Format = compressionFormat;
                        compressor.Compression.SetBGRAPixelFormat();

                        compressor.Process(out ddsContainer);
                    }
                }

                using (var ddsMemoryStream = new MemoryStream())
                {
                    ddsContainer.Write(ddsMemoryStream, DDSFlags.None);

                    using (var br = new BinaryReader(ddsMemoryStream))
                    {
                        br.BaseStream.Seek(12, SeekOrigin.Begin);

                        var newHeight = br.ReadInt32();
                        var newWidth  = br.ReadInt32();
                        br.ReadBytes(8);
                        var newMipCount = br.ReadInt32();

                        if (newHeight % 2 != 0 || newWidth % 2 != 0)
                        {
                            throw new Exception("Resolution must be a multiple of 2");
                        }

                        br.BaseStream.Seek(80, SeekOrigin.Begin);

                        var          textureFlags = br.ReadInt32();
                        var          texType      = br.ReadInt32();
                        XivTexFormat textureType;

                        if (DDSType.ContainsKey(texType))
                        {
                            textureType = DDSType[texType];
                        }
                        else
                        {
                            throw new Exception($"DDS Type ({texType}) not recognized.");
                        }

                        switch (textureFlags)
                        {
                        case 2 when textureType == XivTexFormat.A8R8G8B8:
                            textureType = XivTexFormat.A8;
                            break;

                        case 65 when textureType == XivTexFormat.A8R8G8B8:
                            var bpp = br.ReadInt32();
                            if (bpp == 32)
                            {
                                textureType = XivTexFormat.A8R8G8B8;
                            }
                            else
                            {
                                var red = br.ReadInt32();

                                switch (red)
                                {
                                case 31744:
                                    textureType = XivTexFormat.A1R5G5B5;
                                    break;

                                case 3840:
                                    textureType = XivTexFormat.A4R4G4B4;
                                    break;
                                }
                            }

                            break;
                        }

                        if (textureType == xivTex.TextureFormat)
                        {
                            var uncompressedLength = ddsMemoryStream.Length;
                            var newTex             = new List <byte>();

                            if (!xivTex.TextureTypeAndPath.Path.Contains(".atex"))
                            {
                                var DDSInfo = await DDS.ReadDDS(br, xivTex, newWidth, newHeight, newMipCount);

                                newTex.AddRange(_dat.MakeType4DatHeader(xivTex, DDSInfo.mipPartOffsets, DDSInfo.mipPartCounts, (int)uncompressedLength, newMipCount, newWidth, newHeight));
                                newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                                newTex.AddRange(DDSInfo.compressedDDS);

                                offset = await _dat.WriteToDat(newTex, modEntry, xivTex.TextureTypeAndPath.Path,
                                                               item.ItemCategory, item.Name, xivTex.TextureTypeAndPath.DataFile, source, 4);
                            }
                            else
                            {
                                br.BaseStream.Seek(128, SeekOrigin.Begin);
                                newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                                newTex.AddRange(br.ReadBytes((int)uncompressedLength));

                                offset = await _dat.ImportType2Data(newTex.ToArray(), item.Name, xivTex.TextureTypeAndPath.Path,
                                                                    item.ItemCategory, source);
                            }
                        }
                        else
                        {
                            throw new Exception($"Incorrect file type. Expected: {xivTex.TextureFormat}  Given: {textureType}");
                        }
                    }
                }

                ddsContainer.Dispose();
            }
            else
            {
                throw new IOException($"Could not find file: {bmpFileDirectory.FullName}");
            }

            return(offset);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Converts a DDS file into a TEX file then imports it
        /// </summary>
        /// <param name="xivTex">The texture data</param>
        /// <param name="item">The item who's texture we are importing</param>
        /// <param name="ddsFileDirectory">The directory of the dds file being imported</param>
        /// <returns>The offset to the new imported data</returns>
        public async Task <int> TexDDSImporter(XivTex xivTex, IItem item, DirectoryInfo ddsFileDirectory, string source)
        {
            var offset = 0;

            var modding = new Modding(_gameDirectory);

            if (File.Exists(ddsFileDirectory.FullName))
            {
                // Check if the texture being imported has been imported before
                var modEntry = await modding.TryGetModEntry(xivTex.TextureTypeAndPath.Path);

                using (var br = new BinaryReader(File.OpenRead(ddsFileDirectory.FullName)))
                {
                    br.BaseStream.Seek(12, SeekOrigin.Begin);

                    var newHeight = br.ReadInt32();
                    var newWidth  = br.ReadInt32();
                    br.ReadBytes(8);
                    var newMipCount = br.ReadInt32();

                    if (newHeight % 2 != 0 || newWidth % 2 != 0)
                    {
                        throw new Exception("Resolution must be a multiple of 2");
                    }

                    br.BaseStream.Seek(80, SeekOrigin.Begin);

                    var          textureFlags = br.ReadInt32();
                    var          texType      = br.ReadInt32();
                    XivTexFormat textureType;

                    if (DDSType.ContainsKey(texType))
                    {
                        textureType = DDSType[texType];
                    }
                    else
                    {
                        throw new Exception($"DDS Type ({texType}) not recognized.");
                    }

                    switch (textureFlags)
                    {
                    case 2 when textureType == XivTexFormat.A8R8G8B8:
                        textureType = XivTexFormat.A8;
                        break;

                    case 65 when textureType == XivTexFormat.A8R8G8B8:
                        var bpp = br.ReadInt32();
                        if (bpp == 32)
                        {
                            textureType = XivTexFormat.A8R8G8B8;
                        }
                        else
                        {
                            var red = br.ReadInt32();

                            switch (red)
                            {
                            case 31744:
                                textureType = XivTexFormat.A1R5G5B5;
                                break;

                            case 3840:
                                textureType = XivTexFormat.A4R4G4B4;
                                break;
                            }
                        }

                        break;
                    }

                    if (textureType == xivTex.TextureFormat)
                    {
                        var uncompressedLength = (int)new FileInfo(ddsFileDirectory.FullName).Length - 128;
                        var newTex             = new List <byte>();

                        if (!xivTex.TextureTypeAndPath.Path.Contains(".atex"))
                        {
                            var DDSInfo = await DDS.ReadDDS(br, xivTex, newWidth, newHeight, newMipCount);

                            newTex.AddRange(_dat.MakeType4DatHeader(xivTex, DDSInfo.mipPartOffsets, DDSInfo.mipPartCounts, uncompressedLength, newMipCount, newWidth, newHeight));
                            newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                            newTex.AddRange(DDSInfo.compressedDDS);

                            offset = await _dat.WriteToDat(newTex, modEntry, xivTex.TextureTypeAndPath.Path,
                                                           item.ItemCategory, item.Name, xivTex.TextureTypeAndPath.DataFile, source, 4);
                        }
                        else
                        {
                            br.BaseStream.Seek(128, SeekOrigin.Begin);
                            newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                            newTex.AddRange(br.ReadBytes(uncompressedLength));

                            offset = await _dat.ImportType2Data(newTex.ToArray(), item.Name, xivTex.TextureTypeAndPath.Path,
                                                                item.ItemCategory, source);
                        }
                    }
                    else
                    {
                        throw new Exception($"Incorrect file type. Expected: {xivTex.TextureFormat}  Given: {textureType}");
                    }
                }
            }
            else
            {
                throw new IOException($"Could not find file: {ddsFileDirectory.FullName}");
            }

            return(offset);
        }
Exemplo n.º 13
0
        public async Task <int> TexBMPImporter(XivTex xivTex, IItem item, DirectoryInfo bmpFileDirectory, string source)
        {
            var offset = 0;

            var modding = new Modding(_gameDirectory);

            if (File.Exists(bmpFileDirectory.FullName))
            {
                // Check if the texture being imported has been imported before
                var modEntry = await modding.TryGetModEntry(xivTex.TextureTypeAndPath.Path);

                using (var magickImage = new MagickImage(bmpFileDirectory.FullName))
                {
                    switch (xivTex.TextureFormat)
                    {
                    case XivTexFormat.DXT1:
                        magickImage.Format = MagickFormat.Dxt1;
                        break;

                    case XivTexFormat.DXT5:
                        magickImage.Format = MagickFormat.Dxt5;
                        break;

                    case XivTexFormat.A8R8G8B8:
                        magickImage.Format = MagickFormat.Dds;
                        magickImage.Settings.SetDefines(new DdsWriteDefines
                        {
                            Compression = DdsCompression.None
                        });
                        break;

                    default:
                        throw new Exception($"Format {xivTex.TextureFormat} is not currently supported for BMP import\n\nPlease use the DDS import option instead.");
                    }

                    var data = magickImage.ToByteArray();

                    using (var br = new BinaryReader(new MemoryStream(data)))
                    {
                        br.BaseStream.Seek(12, SeekOrigin.Begin);

                        var newHeight = br.ReadInt32();
                        var newWidth  = br.ReadInt32();
                        br.ReadBytes(8);
                        var newMipCount = br.ReadInt32();

                        if (newHeight % 2 != 0 || newWidth % 2 != 0)
                        {
                            throw new Exception("Resolution must be a multiple of 2");
                        }

                        br.BaseStream.Seek(80, SeekOrigin.Begin);

                        var          textureFlags = br.ReadInt32();
                        var          texType      = br.ReadInt32();
                        XivTexFormat textureType;

                        if (DDSType.ContainsKey(texType))
                        {
                            textureType = DDSType[texType];
                        }
                        else
                        {
                            throw new Exception($"DDS Type ({texType}) not recognized.");
                        }

                        switch (textureFlags)
                        {
                        case 2 when textureType == XivTexFormat.A8R8G8B8:
                            textureType = XivTexFormat.A8;
                            break;

                        case 65 when textureType == XivTexFormat.A8R8G8B8:
                            var bpp = br.ReadInt32();
                            if (bpp == 32)
                            {
                                textureType = XivTexFormat.A8R8G8B8;
                            }
                            else
                            {
                                var red = br.ReadInt32();

                                switch (red)
                                {
                                case 31744:
                                    textureType = XivTexFormat.A1R5G5B5;
                                    break;

                                case 3840:
                                    textureType = XivTexFormat.A4R4G4B4;
                                    break;
                                }
                            }

                            break;
                        }

                        if (textureType == xivTex.TextureFormat)
                        {
                            var uncompressedLength = data.Length;
                            var newTex             = new List <byte>();

                            if (!xivTex.TextureTypeAndPath.Path.Contains(".atex"))
                            {
                                var DDSInfo = await DDS.ReadDDS(br, xivTex, newWidth, newHeight, newMipCount);

                                newTex.AddRange(_dat.MakeType4DatHeader(xivTex, DDSInfo.mipPartOffsets, DDSInfo.mipPartCounts, uncompressedLength, newMipCount, newWidth, newHeight));
                                newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                                newTex.AddRange(DDSInfo.compressedDDS);

                                offset = await _dat.WriteToDat(newTex, modEntry, xivTex.TextureTypeAndPath.Path,
                                                               item.ItemCategory, item.Name, xivTex.TextureTypeAndPath.DataFile, source, 4);
                            }
                            else
                            {
                                br.BaseStream.Seek(128, SeekOrigin.Begin);
                                newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                                newTex.AddRange(br.ReadBytes(uncompressedLength));

                                offset = await _dat.ImportType2Data(newTex.ToArray(), item.Name, xivTex.TextureTypeAndPath.Path,
                                                                    item.ItemCategory, source);
                            }
                        }
                        else
                        {
                            throw new Exception($"Incorrect file type. Expected: {xivTex.TextureFormat}  Given: {textureType}");
                        }
                    }
                }
            }
            else
            {
                throw new IOException($"Could not find file: {bmpFileDirectory.FullName}");
            }

            return(offset);
        }
Exemplo n.º 14
0
        /// <summary>
        /// Creates the header for the texture info from the data to be imported.
        /// </summary>
        /// <param name="xivTex">Data for the currently displayed texture.</param>
        /// <param name="newWidth">The width of the DDS texture to be imported.</param>
        /// <param name="newHeight">The height of the DDS texture to be imported.</param>
        /// <param name="newMipCount">The number of mipmaps the DDS texture to be imported contains.</param>
        /// <returns>The created header data.</returns>
        private static List <byte> MakeTextureInfoHeader(XivTex xivTex, int newWidth, int newHeight, int newMipCount)
        {
            var headerData = new List <byte>();

            headerData.AddRange(BitConverter.GetBytes((short)0));
            headerData.AddRange(BitConverter.GetBytes((short)128));
            headerData.AddRange(BitConverter.GetBytes(short.Parse(xivTex.TextureFormat.GetTexFormatCode())));
            headerData.AddRange(BitConverter.GetBytes((short)0));
            headerData.AddRange(BitConverter.GetBytes((short)newWidth));
            headerData.AddRange(BitConverter.GetBytes((short)newHeight));
            headerData.AddRange(BitConverter.GetBytes((short)1));
            headerData.AddRange(BitConverter.GetBytes((short)newMipCount));


            headerData.AddRange(BitConverter.GetBytes(0));
            headerData.AddRange(BitConverter.GetBytes(1));
            headerData.AddRange(BitConverter.GetBytes(2));

            int mipLength;

            switch (xivTex.TextureFormat)
            {
            case XivTexFormat.DXT1:
                mipLength = (newWidth * newHeight) / 2;
                break;

            case XivTexFormat.DXT5:
            case XivTexFormat.A8:
                mipLength = newWidth * newHeight;
                break;

            case XivTexFormat.A1R5G5B5:
            case XivTexFormat.A4R4G4B4:
                mipLength = (newWidth * newHeight) * 2;
                break;

            case XivTexFormat.L8:
            case XivTexFormat.A8R8G8B8:
            case XivTexFormat.X8R8G8B8:
            case XivTexFormat.R32F:
            case XivTexFormat.G16R16F:
            case XivTexFormat.G32R32F:
            case XivTexFormat.A16B16G16R16F:
            case XivTexFormat.A32B32G32R32F:
            case XivTexFormat.DXT3:
            case XivTexFormat.D16:
            default:
                mipLength = (newWidth * newHeight) * 4;
                break;
            }

            var combinedLength = 80;

            for (var i = 0; i < newMipCount; i++)
            {
                headerData.AddRange(BitConverter.GetBytes(combinedLength));
                combinedLength = combinedLength + mipLength;

                if (mipLength > 16)
                {
                    mipLength = mipLength / 4;
                }
                else
                {
                    mipLength = 16;
                }
            }

            var padding = 80 - headerData.Count;

            headerData.AddRange(new byte[padding]);

            return(headerData);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Reads and parses data from the DDS file to be imported.
        /// </summary>
        /// <param name="br">The currently active BinaryReader.</param>
        /// <param name="xivTex">The Texture data.</param>
        /// <param name="newWidth">The width of the DDS texture to be imported.</param>
        /// <param name="newHeight">The height of the DDS texture to be imported.</param>
        /// <param name="newMipCount">The number of mipmaps the DDS texture to be imported contains.</param>
        /// <returns>A tuple containing the compressed DDS data, a list of offsets to the mipmap parts, a list with the number of parts per mipmap.</returns>
        public static (List <byte> compressedDDS, List <short> mipPartOffsets, List <short> mipPartCounts) ReadDDS(BinaryReader br, XivTex xivTex, int newWidth, int newHeight, int newMipCount)
        {
            var compressedDDS  = new List <byte>();
            var mipPartOffsets = new List <short>();
            var mipPartCount   = new List <short>();

            int mipLength;

            switch (xivTex.TextureFormat)
            {
            case XivTexFormat.DXT1:
                mipLength = (newWidth * newHeight) / 2;
                break;

            case XivTexFormat.DXT5:
            case XivTexFormat.A8:
                mipLength = newWidth * newHeight;
                break;

            case XivTexFormat.A1R5G5B5:
            case XivTexFormat.A4R4G4B4:
                mipLength = (newWidth * newHeight) * 2;
                break;

            case XivTexFormat.L8:
            case XivTexFormat.A8R8G8B8:
            case XivTexFormat.X8R8G8B8:
            case XivTexFormat.R32F:
            case XivTexFormat.G16R16F:
            case XivTexFormat.G32R32F:
            case XivTexFormat.A16B16G16R16F:
            case XivTexFormat.A32B32G32R32F:
            case XivTexFormat.DXT3:
            case XivTexFormat.D16:
            default:
                mipLength = (newWidth * newHeight) * 4;
                break;
            }

            br.BaseStream.Seek(128, SeekOrigin.Begin);

            for (var i = 0; i < newMipCount; i++)
            {
                var mipParts = (int)Math.Ceiling(mipLength / 16000f);
                mipPartCount.Add((short)mipParts);

                if (mipParts > 1)
                {
                    for (var j = 0; j < mipParts; j++)
                    {
                        int uncompLength;
                        var comp = true;

                        if (j == mipParts - 1)
                        {
                            uncompLength = mipLength % 16000;
                        }
                        else
                        {
                            uncompLength = 16000;
                        }

                        var uncompBytes = br.ReadBytes(uncompLength);
                        var compressed  = IOUtil.Compressor(uncompBytes);

                        if (compressed.Length > uncompLength)
                        {
                            compressed = uncompBytes;
                            comp       = false;
                        }

                        compressedDDS.AddRange(BitConverter.GetBytes(16));
                        compressedDDS.AddRange(BitConverter.GetBytes(0));

                        compressedDDS.AddRange(!comp
                            ? BitConverter.GetBytes(32000)
                            : BitConverter.GetBytes(compressed.Length));

                        compressedDDS.AddRange(BitConverter.GetBytes(uncompLength));
                        compressedDDS.AddRange(compressed);

                        var padding = 128 - (compressed.Length % 128);

                        compressedDDS.AddRange(new byte[padding]);

                        mipPartOffsets.Add((short)(compressed.Length + padding + 16));
                    }
                }
                else
                {
                    int uncompLength;
                    var comp = true;

                    if (mipLength != 16000)
                    {
                        uncompLength = mipLength % 16000;
                    }
                    else
                    {
                        uncompLength = 16000;
                    }

                    var uncompBytes = br.ReadBytes(uncompLength);
                    var compressed  = IOUtil.Compressor(uncompBytes);

                    if (compressed.Length > uncompLength)
                    {
                        compressed = uncompBytes;
                        comp       = false;
                    }

                    compressedDDS.AddRange(BitConverter.GetBytes(16));
                    compressedDDS.AddRange(BitConverter.GetBytes(0));

                    compressedDDS.AddRange(!comp
                        ? BitConverter.GetBytes(32000)
                        : BitConverter.GetBytes(compressed.Length));

                    compressedDDS.AddRange(BitConverter.GetBytes(uncompLength));
                    compressedDDS.AddRange(compressed);

                    var padding = 128 - (compressed.Length % 128);

                    compressedDDS.AddRange(new byte[padding]);

                    mipPartOffsets.Add((short)(compressed.Length + padding + 16));
                }

                if (mipLength > 32)
                {
                    mipLength = mipLength / 4;
                }
                else
                {
                    mipLength = 8;
                }
            }

            return(compressedDDS, mipPartOffsets, mipPartCount);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Gets the data for Type 4 (Texture) files.
        /// </summary>
        /// <remarks>
        /// Type 4 files are used for Textures
        /// </remarks>
        /// <param name="offset">Offset to the texture data.</param>
        /// <param name="dataFile">The data file that contains the data.</param>
        /// <param name="xivTex">The XivTex container to fill</param>
        public void GetType4Data(int offset, XivDataFile dataFile, XivTex xivTex)
        {
            var decompressedData = new List <byte>();

            // This formula is used to obtain the dat number in which the offset is located
            var datNum = ((offset / 8) & 0x0F) / 2;

            offset = OffsetCorrection(datNum, offset);

            var datPath = _gameDirectory + "\\" + dataFile.GetDataFileName() + DatExtension + datNum;

            using (var br = new BinaryReader(File.OpenRead(datPath)))
            {
                br.BaseStream.Seek(offset, SeekOrigin.Begin);

                var headerLength         = br.ReadInt32();
                var fileType             = br.ReadInt32();
                var uncompressedFileSize = br.ReadInt32();
                br.ReadBytes(8);
                xivTex.MipMapCount = br.ReadInt32();

                var endOfHeader      = offset + headerLength;
                var mipMapInfoOffset = offset + 24;

                br.BaseStream.Seek(endOfHeader + 4, SeekOrigin.Begin);

                xivTex.TextureFormat = TextureTypeDictionary[br.ReadInt32()];
                xivTex.Width         = br.ReadInt16();
                xivTex.Heigth        = br.ReadInt16();

                for (int i = 0, j = 0; i < xivTex.MipMapCount; i++)
                {
                    br.BaseStream.Seek(mipMapInfoOffset + j, SeekOrigin.Begin);

                    var offsetFromHeaderEnd = br.ReadInt32();
                    var mipMapLength        = br.ReadInt32();
                    var mipMapSize          = br.ReadInt32();
                    var mipMapStart         = br.ReadInt32();
                    var mipMapParts         = br.ReadInt32();

                    var mipMapPartOffset = endOfHeader + offsetFromHeaderEnd;

                    br.BaseStream.Seek(mipMapPartOffset, SeekOrigin.Begin);

                    br.ReadBytes(8);
                    var compressedSize   = br.ReadInt32();
                    var uncompressedSize = br.ReadInt32();

                    if (mipMapParts > 1)
                    {
                        var compressedData = br.ReadBytes(compressedSize);

                        var decompressedPartData = IOUtil.Decompressor(compressedData, uncompressedSize);

                        decompressedData.AddRange(decompressedPartData);

                        for (var k = 1; k < mipMapParts; k++)
                        {
                            var check = br.ReadByte();
                            while (check != 0x10)
                            {
                                check = br.ReadByte();
                            }

                            br.ReadBytes(7);
                            compressedSize   = br.ReadInt32();
                            uncompressedSize = br.ReadInt32();

                            // When the compressed size of a data block shows 32000, it is uncompressed.
                            if (compressedSize != 32000)
                            {
                                compressedData       = br.ReadBytes(compressedSize);
                                decompressedPartData = IOUtil.Decompressor(compressedData, uncompressedSize);

                                decompressedData.AddRange(decompressedPartData);
                            }
                            else
                            {
                                decompressedPartData = br.ReadBytes(uncompressedSize);
                                decompressedData.AddRange(decompressedPartData);
                            }
                        }
                    }
                    else
                    {
                        // When the compressed size of a data block shows 32000, it is uncompressed.
                        if (compressedSize != 32000)
                        {
                            var compressedData = br.ReadBytes(compressedSize);

                            var uncompressedData = IOUtil.Decompressor(compressedData, uncompressedSize);

                            decompressedData.AddRange(uncompressedData);
                        }
                        else
                        {
                            var decompressedPartData = br.ReadBytes(uncompressedSize);
                            decompressedData.AddRange(decompressedPartData);
                        }
                    }
                    j = j + 20;
                }

                if (decompressedData.Count >= uncompressedFileSize)
                {
                    return;
                }

                var difference = uncompressedFileSize - decompressedData.Count;
                var padding    = new byte[difference];
                Array.Clear(padding, 0, difference);
                decompressedData.AddRange(padding);
            }

            xivTex.TexData = decompressedData.ToArray();
        }
Exemplo n.º 17
0
        /// <summary>
        /// Converts a DDS file into a TEX file then imports it
        /// </summary>
        /// <param name="xivTex">The texture data</param>
        /// <param name="item">The item who's texture we are importing</param>
        /// <param name="ddsFileDirectory">The directory of the dds file being imported</param>
        /// <returns>The offset to the new imported data</returns>
        public long TexDDSImporter(XivTex xivTex, IItem item, DirectoryInfo ddsFileDirectory)
        {
            int     lineNum = 0, offset = 0;
            var     inModList = false;
            ModInfo modInfo   = null;

            var dat = new Dat(_gameDirectory);

            if (File.Exists(ddsFileDirectory.FullName))
            {
                // Check if the texture being imported has been imported before
                using (var sr = new StreamReader(_modListDirectory.FullName))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        modInfo = JsonConvert.DeserializeObject <ModInfo>(line);
                        if (modInfo.fullPath.Equals(xivTex.TextureTypeAndPath.Path))
                        {
                            inModList = true;
                            break;
                        }
                        lineNum++;
                    }
                }

                using (var br = new BinaryReader(File.OpenRead(ddsFileDirectory.FullName)))
                {
                    br.BaseStream.Seek(12, SeekOrigin.Begin);

                    var newHeight = br.ReadInt32();
                    var newWidth  = br.ReadInt32();
                    br.ReadBytes(8);
                    var newMipCount = br.ReadInt32();

                    if (newHeight % 2 != 0 || newWidth % 2 != 0)
                    {
                        throw new Exception("Resolution must be a multiple of 2");
                    }

                    br.BaseStream.Seek(80, SeekOrigin.Begin);

                    var          textureFlags = br.ReadInt32();
                    var          texType      = br.ReadInt32();
                    XivTexFormat textureType;

                    if (DDSType.ContainsKey(texType))
                    {
                        textureType = DDSType[texType];
                    }
                    else
                    {
                        throw new Exception($"DDS Type ({texType}) not recognized.");
                    }

                    switch (textureFlags)
                    {
                    case 2 when textureType == XivTexFormat.A8R8G8B8:
                        textureType = XivTexFormat.A8;
                        break;

                    case 65 when textureType == XivTexFormat.A8R8G8B8:
                        var bpp = br.ReadInt32();
                        if (bpp == 32)
                        {
                            textureType = XivTexFormat.A8R8G8B8;
                        }
                        else
                        {
                            var red = br.ReadInt32();

                            switch (red)
                            {
                            case 31744:
                                textureType = XivTexFormat.A1R5G5B5;
                                break;

                            case 3840:
                                textureType = XivTexFormat.A4R4G4B4;
                                break;
                            }
                        }

                        break;
                    }

                    if (textureType == xivTex.TextureFormat)
                    {
                        var newTex = new List <byte>();

                        var uncompressedLength = (int)new FileInfo(ddsFileDirectory.FullName).Length - 128;

                        var DDSInfo = DDS.ReadDDS(br, xivTex, newWidth, newHeight, newMipCount);

                        newTex.AddRange(dat.MakeType4DatHeader(xivTex, DDSInfo.mipPartOffsets, DDSInfo.mipPartCounts, uncompressedLength, newMipCount, newWidth, newHeight));
                        newTex.AddRange(MakeTextureInfoHeader(xivTex, newWidth, newHeight, newMipCount));
                        newTex.AddRange(DDSInfo.compressedDDS);

                        offset = dat.WriteToDat(newTex, modInfo, inModList, xivTex.TextureTypeAndPath.Path,
                                                item.ItemCategory, item.Name, lineNum, xivTex.TextureTypeAndPath.DataFile);
                    }
                    else
                    {
                        throw new Exception($"Incorrect file type. Expected: {xivTex.TextureFormat}  Given: {textureType}");
                    }
                }
            }
            else
            {
                throw new IOException($"Could not find file: {ddsFileDirectory.FullName}");
            }

            return(offset);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Creates the DDS header for given texture data.
        /// <see cref="https://msdn.microsoft.com/en-us/library/windows/desktop/bb943982(v=vs.85).aspx"/>
        /// </summary>
        /// <returns>Byte array containing DDS header</returns>
        private static byte[] CreateDDSHeader(XivTex xivTex)
        {
            uint dwPitchOrLinearSize, pfFlags, dwFourCC;
            var  header = new List <byte>();

            // DDS header magic number
            const uint dwMagic = 0x20534444;

            header.AddRange(BitConverter.GetBytes(dwMagic));

            // Size of structure. This member must be set to 124.
            const uint dwSize = 124;

            header.AddRange(BitConverter.GetBytes(dwSize));

            // Flags to indicate which members contain valid data.
            uint dwFlags = 528391;

            if (xivTex.Layers > 1)
            {
                dwFlags = 0x00000004;
            }
            header.AddRange(BitConverter.GetBytes(dwFlags));

            // Surface height (in pixels).
            var dwHeight = (uint)xivTex.Height;

            header.AddRange(BitConverter.GetBytes(dwHeight));

            // Surface width (in pixels).
            var dwWidth = (uint)xivTex.Width;

            header.AddRange(BitConverter.GetBytes(dwWidth));

            // The pitch or number of bytes per scan line in an uncompressed texture; the total number of bytes in the top level texture for a compressed texture.
            if (xivTex.TextureFormat == XivTexFormat.A16B16G16R16F)
            {
                dwPitchOrLinearSize = 512;
            }
            else if (xivTex.TextureFormat == XivTexFormat.A8R8G8B8)
            {
                dwPitchOrLinearSize = (dwHeight * dwWidth) * 4;
            }
            else if (xivTex.TextureFormat == XivTexFormat.DXT1)
            {
                dwPitchOrLinearSize = (dwHeight * dwWidth) / 2;
            }
            else if (xivTex.TextureFormat == XivTexFormat.A4R4G4B4 || xivTex.TextureFormat == XivTexFormat.A1R5G5B5)
            {
                dwPitchOrLinearSize = (dwHeight * dwWidth) * 2;
            }
            else
            {
                dwPitchOrLinearSize = dwHeight * dwWidth;
            }
            header.AddRange(BitConverter.GetBytes(dwPitchOrLinearSize));


            // Depth of a volume texture (in pixels), otherwise unused.
            const uint dwDepth = 0;

            header.AddRange(BitConverter.GetBytes(dwDepth));

            // Number of mipmap levels, otherwise unused.
            var dwMipMapCount = (uint)xivTex.MipMapCount;

            header.AddRange(BitConverter.GetBytes(dwMipMapCount));

            // Unused.
            var dwReserved1 = new byte[44];

            Array.Clear(dwReserved1, 0, 44);
            header.AddRange(dwReserved1);

            // DDS_PIXELFORMAT start

            // Structure size; set to 32 (bytes).
            const uint pfSize = 32;

            header.AddRange(BitConverter.GetBytes(pfSize));

            switch (xivTex.TextureFormat)
            {
            // Values which indicate what type of data is in the surface.
            case XivTexFormat.A8R8G8B8:
            case XivTexFormat.A4R4G4B4:
            case XivTexFormat.A1R5G5B5:
                pfFlags = 65;
                break;

            case XivTexFormat.A8:
                pfFlags = 2;
                break;

            default:
                pfFlags = 4;
                break;
            }
            header.AddRange(BitConverter.GetBytes(pfFlags));

            switch (xivTex.TextureFormat)
            {
            // Four-character codes for specifying compressed or custom formats.
            case XivTexFormat.DXT1:
                dwFourCC = 0x31545844;
                break;

            case XivTexFormat.DXT5:
                dwFourCC = 0x35545844;
                break;

            case XivTexFormat.DXT3:
                dwFourCC = 0x33545844;
                break;

            case XivTexFormat.A16B16G16R16F:
                dwFourCC = 0x71;
                break;

            case XivTexFormat.A8R8G8B8:
            case XivTexFormat.A8:
            case XivTexFormat.A4R4G4B4:
            case XivTexFormat.A1R5G5B5:
                dwFourCC = 0;
                break;

            default:
                return(null);
            }

            if (xivTex.Layers > 1)
            {
                var bytes = System.Text.Encoding.UTF8.GetBytes("DX10");
                dwFourCC = BitConverter.ToUInt32(bytes, 0);
            }

            header.AddRange(BitConverter.GetBytes(dwFourCC));

            switch (xivTex.TextureFormat)
            {
            case XivTexFormat.A8R8G8B8:
            {
                // Number of bits in an RGB (possibly including alpha) format.
                const uint dwRGBBitCount = 32;
                header.AddRange(BitConverter.GetBytes(dwRGBBitCount));

                // Red (or lumiannce or Y) mask for reading color data.
                const uint dwRBitMask = 16711680;
                header.AddRange(BitConverter.GetBytes(dwRBitMask));

                // Green (or U) mask for reading color data.
                const uint dwGBitMask = 65280;
                header.AddRange(BitConverter.GetBytes(dwGBitMask));

                // Blue (or V) mask for reading color data.
                const uint dwBBitMask = 255;
                header.AddRange(BitConverter.GetBytes(dwBBitMask));

                // Alpha mask for reading alpha data.
                const uint dwABitMask = 4278190080;
                header.AddRange(BitConverter.GetBytes(dwABitMask));

                // DDS_PIXELFORMAT End

                // Specifies the complexity of the surfaces stored.
                const uint dwCaps = 4096;
                header.AddRange(BitConverter.GetBytes(dwCaps));

                // dwCaps2, dwCaps3, dwCaps4, dwReserved2.
                // Unused.
                var blank1 = new byte[16];
                header.AddRange(blank1);

                break;
            }

            case XivTexFormat.A8:
            {
                // Number of bits in an RGB (possibly including alpha) format.
                const uint dwRGBBitCount = 8;
                header.AddRange(BitConverter.GetBytes(dwRGBBitCount));

                // Red (or lumiannce or Y) mask for reading color data.
                const uint dwRBitMask = 0;
                header.AddRange(BitConverter.GetBytes(dwRBitMask));

                // Green (or U) mask for reading color data.
                const uint dwGBitMask = 0;
                header.AddRange(BitConverter.GetBytes(dwGBitMask));

                // Blue (or V) mask for reading color data.
                const uint dwBBitMask = 0;
                header.AddRange(BitConverter.GetBytes(dwBBitMask));

                // Alpha mask for reading alpha data.
                const uint dwABitMask = 255;
                header.AddRange(BitConverter.GetBytes(dwABitMask));

                // DDS_PIXELFORMAT End

                // Specifies the complexity of the surfaces stored.
                const uint dwCaps = 4096;
                header.AddRange(BitConverter.GetBytes(dwCaps));

                // dwCaps2, dwCaps3, dwCaps4, dwReserved2.
                // Unused.
                var blank1 = new byte[16];
                header.AddRange(blank1);
                break;
            }

            case XivTexFormat.A1R5G5B5:
            {
                // Number of bits in an RGB (possibly including alpha) format.
                const uint dwRGBBitCount = 16;
                header.AddRange(BitConverter.GetBytes(dwRGBBitCount));

                // Red (or lumiannce or Y) mask for reading color data.
                const uint dwRBitMask = 31744;
                header.AddRange(BitConverter.GetBytes(dwRBitMask));

                // Green (or U) mask for reading color data.
                const uint dwGBitMask = 992;
                header.AddRange(BitConverter.GetBytes(dwGBitMask));

                // Blue (or V) mask for reading color data.
                const uint dwBBitMask = 31;
                header.AddRange(BitConverter.GetBytes(dwBBitMask));

                // Alpha mask for reading alpha data.
                const uint dwABitMask = 32768;
                header.AddRange(BitConverter.GetBytes(dwABitMask));

                // DDS_PIXELFORMAT End

                // Specifies the complexity of the surfaces stored.
                const uint dwCaps = 4096;
                header.AddRange(BitConverter.GetBytes(dwCaps));

                // dwCaps2, dwCaps3, dwCaps4, dwReserved2.
                // Unused.
                var blank1 = new byte[16];
                header.AddRange(blank1);
                break;
            }

            case XivTexFormat.A4R4G4B4:
            {
                // Number of bits in an RGB (possibly including alpha) format.
                const uint dwRGBBitCount = 16;
                header.AddRange(BitConverter.GetBytes(dwRGBBitCount));

                // Red (or lumiannce or Y) mask for reading color data.
                const uint dwRBitMask = 3840;
                header.AddRange(BitConverter.GetBytes(dwRBitMask));

                // Green (or U) mask for reading color data.
                const uint dwGBitMask = 240;
                header.AddRange(BitConverter.GetBytes(dwGBitMask));

                // Blue (or V) mask for reading color data.
                const uint dwBBitMask = 15;
                header.AddRange(BitConverter.GetBytes(dwBBitMask));

                // Alpha mask for reading alpha data.
                const uint dwABitMask = 61440;
                header.AddRange(BitConverter.GetBytes(dwABitMask));

                // DDS_PIXELFORMAT End

                // Specifies the complexity of the surfaces stored.
                const uint dwCaps = 4096;
                header.AddRange(BitConverter.GetBytes(dwCaps));

                // dwCaps2, dwCaps3, dwCaps4, dwReserved2.
                // Unused.
                var blank1 = new byte[16];
                header.AddRange(blank1);
                break;
            }

            default:
            {
                // dwRGBBitCount, dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask, dwCaps, dwCaps2, dwCaps3, dwCaps4, dwReserved2.
                // Unused.
                var blank1 = new byte[40];
                header.AddRange(blank1);
                break;
            }
            }

            // Need to write DX10 header here.
            if (xivTex.Layers > 1)
            {
                // DXGI_FORMAT dxgiFormat
                uint dxgiFormat = 0;
                if (xivTex.TextureFormat == XivTexFormat.DXT1)
                {
                    dxgiFormat = (uint)DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM;
                }
                else if (xivTex.TextureFormat == XivTexFormat.DXT5)
                {
                    dxgiFormat = (uint)DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM;
                }
                else
                {
                    dxgiFormat = (uint)DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM;
                }
                header.AddRange(BitConverter.GetBytes(dxgiFormat));

                // D3D10_RESOURCE_DIMENSION resourceDimension
                header.AddRange(BitConverter.GetBytes((int)3));


                // UINT miscFlag
                header.AddRange(BitConverter.GetBytes((int)0));

                // UINT arraySize
                header.AddRange(BitConverter.GetBytes(xivTex.Layers));

                // UINT miscFlags2
                header.AddRange(BitConverter.GetBytes((int)0));
            }

            return(header.ToArray());
        }
Exemplo n.º 19
0
        /// <summary>
        /// Creates the header for the compressed texture data to be imported.
        /// </summary>
        /// <param name="xivTex">Data for the currently displayed texture.</param>
        /// <param name="mipPartOffsets">List of part offsets.</param>
        /// <param name="mipPartCount">List containing the amount of parts per mipmap.</param>
        /// <param name="uncompressedLength">Length of the uncompressed texture file.</param>
        /// <param name="newMipCount">The number of mipmaps the DDS texture to be imported contains.</param>
        /// <param name="newWidth">The width of the DDS texture to be imported.</param>
        /// <param name="newHeight">The height of the DDS texture to be imported.</param>
        /// <returns>The created header data.</returns>
        public byte[] MakeType4DatHeader(XivTex xivTex, List <short> mipPartOffsets, List <short> mipPartCount, int uncompressedLength, int newMipCount, int newWidth, int newHeight)
        {
            var headerData = new List <byte>();

            var headerSize    = 24 + (newMipCount * 20) + (mipPartOffsets.Count * 2);
            var headerPadding = 128 - (headerSize % 128);

            headerData.AddRange(BitConverter.GetBytes(headerSize + headerPadding));
            headerData.AddRange(BitConverter.GetBytes(4));
            headerData.AddRange(BitConverter.GetBytes(uncompressedLength));
            headerData.AddRange(BitConverter.GetBytes(0));
            headerData.AddRange(BitConverter.GetBytes(0));
            headerData.AddRange(BitConverter.GetBytes(newMipCount));


            var partIndex      = 0;
            var mipOffsetIndex = 80;
            var uncompMipSize  = newHeight * newWidth;

            switch (xivTex.TextureFormat)
            {
            case XivTexFormat.DXT1:
                uncompMipSize = (newWidth * newHeight) / 2;
                break;

            case XivTexFormat.DXT5:
            case XivTexFormat.A8:
                uncompMipSize = newWidth * newHeight;
                break;

            case XivTexFormat.A1R5G5B5:
            case XivTexFormat.A4R4G4B4:
                uncompMipSize = (newWidth * newHeight) * 2;
                break;

            case XivTexFormat.L8:
            case XivTexFormat.A8R8G8B8:
            case XivTexFormat.X8R8G8B8:
            case XivTexFormat.R32F:
            case XivTexFormat.G16R16F:
            case XivTexFormat.G32R32F:
            case XivTexFormat.A16B16G16R16F:
            case XivTexFormat.A32B32G32R32F:
            case XivTexFormat.DXT3:
            case XivTexFormat.D16:
            default:
                uncompMipSize = (newWidth * newHeight) * 4;
                break;
            }

            for (var i = 0; i < newMipCount; i++)
            {
                headerData.AddRange(BitConverter.GetBytes(mipOffsetIndex));

                var paddedSize = 0;

                for (var j = 0; j < mipPartCount[i]; j++)
                {
                    paddedSize = paddedSize + mipPartOffsets[j + partIndex];
                }

                headerData.AddRange(BitConverter.GetBytes(paddedSize));

                headerData.AddRange(uncompMipSize > 16
                    ? BitConverter.GetBytes(uncompMipSize)
                    : BitConverter.GetBytes(16));

                uncompMipSize = uncompMipSize / 4;

                headerData.AddRange(BitConverter.GetBytes(partIndex));
                headerData.AddRange(BitConverter.GetBytes((int)mipPartCount[i]));

                partIndex      = partIndex + mipPartCount[i];
                mipOffsetIndex = mipOffsetIndex + paddedSize;
            }

            foreach (var part in mipPartOffsets)
            {
                headerData.AddRange(BitConverter.GetBytes(part));
            }

            headerData.AddRange(new byte[headerPadding]);

            return(headerData.ToArray());
        }
Exemplo n.º 20
0
        private async Task <TextureModel> MakeTextureModel(XivTex tex)
        {
            var layer = (int)Math.Floor(RowData[2][3] * 64);

            if (layer > 63 || layer < 0)
            {
                layer = 0;
            }
            var tileX     = (float)RowData[3][0];
            var tileY     = (float)RowData[3][3];
            var tileSkewX = (float)RowData[3][1];
            var tileSkewY = (float)RowData[3][2];

            var _tex = new Tex(XivCache.GameInfo.GameDirectory);
            var data = await _tex.GetImageData(tex, layer);

            var ogW = 32;
            var ogH = 32;
            var w   = 256;
            var h   = 256;

            Color4[] colors = new Color4[w * h];


            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    var nPixel = (y * w) + x;
                    //U = Dot Product ([u,v], [Red, Green])
                    float u = (float)x / (float)w;
                    float v = ((float)y) / (float)h;

                    // This is now the new U and V coordinates we want to map to.
                    var newU = SharpDX.Vector2.Dot(new SharpDX.Vector2(u, v), new SharpDX.Vector2(tileX, tileSkewX)) % 1.0f;
                    var newV = SharpDX.Vector2.Dot(new SharpDX.Vector2(u, v), new SharpDX.Vector2(tileSkewY, tileY)) % 1.0f;

                    var xPx = (int)(newU * ogW);
                    var yPx = (int)(newV * ogH);

                    xPx = xPx < 0 ? ogW - xPx : xPx;
                    yPx = yPx < 0 ? ogH - yPx : yPx;

                    xPx = xPx >= ogW ? 0 : xPx;
                    yPx = yPx >= ogH ? 0 : yPx;


                    var ogPixel      = (yPx * ogW) + xPx;
                    var ogDataOffset = ogPixel * 4;

                    colors[nPixel] = new Color4()
                    {
                        Red   = data[ogDataOffset] / 255.0f,
                        Green = data[ogDataOffset + 1] / 255.0f,
                        Blue  = data[ogDataOffset + 2] / 255.0f,
                        Alpha = 1.0f,
                    };
                }
            }

            var tm = new TextureModel(colors, w, h);

            return(tm);
        }