Пример #1
0
        public TEX(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                // Set endianess
                if (br.PeekString() == "\0XET")
                {
                    br.ByteOrder = ByteOrder = ByteOrder.BigEndian;
                }

                // Header
                Header     = br.ReadType <FileHeader>();
                HeaderInfo = new FileHeaderInfo
                {
                    // Block 1
                    Version           = (Version)(Header.Block1 & 0xFFF),
                    Unknown1          = (int)((Header.Block1 >> 12) & 0xFFF),
                    Unused1           = (int)((Header.Block1 >> 24) & 0xF),
                    AlphaChannelFlags = (AlphaChannelFlags)((Header.Block1 >> 28) & 0xF),
                    // Block 2
                    MipMapCount = (int)(Header.Block2 & 0x3F),
                    Width       = (int)((Header.Block2 >> 6) & 0x1FFF),
                    Height      = Math.Max((int)((Header.Block2 >> 19) & 0x1FFF), MinHeight),
                    // Block 3
                    Unknown2 = (int)(Header.Block3 & 0xFF),
                    Format   = (byte)((Header.Block3 >> 8) & 0xFF),
                    Unknown3 = (int)((Header.Block3 >> 16) & 0xFFFF)
                };

                if (HeaderInfo.Version == Version._Switchv1 && !SwitchFormats.ContainsKey(HeaderInfo.Format))
                {
                    throw new ImageFormatException($"Switch texture format 0x{HeaderInfo.Format.ToString("X2")} is not implemented.");
                }
                else if (!Formats.ContainsKey(HeaderInfo.Format))
                {
                    throw new ImageFormatException($"Texture format 0x{HeaderInfo.Format.ToString("X2")} is not implemented.");
                }

                // TODO: Consider whether the following settings make more sense if conditioned by the ByteOrder (or Platform)
                //var format = HeaderInfo.Format.ToString().StartsWith("DXT1") ? Format.DXT1 : HeaderInfo.Format.ToString().StartsWith("DXT5") ? Format.DXT5 : HeaderInfo.Format;
                Settings.Format = (HeaderInfo.Version == Version._Switchv1) ? SwitchFormats[HeaderInfo.Format] : Formats[HeaderInfo.Format];

                List <int> mipMaps = null;
                if (HeaderInfo.Version == Version._Switchv1)
                {
                    var texOverallSize = br.ReadInt32();
                    if (texOverallSize > br.BaseStream.Length)
                    {
                        br.BaseStream.Position -= 4;
                        SwitchUnknownData       = br.ReadBytes(0x6C);
                        texOverallSize          = br.ReadInt32();
                        HeaderInfo.MipMapCount++;
                    }
                    mipMaps = br.ReadMultiple <int>(HeaderInfo.MipMapCount);
                }
                else if (HeaderInfo.Version != Version._3DSv1)
                {
                    mipMaps = br.ReadMultiple <int>(HeaderInfo.MipMapCount);
                }

                for (var i = 0; i < mipMaps.Count; i++)
                {
                    var texDataSize = 0;
                    if (SwitchUnknownData != null)
                    {
                        if (i + 1 == HeaderInfo.MipMapCount)
                        {
                            continue;
                        }
                        texDataSize = mipMaps[i + 1] - mipMaps[i];
                    }
                    else if (HeaderInfo.Version != Version._3DSv1)
                    {
                        texDataSize = (i + 1 < HeaderInfo.MipMapCount ? mipMaps[i + 1] : (int)br.BaseStream.Length) - mipMaps[i];
                    }
                    else
                    {
                        texDataSize = Formats[HeaderInfo.Format].BitDepth * (HeaderInfo.Width >> i) * (HeaderInfo.Height >> i) / 8;
                    }

                    Settings.Width  = Math.Max(HeaderInfo.Width >> i, 2);
                    Settings.Height = Math.Max(HeaderInfo.Height >> i, 2);

                    //Set possible Swizzles
                    if (HeaderInfo.Version == Version._3DSv1 || HeaderInfo.Version == Version._3DSv2 || HeaderInfo.Version == Version._3DSv3)
                    {
                        Settings.Swizzle = new CTRSwizzle(Settings.Width, Settings.Height);
                    }
                    else if (HeaderInfo.Version == Version._Switchv1)
                    {
                        Settings.Swizzle = new NXSwizzle(Settings.Width, Settings.Height, Settings.Format.BitDepth, GetSwitchSwizzleFormat(Settings.Format.FormatName));
                    }
                    else if (Settings.Format.FormatName.Contains("DXT"))
                    {
                        Settings.Swizzle = new BlockSwizzle(Settings.Width, Settings.Height);
                    }

                    //Set possible pixel shaders
                    if ((Format)HeaderInfo.Format == Format.DXT5_B)
                    {
                        Settings.PixelShader = ToNoAlpha;
                    }
                    else if ((Format)HeaderInfo.Format == Format.DXT5_YCbCr)
                    {
                        Settings.PixelShader = ToProperColors;
                    }

                    Bitmaps.Add(Common.Load(br.ReadBytes(texDataSize), Settings));
                }

                if (SwitchUnknownData != null)
                {
                    SwitchOverflowingData = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position));
                }
            }
        }