Beispiel #1
0
        public static void Export(string FileName, SBSurface surface)
        {
            using (BinaryWriter writer = new BinaryWriter(new FileStream(FileName, FileMode.Create)))
            {
                writer.Write(SwitchSwizzler.CreateBuffer(surface));

                uint ImageSize = (uint)writer.BaseStream.Position;

                foreach (var mip in surface.Arrays)
                {
                    foreach (var m in mip.Mipmaps)
                    {
                        writer.Write(m.Length);
                    }
                    for (int i = mip.Mipmaps.Count; i < 0x10; i++)
                    {
                        writer.Write(0);
                    }
                }

                writer.Write(new char[] { ' ', 'X', 'N', 'T' });
                writer.Write(surface.Name.ToCharArray());
                writer.Write(new byte[0x40 - surface.Name.Length]);
                writer.Write(surface.Width);
                writer.Write(surface.Height);
                writer.Write(surface.Depth);
                writer.Write((byte)TexFormatByInternalFormat(surface.InternalFormat)); // format
                writer.Write((byte)4);                                                 // unknown usually 4
                writer.Write((short)0);                                                // pad
                writer.Write(surface.IsCubeMap ? 9 : 4);                               // unknown usually 4 9 for cubemap
                writer.Write(surface.Arrays[0].Mipmaps.Count);
                writer.Write(0x1000);                                                  // alignment
                writer.Write(surface.Arrays.Count);                                    // array count
                writer.Write(ImageSize);

                writer.Write(new char[] { ' ', 'X', 'E', 'T' });
                writer.Write((short)1); // version major
                writer.Write((short)2); // version minor
            }
        }
Beispiel #2
0
        public static SBSurface Open(string FilePath)
        {
            using (BinaryReader reader = new BinaryReader(new FileStream(FilePath, FileMode.Open)))
            {
                // TODO: Why are there empty streams?
                if (reader.BaseStream.Length == 0)
                {
                    return(null);
                }

                SBSurface surface = new SBSurface();

                reader.BaseStream.Position = reader.BaseStream.Length - 0xB0;

                int[] mipmapSizes = new int[16];
                for (int i = 0; i < mipmapSizes.Length; i++)
                {
                    mipmapSizes[i] = reader.ReadInt32();
                }

                reader.ReadChars(4); // TNX magic

                string texName = ReadTexName(reader);
                surface.Name = texName;

                surface.Width  = reader.ReadInt32();
                surface.Height = reader.ReadInt32();
                surface.Depth  = reader.ReadInt32();

                var Format = (NUTEX_FORMAT)reader.ReadByte();

                reader.ReadByte();

                ushort Padding = reader.ReadUInt16();
                reader.ReadUInt32();

                int MipCount  = reader.ReadInt32();
                int Alignment = reader.ReadInt32();
                surface.ArrayCount = reader.ReadInt32();
                int    ImageSize    = reader.ReadInt32();
                char[] Magic        = reader.ReadChars(4);
                int    MajorVersion = reader.ReadInt16();
                int    MinorVersion = reader.ReadInt16();

                if (pixelFormatByNuTexFormat.ContainsKey(Format))
                {
                    surface.PixelFormat = pixelFormatByNuTexFormat[Format];
                }

                if (internalFormatByNuTexFormat.ContainsKey(Format))
                {
                    surface.InternalFormat = internalFormatByNuTexFormat[Format];
                }

                surface.PixelType = GetPixelType(Format);

                reader.BaseStream.Position = 0;
                byte[] ImageData = reader.ReadBytes(ImageSize);

                for (int array = 0; array < surface.ArrayCount; array++)
                {
                    MipArray arr = new MipArray();
                    for (int i = 0; i < MipCount; i++)
                    {
                        byte[] deswiz = SwitchSwizzler.GetImageData(surface, ImageData, array, i, MipCount);
                        arr.Mipmaps.Add(deswiz);
                    }
                    surface.Arrays.Add(arr);
                }

                return(surface);
            }
        }
