예제 #1
0
        /// <summary>
        ///     Saves the changes to a Bayonetta *.idd file.
        /// </summary>
        /// <param name="Output">The output *.idd file</param>
        /// <param name="ModifiedContent">The changes to be written</param>
        public static void Save(Stream Output, IDDContent ModifiedContent)
        {
            EndianBinaryWriter Writer = new EndianBinaryWriter(Output, Endian.Big);

            for (int Index = 0; Index < ModifiedContent.Textures.Count; Index++)
            {
                IDDTexture Texture = ModifiedContent.Textures[Index];

                byte[] Data = Texture.TextureData;
                if (Texture.Platform == Console.Xbox360)
                {
                    Data = XTextureScramble(Data, Texture, true);
                    Data = XEndian16(Data);
                }

                Output.Seek(Texture.TextureOffset, SeekOrigin.Begin);
                Writer.Write(Data);

                foreach (IDDTextureElement Element in Texture.Elements)
                {
                    Output.Seek(Element.Offset, SeekOrigin.Begin);

                    Writer.Write((ushort)Element.Id);
                    Writer.Write((ushort)Index);
                    Writer.Write(Element.X1);
                    Writer.Write(Element.Y1);
                    Writer.Write(Element.X2);
                    Writer.Write(Element.Y2);
                }
            }

            Output.Close();
        }
예제 #2
0
        //This code was adapted from GTA XTD Viewer tool
        private static byte[] XTextureScramble(byte[] Data, IDDTexture Texture, bool ToLinear = false)
        {
            byte[] Output = new byte[Data.Length];

            int BlockSize  = 0;
            int TexelPitch = 0;

            if (Texture.Format == TextureFormat.DXT1)
            {
                BlockSize  = 4;
                TexelPitch = 8;
            }
            else
            {
                BlockSize  = 4;
                TexelPitch = 16;
            }

            int BlockWidth  = Texture.Resolution.Width / BlockSize;
            int BlockHeight = Texture.Resolution.Height / BlockSize;

            for (int j = 0; j < BlockHeight; j++)
            {
                for (int i = 0; i < BlockWidth; i++)
                {
                    int BlockOffset = j * BlockWidth + i;

                    int X = XGAddress2DTiledX(BlockOffset, BlockWidth, TexelPitch);
                    int Y = XGAddress2DTiledY(BlockOffset, BlockWidth, TexelPitch);

                    int SrcOffset = j * BlockWidth * TexelPitch + i * TexelPitch;
                    int DstOffset = Y * BlockWidth * TexelPitch + X * TexelPitch;

                    if (ToLinear)
                    {
                        Buffer.BlockCopy(Data, DstOffset, Output, SrcOffset, TexelPitch);
                    }
                    else
                    {
                        Buffer.BlockCopy(Data, SrcOffset, Output, DstOffset, TexelPitch);
                    }
                }
            }

            return(Output);
        }
예제 #3
0
        /// <summary>
        ///     Exports a IDD texture to a DDS file.
        /// </summary>
        /// <param name="Texture">The texture to be exported</param>
        /// <param name="OutFile">Output file full path with name and extension</param>
        public static void Export(IDDTexture Texture, string OutFile)
        {
            using (FileStream Output = new FileStream(OutFile, FileMode.Create))
            {
                BinaryWriter Writer = new BinaryWriter(Output);

                Writer.Write(0x20534444);  //DDS Signature
                Writer.Write(0x7cu);       //Header size (without the signature)
                Writer.Write(0x00021007u); //DDS Flags
                Writer.Write(Texture.Resolution.Height);
                Writer.Write(Texture.Resolution.Width);
                Writer.Write(0u);                      //Stride
                Writer.Write(0u);                      //BPP
                Writer.Write(1u);                      //Mipmaps
                Output.Seek(0x2c, SeekOrigin.Current); //Reserved space for future use
                Writer.Write((uint)0x20);              //PixelFormat structure size (32 bytes)
                Writer.Write(4u);                      //Pixel flags (4 = DXT compressed)

                switch (Texture.Format)
                {
                case TextureFormat.DXT1: Writer.Write(Encoding.ASCII.GetBytes("DXT1")); break;

                case TextureFormat.DXT3: Writer.Write(Encoding.ASCII.GetBytes("DXT3")); break;

                case TextureFormat.DXT5: Writer.Write(Encoding.ASCII.GetBytes("DXT5")); break;

                default: throw new Exception("Unsupported texture format!");
                }

                Output.Seek(20, SeekOrigin.Current);
                Writer.Write(0x400000u); //Caps 1
                Writer.Write(0u);        //Caps 2
                Writer.Write(0u);        //Unused stuff
                Writer.Write(0u);
                Writer.Write(0u);
                Writer.Write(Texture.TextureData);
            }
        }
