Beispiel #1
0
            internal Texture(BinaryReaderEx br, TPFPlatform platform, byte encoding)
            {
                int fileOffset = br.ReadInt32();
                int fileSize   = br.ReadInt32();

                Format  = br.ReadByte();
                Cubemap = br.ReadBoolean();
                Mipmaps = br.ReadByte();
                Flags1  = br.AssertByte(0, 1, 2, 3);

                int nameOffset = 0;

                if (platform == TPFPlatform.PC)
                {
                    Header     = null;
                    nameOffset = br.ReadInt32();
                    Flags2     = br.AssertInt32(0, 1);
                }
                else if (platform == TPFPlatform.PS3)
                {
                    Header        = new TexHeader();
                    Header.Width  = br.ReadInt16();
                    Header.Height = br.ReadInt16();
                    Header.Unk1   = br.ReadInt32();
                    Header.Unk2   = br.AssertInt32(0, 0xAAE4);
                    nameOffset    = br.ReadInt32();
                    Flags2        = br.AssertInt32(0, 1);
                }
                else if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                {
                    Header        = new TexHeader();
                    Header.Width  = br.ReadInt16();
                    Header.Height = br.ReadInt16();

                    Header.TextureCount = br.AssertByte(1, 6);
                    br.AssertByte(0);
                    br.AssertByte(0);
                    br.AssertByte(0);

                    Header.Unk2       = br.AssertInt32(0xD);
                    nameOffset        = br.ReadInt32();
                    Flags2            = br.AssertInt32(0, 1);
                    Header.DXGIFormat = br.ReadInt32();
                }

                Bytes = br.GetBytes(fileOffset, fileSize);
                if (Flags1 == 2 || Flags1 == 3)
                {
                    Bytes = DCX.Decompress(Bytes);
                }

                if (encoding == 1)
                {
                    Name = br.GetUTF16(nameOffset);
                }
                else if (encoding == 0 || encoding == 2)
                {
                    Name = br.GetShiftJIS(nameOffset);
                }
            }
Beispiel #2
0
 /// <summary>
 /// Creates an empty TPF configured for DS3.
 /// </summary>
 public TPF()
 {
     Textures = new List <Texture>();
     Platform = TPFPlatform.PC;
     Encoding = 1;
     Flag2    = 3;
 }
Beispiel #3
0
 public void ConvertPS3ToPC()
 {
     if (Platform != TPFPlatform.PS3)
     {
         return;
     }
     Platform = TPFPlatform.PC;
     foreach (Texture tex in Textures)
     {
         tex.ConsoleToPC(TPFPlatform.PS3);
     }
 }
Beispiel #4
0
 public void ConvertPS4ToPC()
 {
     if (Platform != TPFPlatform.PS4)
     {
         return;
     }
     Platform = TPFPlatform.PC;
     foreach (Texture tex in Textures)
     {
         tex.PS4ToPC();
     }
 }
Beispiel #5
0
            internal void Write(BinaryWriterEx bw, int index, TPFPlatform platform)
            {
                if (platform == TPFPlatform.PC)
                {
                    DDS dds = new DDS(Bytes);
                    // DDSCAPS2_CUBEMAP
                    Cubemap = (dds.dwCaps2 & 0x200) != 0;
                    Mipmaps = (byte)dds.dwMipMapCount;
                }

                bw.ReserveInt32($"FileData{index}");
                bw.ReserveInt32($"FileSize{index}");

                bw.WriteByte(Format);
                bw.WriteBoolean(Cubemap);
                bw.WriteByte(Mipmaps);
                bw.WriteByte(Flags1);

                if (platform == TPFPlatform.PC)
                {
                    bw.ReserveInt32($"FileName{index}");
                    bw.WriteInt32(Flags2);
                }
                else if (platform == TPFPlatform.PS3)
                {
                    bw.WriteInt16(Header.Width);
                    bw.WriteInt16(Header.Height);
                    bw.WriteInt32(Header.Unk1);
                    bw.WriteInt32(Header.Unk2);
                    bw.ReserveInt32($"FileName{index}");
                    bw.WriteInt32(Flags2);
                }
                else if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                {
                    bw.WriteInt16(Header.Width);
                    bw.WriteInt16(Header.Height);

                    bw.WriteByte(Header.TextureCount);
                    bw.WriteByte(0);
                    bw.WriteByte(0);
                    bw.WriteByte(0);

                    bw.WriteInt32(Header.Unk2);
                    bw.ReserveInt32($"FileName{index}");
                    bw.WriteInt32(Flags2);
                    bw.WriteInt32(Header.DXGIFormat);
                }
            }