Beispiel #3
0
        public override void Open(string Path)
        {
            //hingadingadurgan
            using (BinaryReader R = new BinaryReader(new FileStream(Path, FileMode.Open)))
            {
                Mipmaps = new List <byte[]>();
                // TODO: Why are there empty streams?
                if (R.BaseStream.Length == 0)
                {
                    return;
                }

                R.BaseStream.Position = R.BaseStream.Length - 0xB0;


                int[] MipSizes = new int[16];
                for (int i = 0; i < MipSizes.Length; i++)
                {
                    MipSizes[i] = R.ReadInt32();
                }
                R.ReadChars(4); // TNX magic
                TexName = "";
                for (int i = 0; i < 0x40; i++)
                {
                    byte b = R.ReadByte();
                    if (b != 0)
                    {
                        TexName += (char)b;
                    }
                }
                Width  = R.ReadInt32();
                Height = R.ReadInt32();
                int Unk = R.ReadInt32();
                Format = (NUTEX_FORMAT)R.ReadByte();
                R.ReadByte();
                ushort Padding = R.ReadUInt16();
                R.ReadUInt32();
                int    MipCount     = R.ReadInt32();
                int    Alignment    = R.ReadInt32();
                int    ArrayCount   = R.ReadInt32();
                int    ImageSize    = R.ReadInt32();
                char[] Magic        = R.ReadChars(4);
                int    MajorVersion = R.ReadInt16();
                int    MinorVersion = R.ReadInt16();

                uint blkWidth  = (uint)blkDims[Format].X;
                uint blkHeight = (uint)blkDims[Format].Y;

                uint blockHeight     = SwitchSwizzler.GetBlockHeight(SwitchSwizzler.DIV_ROUND_UP((uint)Height, blkHeight));
                uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
                uint tileMode        = 0;

                uint bpp = GetBpps(Format);

                R.BaseStream.Position = 0;
                int blockHeightShift = 0;
                for (int i = 0; i < 1; i++)
                {
                    int size = MipSizes[i];

                    if (i == 0)
                    {
                        if (size % Alignment != 0)
                        {
                            size = size + (Alignment - (size % Alignment));
                        }
                    }

                    try
                    {
                        byte[] deswiz  = SwitchSwizzler.deswizzle((uint)Width, (uint)Height, blkWidth, blkHeight, 0, bpp, tileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), R.ReadBytes(ImageSize));
                        byte[] trimmed = new byte[MipSizes[0]];
                        Array.Copy(deswiz, 0, trimmed, 0, trimmed.Length);

                        Mipmaps.Add(trimmed);
                    }
                    catch
                    {
                    }
                }
            }
        }
