public MTTEX(Stream input) { using (var br = new BinaryReaderX(input)) { // Set endianess if (br.PeekString() == "\0XET") { br.ByteOrder = ByteOrder = ByteOrder.BigEndian; } // Header Header = br.ReadStruct <Header>(); HeaderInfo = new HeaderInfo { // 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 = (Format)((Header.Block3 >> 8) & 0xFF), Unknown3 = (int)((Header.Block3 >> 16) & 0xFFFF) }; // @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 = ImageSettings.ConvertFormat(format); if (Settings.Format.ToString().Contains("DXT")) { Settings.PadToPowerOf2 = false; Settings.ZOrder = false; Settings.TileSize = 4; } var mipMaps = br.ReadMultiple <int>(HeaderInfo.MipMapCount); for (var i = 0; i < mipMaps.Count; i++) { var texDataSize = (i + 1 < mipMaps.Count ? mipMaps[i + 1] : (int)br.BaseStream.Length) - mipMaps[i]; Settings.Width = Math.Max(HeaderInfo.Width >> i, 2); Settings.Height = Math.Max(HeaderInfo.Height >> i, 2); if (HeaderInfo.Format == Format.DXT5_B) { Settings.PixelShader = ToNoAlpha; } else if (HeaderInfo.Format == Format.DXT5_YCbCr) { Settings.PixelShader = ToProperColors; } Bitmaps.Add(Common.Load(br.ReadBytes(texDataSize), Settings)); } } }
public MTTEX(Stream input) { using (var br = new BinaryReaderX(input)) { // Set endianess if (br.PeekString(4) == "\0XET") { br.ByteOrder = ByteOrder = ByteOrder.BigEndian; } // Header Header = br.ReadStruct <Header>(); HeaderInfo = new HeaderInfo { // 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) }; // @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 == image_mt.Version._Switchv1) ? SwitchFormats[HeaderInfo.Format] : Formats[HeaderInfo.Format]; List <int> mipMaps = null; if (HeaderInfo.Version == image_mt.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 != image_mt.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 != image_mt.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 == image_mt.Version._3DSv1 || HeaderInfo.Version == image_mt.Version._3DSv2 || HeaderInfo.Version == image_mt.Version._3DSv3) { Settings.Swizzle = new CTRSwizzle(Settings.Width, Settings.Height); } else if (HeaderInfo.Version == image_mt.Version._Switchv1) { Settings.Swizzle = new SwitchSwizzle(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)); } } }