Beispiel #6
0
        /// <summary>
        /// Reads TPF data from a BinaryReaderEx.
        /// </summary>
        internal override void Read(BinaryReaderEx br)
        {
            br.BigEndian = false;
            br.AssertASCII("TPF\0");
            br.BigEndian = br.GetByte(0xC) == 2;

            int totalFileSize = br.ReadInt32();
            int fileCount     = br.ReadInt32();

            Platform = br.ReadEnum8 <TPFPlatform>();
            Flag2    = br.AssertByte(1, 2, 3);
            Encoding = br.AssertByte(0, 1, 2);
            br.AssertByte(0);

            Textures = new List <Texture>(fileCount);
            for (int i = 0; i < fileCount; i++)
            {
                Textures.Add(new Texture(br, Platform, Encoding));
            }
        }
Beispiel #7
0
            internal void WriteHeader(BinaryWriterEx bw, int index, TPFPlatform platform, byte flag2)
            {
                if (platform == TPFPlatform.PC)
                {
                    DDS dds = new DDS(Bytes);
                    if (dds.dwCaps2.HasFlag(DDS.DDSCAPS2.CUBEMAP))
                    {
                        Type = TexType.Cubemap;
                    }
                    else if (dds.dwCaps2.HasFlag(DDS.DDSCAPS2.VOLUME))
                    {
                        Type = TexType.Volume;
                    }
                    else
                    {
                        Type = TexType.Texture;
                    }
                    Mipmaps = (byte)dds.dwMipMapCount;
                }

                bw.ReserveUInt32($"FileData{index}");
                bw.ReserveInt32($"FileSize{index}");

                bw.WriteByte(Format);
                bw.WriteByte((byte)Type);
                bw.WriteByte(Mipmaps);
                bw.WriteByte(Flags1);

                if (platform != TPFPlatform.PC)
                {
                    bw.WriteInt16(Header.Width);
                    bw.WriteInt16(Header.Height);

                    if (platform == TPFPlatform.Xbox360)
                    {
                        bw.WriteInt32(0);
                    }
                    else if (platform == TPFPlatform.PS3)
                    {
                        bw.WriteInt32(Header.Unk1);
                        if (flag2 != 0)
                        {
                            bw.WriteInt32(Header.Unk2);
                        }
                    }
                    else if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                    {
                        bw.WriteInt32(Header.TextureCount);
                        bw.WriteInt32(Header.Unk2);
                    }
                }

                bw.ReserveUInt32($"FileName{index}");
                bw.WriteInt32(FloatStruct == null ? 0 : 1);

                if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                {
                    bw.WriteInt32(Header.DXGIFormat);
                }

                if (FloatStruct != null)
                {
                    FloatStruct.Write(bw);
                }
            }
Beispiel #8
0
            internal Texture(BinaryReaderEx br, TPFPlatform platform, byte flag2, byte encoding)
            {
                uint fileOffset = br.ReadUInt32();
                int  fileSize   = br.ReadInt32();

                Format  = br.ReadByte();
                Type    = br.ReadEnum8 <TexType>();
                Mipmaps = br.ReadByte();
                Flags1  = br.AssertByte(0, 1, 2, 3);

                if (platform != TPFPlatform.PC)
                {
                    Header        = new TexHeader();
                    Header.Width  = br.ReadInt16();
                    Header.Height = br.ReadInt16();

                    if (platform == TPFPlatform.Xbox360)
                    {
                        br.AssertInt32(0);
                    }
                    else if (platform == TPFPlatform.PS3)
                    {
                        Header.Unk1 = br.ReadInt32();
                        if (flag2 != 0)
                        {
                            Header.Unk2 = br.AssertInt32(0, 0x69E0, 0xAAE4);
                        }
                    }
                    else if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                    {
                        Header.TextureCount = br.AssertInt32(1, 6);
                        Header.Unk2         = br.AssertInt32(0xD);
                    }
                }

                uint nameOffset     = br.ReadUInt32();
                bool hasFloatStruct = br.AssertInt32(0, 1) == 1;

                if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                {
                    Header.DXGIFormat = br.ReadInt32();
                }

                if (hasFloatStruct)
                {
                    FloatStruct = new FloatStruct(br);
                }

                Bytes = br.GetBytes(fileOffset, fileSize);
                if (Flags1 == 2 || Flags1 == 3)
                {
                    Bytes = DCX.Decompress(Bytes, out DCX.Type type);
                    if (type != DCX.Type.DCP_EDGE)
                    {
                        throw new NotImplementedException($"TPF compression is expected to be DCP_EDGE, but it was {type}");
                    }
                }

                if (encoding == 1)
                {
                    Name = br.GetUTF16(nameOffset);
                }
                else if (encoding == 0 || encoding == 2)
                {
                    Name = br.GetShiftJIS(nameOffset);
                }
            }