Beispiel #4
0
        private byte[] Deswizzle(uint width, uint height, uint numMipmaps, byte[] image)
        {
            uint bpp           = 8;
            uint blkWidth      = 4;
            uint blkHeight     = 4;
            uint dataAlignment = 512;

            uint blockHeight         = SwitchSwizzler.GetBlockHeight(SwitchSwizzler.DivRoundUp(height, blkHeight));
            uint blockHeightLog2     = (uint)System.Convert.ToString(blockHeight, 2).Length - 1;
            int  linesPerBlockHeight = (1 << (int)blockHeightLog2) * 8;

            uint totalSize = 0;

            for (var i = 0; i < numMipmaps; i++)
            {
                uint mipmapWidth  = Math.Max(1, width >> i);
                uint mipmapHeight = Math.Max(1, height >> i);
                uint mipmapSize   = SwitchSwizzler.DivRoundUp(mipmapWidth, blkWidth) *
                                    SwitchSwizzler.DivRoundUp(mipmapHeight, blkHeight) *
                                    bpp;

                totalSize += mipmapSize;
            }

            var result = new byte[totalSize];

            uint surfaceSize      = 0;
            var  blockHeightShift = 0;

            List <uint> mipOffsets = new List <uint>();

            uint resultOffset = 0;

            for (var i = 0; i < numMipmaps; i++)
            {
                uint mipmapWidth  = Math.Max(1, width >> i);
                uint mipmapHeight = Math.Max(1, height >> i);
                uint mipmapSize   = SwitchSwizzler.DivRoundUp(mipmapWidth, blkWidth) *
                                    SwitchSwizzler.DivRoundUp(mipmapHeight, blkHeight) *
                                    bpp;

                if (SwitchSwizzler.Pow2RoundUp(SwitchSwizzler.DivRoundUp(mipmapHeight, blkWidth)) < linesPerBlockHeight)
                {
                    blockHeightShift += 1;
                }

                uint roundWidth  = SwitchSwizzler.DivRoundUp(mipmapWidth, blkWidth);
                uint roundHeight = SwitchSwizzler.DivRoundUp(mipmapHeight, blkHeight);

                surfaceSize += SwitchSwizzler.RoundUp(surfaceSize, dataAlignment) - surfaceSize;
                mipOffsets.Add(surfaceSize);

                var msize = (int)(mipOffsets[0] + image.Length - mipOffsets[i]);

                var mipmap = new byte[msize];
                Array.Copy(image, mipOffsets[i], mipmap, 0, msize);

                var info = new SwizzleInfo
                {
                    Width           = mipmapWidth,
                    Height          = mipmapHeight,
                    Depth           = 1,
                    BlkWidth        = blkWidth,
                    BlkHeight       = blkHeight,
                    BlkDepth        = 1,
                    RoundPitch      = 1,
                    Bpp             = bpp,
                    TileMode        = 0,
                    BlockHeightLog2 = (int)Math.Max(0, blockHeightLog2 - blockHeightShift),
                };

                uint pitch = SwitchSwizzler.RoundUp(roundWidth * bpp, 64);
                surfaceSize += pitch *
                               SwitchSwizzler.RoundUp(roundHeight, Math.Max(1, blockHeight >> blockHeightShift) * 8);
                byte[] deswizzled = SwitchSwizzler.Deswizzle(info, mipmap);
                Array.Copy(deswizzled, 0, result, resultOffset, mipmapSize);
                resultOffset += mipmapSize;
            }

            return(result);
        }