예제 #4
0
        /// <summary>
        ///     Loads the textures of a Bayonetta *.idd file into a object.
        /// </summary>
        /// <param name="Input">The input Stream with the IDD data</param>
        /// <returns>The textures and mappings</returns>
        public static IDDContent Load(Stream Input)
        {
            IDDContent Output = new IDDContent();

            EndianBinaryReader Reader = new EndianBinaryReader(Input, Endian.Big);

            string Signature         = StringUtilities.ReadASCIIString(Input); //IDD
            uint   UsedSectionsCount = Reader.ReadUInt32();

            uint TEXOffset = 0;
            uint TUVOffset = 0;

            for (int i = 0; i < UsedSectionsCount; i++)
            {
                Input.Seek(8 + i * 8, SeekOrigin.Begin);

                uint Index  = Reader.ReadUInt32();
                uint Offset = Reader.ReadUInt32();

                switch (Index)
                {
                case 0: TEXOffset = Offset; break;

                case 1: TUVOffset = Offset; break;
                }
            }

            Input.Seek(TEXOffset + 4, SeekOrigin.Begin);
            if (Reader.ReadUInt32() == 0)
            {
                throw new Exception("This file doesn't contain any texture!");
            }
            Reader.ReadUInt32();
            uint BaseTextureOffset = TEXOffset + Reader.ReadUInt32();

            Input.Seek(BaseTextureOffset, SeekOrigin.Begin);

            uint WTBSignature = Reader.ReadUInt32();

            Reader.ReadUInt32();
            uint TexturesCount      = Reader.ReadUInt32();
            uint AddressTableOffset = Reader.ReadUInt32();
            uint LengthTableOffset  = Reader.ReadUInt32();

            Reader.ReadUInt32(); //Another ??? table offset

            for (int i = 0; i < TexturesCount; i++)
            {
                IDDTexture Texture = new IDDTexture();

                Input.Seek(BaseTextureOffset + AddressTableOffset + i * 4, SeekOrigin.Begin);
                Input.Seek(BaseTextureOffset + Reader.ReadUInt32(), SeekOrigin.Begin);

                if (Reader.ReadUInt32() == 3)
                {
                    //Xbox 360
                    uint Count = Reader.ReadUInt32();
                    Input.Seek(0xc, SeekOrigin.Current); //0x0
                    Reader.ReadUInt32();                 //0xFFFF0000
                    Reader.ReadUInt32();                 //0xFFFF0000
                    Reader.ReadUInt32();                 //0x81000002
                    uint TextureFormat     = Reader.ReadUInt32();
                    uint TextureDescriptor = Reader.ReadUInt32();
                    Reader.ReadUInt32(); //0xD10
                    uint Mipmaps        = ((Reader.ReadUInt32() >> 6) & 7) + 1;
                    uint OriginalLength = Reader.ReadUInt32();

                    int Width  = (int)(TextureDescriptor & 0x1fff) + 1;
                    int Height = (int)((TextureDescriptor >> 13) & 0x1fff) + 1;

                    switch (TextureFormat)
                    {
                    case 0x52: Texture.Format = Format.TextureFormat.DXT1; break;

                    case 0x53: Texture.Format = Format.TextureFormat.DXT3; break;

                    case 0x54: Texture.Format = Format.TextureFormat.DXT5; break;

                    default: throw new Exception(string.Format("Unsupported IDD X360 texture format 0x{0:X2}!", TextureFormat));
                    }
                    Texture.Platform      = Console.Xbox360;
                    Texture.Resolution    = new Size(Width, Height);
                    Texture.TextureOffset = (uint)Input.Position;

                    int Length = Width * Height;
                    if (Texture.Format == Format.TextureFormat.DXT1)
                    {
                        Length /= 2;
                    }
                    byte[] Data = new byte[Length];
                    Reader.Read(Data, 0, Data.Length);
                    Data = XEndian16(Data);
                    Data = XTextureScramble(Data, Texture, false);
                    Texture.TextureData = Data;
                }
                else
                {
                    //Playstation 3
                    uint   Length            = Reader.ReadUInt32();
                    uint   TextureCount      = Reader.ReadUInt32();
                    uint   Id                = Reader.ReadUInt32();
                    uint   TextureDataOffset = Reader.ReadUInt32();
                    uint   TextureDataLength = Reader.ReadUInt32();
                    byte   TextureFormat     = Reader.ReadByte();
                    byte   Mipmaps           = Reader.ReadByte();
                    byte   Dimension         = Reader.ReadByte();
                    byte   Cubemaps          = Reader.ReadByte();
                    uint   Remap             = Reader.ReadUInt32();
                    ushort Width             = Reader.ReadUInt16();
                    ushort Height            = Reader.ReadUInt16();
                    ushort Depth             = Reader.ReadUInt16();
                    ushort Pitch             = Reader.ReadUInt16();
                    ushort Location          = Reader.ReadUInt16();
                    uint   TextureOffset     = Reader.ReadUInt16();
                    Reader.Seek(8, SeekOrigin.Current);

                    bool IsSwizzle    = (TextureFormat & 0x20) == 0;
                    bool IsNormalized = (TextureFormat & 0x40) == 0;
                    TextureFormat = (byte)(TextureFormat & ~0x60);

                    switch (TextureFormat)
                    {
                    case 0x86: Texture.Format = Format.TextureFormat.DXT1; break;

                    case 0x87: Texture.Format = Format.TextureFormat.DXT3; break;

                    case 0x88: Texture.Format = Format.TextureFormat.DXT5; break;

                    default: throw new Exception(string.Format("Unsupported IDD PS3 texture format 0x{0:X2}!", TextureFormat));
                    }
                    Texture.Platform      = Console.Playstation3;
                    Texture.Resolution    = new Size(Width, Height);
                    Texture.TextureOffset = (uint)Input.Position;
                    Texture.TextureData   = new byte[Length];
                    Reader.Read(Texture.TextureData, 0, (int)Length);
                }

                //Texture Map stuff (needs optimization)
                Input.Seek(TUVOffset + 0xc, SeekOrigin.Begin);
                uint BaseMapOffset = TUVOffset + Reader.ReadUInt32();
                Input.Seek(BaseMapOffset, SeekOrigin.Begin);

                uint Entries = Reader.ReadUInt32();
                for (int j = 0; j < Entries; j++)
                {
                    Input.Seek(BaseMapOffset + 4 + j * 8, SeekOrigin.Begin);

                    ushort Offset     = Reader.ReadUInt16(); //???
                    ushort StartIndex = Reader.ReadUInt16();
                    ushort Count      = Reader.ReadUInt16();
                    Reader.ReadUInt16(); //???

                    long ElementOffset = BaseMapOffset + 4 + Entries * 8 + StartIndex * 0x14;
                    Input.Seek(ElementOffset, SeekOrigin.Begin);

                    for (int k = 0; k < Count; k++)
                    {
                        ushort ElementId    = Reader.ReadUInt16();
                        ushort TextureIndex = Reader.ReadUInt16();
                        float  X1           = Reader.ReadSingle();
                        float  Y1           = Reader.ReadSingle();
                        float  X2           = Reader.ReadSingle();
                        float  Y2           = Reader.ReadSingle();

                        if (TextureIndex == i)
                        {
                            IDDTextureElement Element = new IDDTextureElement();

                            Element.Offset = (uint)(ElementOffset + k * 0x14);
                            Element.Id     = ElementId;
                            Element.X1     = X1;
                            Element.Y1     = Y1;
                            Element.X2     = X2;
                            Element.Y2     = Y2;

                            Texture.Elements.Add(Element);
                        }
                    }
                }

                Output.Textures.Add(Texture);
            }

            Input.Close();
            return(Output);
        }