Beispiel #9
0
            // <summary>
            // Convert the internal format to PC tpf format
            // </summary>
            public void ConsoleToPC(TPFPlatform source)
            {
                // Need to create a DDS Header
                BinaryWriterEx bw = new BinaryWriterEx(false);

                bw.WriteASCII("DDS ");
                bw.WriteInt32(124);
                bw.WriteUInt32(659463); // Flags
                bw.WriteUInt32((uint)Header.Height);
                bw.WriteUInt32((uint)Header.Width);
                bw.WriteUInt32(((uint)Header.Width * (uint)Header.Height) / 2); // Dummy pitch size
                bw.WriteUInt32(1);                                              // Depth
                if (source == TPFPlatform.PS3)
                {
                    // DeS sometimes has mipmap count set to 0 :trashcat:
                    if (Mipmaps == 0)
                    {
                        var dim = Math.Max(Header.Width, Header.Height);
                        while (dim >= 1)
                        {
                            Mipmaps++;
                            dim >>= 1;
                        }
                    }
                }
                bw.WriteUInt32(Mipmaps);
                for (int i = 0; i < 11; i++)
                {
                    bw.WriteInt32(0);
                }
                // Pixel format
                bw.WriteInt32(32);
                bw.WriteInt32(4); // Flags (compressed)
                bool writeExtendedHeader = false;

                if (Header.DXGIFormat == 71 || Header.DXGIFormat == 72 || (source == TPFPlatform.PS3 && (Format == 0 || Format == 1)))
                {
                    bw.WriteASCII("DXT1");
                }
                else if (Header.DXGIFormat == 73 || Header.DXGIFormat == 74 || Header.DXGIFormat == 75 || (source == TPFPlatform.PS3 && (Format == 2 || Format == 3)))
                {
                    bw.WriteASCII("DXT3");
                }
                else if (Header.DXGIFormat == 76 || Header.DXGIFormat == 77 || Header.DXGIFormat == 78 || (source == TPFPlatform.PS3 && (Format == 4 || Format == 5)))
                {
                    bw.WriteASCII("DXT5");
                }
                else if (Header.DXGIFormat == 79 || Header.DXGIFormat == 80 || Header.DXGIFormat == 81)
                {
                    bw.WriteASCII("ATI1");
                }
                else if (Header.DXGIFormat == 82 || Header.DXGIFormat == 83 || Header.DXGIFormat == 84)
                {
                    bw.WriteASCII("ATI2");
                }
                else if (source == TPFPlatform.PS3 && (Format == 9 || Format == 10))
                {
                    bw.WriteASCII("DXT1");
                    Console.WriteLine("ARGB");
                }
                else
                {
                    bw.WriteASCII("DX10");
                    writeExtendedHeader = true;
                }
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);
                bw.WriteInt32(0);

                bw.WriteUInt32(0x401008); // Caps
                if (Cubemap)
                {
                    bw.WriteUInt32(0xFE00);
                }
                else
                {
                    bw.WriteUInt32(0);
                }
                bw.WriteUInt32(0);
                bw.WriteUInt32(0);
                bw.WriteUInt32(0);

                // DX10 extended header
                if (writeExtendedHeader)
                {
                    bw.WriteInt32(Header.DXGIFormat);
                    bw.WriteUInt32(3); // 2D texture
                    if (Cubemap)
                    {
                        bw.WriteUInt32(0x4);
                    }
                    else
                    {
                        bw.WriteUInt32(0);
                    }
                    bw.WriteUInt32(1); // Array Size
                    bw.WriteUInt32(0); // Misc
                }

                // Next attempt to unswizzle the texture
                byte[] unswizzled = new byte[Bytes.Length];
                for (int i = 0; i < unswizzled.Length; i++)
                {
                    unswizzled[i] = Bytes[i];
                }

                if (source == TPFPlatform.PS4)
                {
                    uint blockSize = 16;
                    if (Header.DXGIFormat == 71 || Header.DXGIFormat == 72 || Header.DXGIFormat == 79 || Header.DXGIFormat == 80 || Header.DXGIFormat == 81)
                    {
                        blockSize = 8;
                    }

                    int mipBase    = 0;
                    int mipBaseSrc = 0;
                    for (int miplevel = 0; miplevel < Mipmaps; miplevel++)
                    {
                        uint bytesPerLine = Math.Max((uint)Header.Width >> miplevel, 1) * blockSize / 4;
                        int  heightBlock  = Math.Max((Header.Height / 4) >> miplevel, 1);
                        int  widthBlock   = Math.Max((Header.Width / 4) >> miplevel, 1);
                        // Convert swizzled to linear strided

                        int index = 0;
                        for (int y = 0; y < heightBlock; y++)
                        {
                            for (int x = 0; x < widthBlock; x++)
                            {
                                int mx = x;
                                int my = y;
                                if (widthBlock > 1 && heightBlock > 1)
                                {
                                    MapBlockPosition(x, y, widthBlock, 2, out mx, out my);
                                }

                                if (widthBlock > 2 && heightBlock > 2)
                                {
                                    MapBlockPosition(mx, my, widthBlock, 4, out mx, out my);
                                }

                                if (widthBlock > 4 && heightBlock > 4)
                                {
                                    MapBlockPosition(mx, my, widthBlock, 8, out mx, out my);
                                }

                                int destinationIndex = (int)blockSize * (my * widthBlock + mx);
                                for (int i = 0; i < blockSize; i++)
                                {
                                    unswizzled[mipBase + destinationIndex + i] = Bytes[mipBaseSrc + index];
                                    index += 1;
                                }
                            }
                        }

                        mipBase += index;
                        if (index < 512)
                        {
                            mipBaseSrc += 512;
                        }
                        else
                        {
                            mipBaseSrc += index;
                        }
                    }
                }

                // Append the rest of the original texture and update
                bw.WriteBytes(unswizzled);
                Bytes = bw.FinishBytes();
            }