Beispiel #5
0
        public override void Open()
        {
            using (BinaryReader reader = new BinaryReader(new FileStream(AbsolutePath, FileMode.Open)))
            {
                Mipmaps = new List <byte[]>();
                // TODO: Why are there empty streams?
                if (reader.BaseStream.Length == 0)
                {
                    return;
                }

                reader.BaseStream.Position = reader.BaseStream.Length - 0xB0;


                int[] mipmapSizes = new int[16];
                for (int i = 0; i < mipmapSizes.Length; i++)
                {
                    mipmapSizes[i] = reader.ReadInt32();
                }

                reader.ReadChars(4); // TNX magic

                TexName = ReadTexName(reader);

                Width  = reader.ReadInt32();
                Height = reader.ReadInt32();
                Depth  = reader.ReadInt32();

                Format = (NUTEX_FORMAT)reader.ReadByte();

                reader.ReadByte();

                ushort Padding = reader.ReadUInt16();
                reader.ReadUInt32();

                int    MipCount     = reader.ReadInt32();
                int    Alignment    = reader.ReadInt32();
                int    ArrayCount   = reader.ReadInt32();
                int    ImageSize    = reader.ReadInt32();
                char[] Magic        = reader.ReadChars(4);
                int    MajorVersion = reader.ReadInt16();
                int    MinorVersion = reader.ReadInt16();

                uint blkWidth  = (uint)blkDims[Format].X;
                uint blkHeight = (uint)blkDims[Format].Y;

                uint blockHeight     = SwitchSwizzler.GetBlockHeight(SwitchSwizzler.DivRoundUp((uint)Height, blkHeight));
                uint BlockHeightLog2 = (uint)Convert.ToString(blockHeight, 2).Length - 1;
                uint tileMode        = 0;

                uint bpp = GetBpps(Format);

                reader.BaseStream.Position = 0;
                int blockHeightShift = 0;
                for (int i = 0; i < 1; i++)
                {
                    int size = mipmapSizes[i];

                    if (i == 0 && size % Alignment != 0)
                    {
                        size += Alignment - (size % Alignment);
                    }

                    byte[] deswiz  = SwitchSwizzler.Deswizzle((uint)Width, (uint)Height, blkWidth, blkHeight, 0, bpp, tileMode, (int)Math.Max(0, BlockHeightLog2 - blockHeightShift), reader.ReadBytes(ImageSize));
                    byte[] trimmed = new byte[mipmapSizes[0]];
                    Array.Copy(deswiz, 0, trimmed, 0, trimmed.Length);

                    Mipmaps.Add(trimmed);
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Write the swizzled mipmaps to a DataStream.
        /// </summary>
        /// <param name="height">Image height (in pixels).</param>
        /// <param name="width">Image width (in pixels).</param>
        /// <param name="mipmaps">The list of mipmaps.</param>
        /// <returns>The DataStream.</returns>
        protected override DataStream Write(uint height, uint width, List <byte[]> mipmaps)
        {
            if (mipmaps == null)
            {
                throw new ArgumentNullException(nameof(mipmaps));
            }

            DataStream outputDataStream = DataStreamFactory.FromMemory();
            var        writer           = new DataWriter(outputDataStream)
            {
                DefaultEncoding = Encoding.ASCII,
                Endianness      = EndiannessMode.LittleEndian,
            };

            writer.Write(0x20L);
            writer.Write(0x10L);
            writer.Write(0x20L);
            writer.Write(0x00L); // Size
            writer.Write(0x00L);
            writer.Write(0x00L);

            writer.Write(0x20L);
            writer.Write(0x18L);
            writer.Write(0x28L);
            writer.Write(0x00L); // Size - 0x38

            writer.Write(width);
            writer.Write(height);
            writer.Write(0x01);
            writer.Write(0x01);

            writer.Write(0x49);
            writer.Write(mipmaps.Count);

            var blockHeightShift = 0;

            const uint blkWidth  = 4;
            const uint blkHeight = 4;
            const uint bpp       = 8;

            uint blockHeight     = SwitchSwizzler.GetBlockHeight(SwitchSwizzler.DivRoundUp(height, blkHeight));
            uint blockHeightLog2 = (uint)System.Convert.ToString(blockHeight, 2).Length - 1;

            uint linesPerBlockHeight = blockHeight * 8;

            for (var mipLevel = 0; mipLevel < mipmaps.Count; mipLevel++)
            {
                byte[] mipmap = mipmaps[mipLevel];

                uint mipmapWidth  = Math.Max(1, width >> mipLevel);
                uint mipmapHeight = Math.Max(1, height >> mipLevel);

                uint roundedHeight = SwitchSwizzler.DivRoundUp(mipmapHeight, blkHeight);

                if (SwitchSwizzler.Pow2RoundUp(roundedHeight) < linesPerBlockHeight)
                {
                    blockHeightShift += 1;
                }

                var info = new SwizzleInfo
                {
                    Width           = mipmapWidth,
                    Height          = mipmapHeight,
                    Depth           = 1,
                    BlkWidth        = blkWidth,
                    BlkHeight       = blkHeight,
                    BlkDepth        = 1,
                    RoundPitch      = 1,
                    Bpp             = bpp,
                    TileMode        = 0,
                    BlockHeightLog2 = (int)Math.Max(0, blockHeightLog2 - blockHeightShift),
                };

                byte[] swizzled = SwitchSwizzler.Swizzle(info, mipmap);
                writer.Write(swizzled);
            }

            writer.Stream.Seek(0x18, System.IO.SeekOrigin.Begin);
            writer.Write(outputDataStream.Length - 0x30);

            writer.Stream.Seek(0x48, System.IO.SeekOrigin.Begin);
            writer.Write(outputDataStream.Length - 0x68);

            return(outputDataStream);
        }