Beispiel #10
0
            internal Texture(BinaryReaderEx br, TPFPlatform platform, byte flag2, byte encoding)
            {
                uint fileOffset = br.ReadUInt32();
                int  fileSize   = br.ReadInt32();

                Format  = br.ReadByte();
                Type    = br.ReadEnum8 <TexType>();
                Mipmaps = br.ReadByte();
                Flags1  = br.AssertByte(0, 1, 2, 3);

                uint nameOffset = uint.MaxValue;

                if (platform == TPFPlatform.PC)
                {
                    Header     = null;
                    nameOffset = br.ReadUInt32();
                    Flags2     = br.AssertInt32(0, 1);
                }
                else
                {
                    Header        = new TexHeader();
                    Header.Width  = br.ReadInt16();
                    Header.Height = br.ReadInt16();

                    if (platform == TPFPlatform.Xbox360)
                    {
                        br.AssertInt32(0);
                        nameOffset = br.ReadUInt32();
                        br.AssertInt32(0);
                    }
                    else if (platform == TPFPlatform.PS3)
                    {
                        Header.Unk1 = br.ReadInt32();
                        if (flag2 != 0)
                        {
                            Header.Unk2 = br.AssertInt32(0, 0xAAE4);
                        }
                        nameOffset = br.ReadUInt32();
                        Flags2     = br.AssertInt32(0, 1);
                        if (Flags2 == 1)
                        {
                            Unk20 = br.ReadInt32();
                            Unk24 = br.ReadInt32();
                            Unk28 = br.ReadSingle();
                        }
                    }
                    else if (platform == TPFPlatform.PS4 || platform == TPFPlatform.Xbone)
                    {
                        Header.TextureCount = br.AssertInt32(1, 6);
                        Header.Unk2         = br.AssertInt32(0xD);
                        nameOffset          = br.ReadUInt32();
                        Flags2            = br.AssertInt32(0, 1);
                        Header.DXGIFormat = br.ReadInt32();
                    }
                }

                Bytes = br.GetBytes(fileOffset, fileSize);
                if (Flags1 == 2 || Flags1 == 3)
                {
                    Bytes = DCX.Decompress(Bytes);
                }

                if (encoding == 1)
                {
                    Name = br.GetUTF16(nameOffset);
                }
                else if (encoding == 0 || encoding == 2)
                {
                    Name = br.GetShiftJIS(nameOffset);
                }
            }