Пример #1
0
        public void Read(string fname)
        {
            FileData d = new FileData(fname);

            d.Endian = System.IO.Endianness.Little;

            d.skip(4); // RIFF
            int riffsize = d.readInt();

            d.skip(4); //WAVE

            d.skip(4); //fmt
            int formatsize   = d.readInt();
            int audio_format = d.readShort();
            int channelCount = d.readShort();
            int sampleRate   = d.readInt();
            int byte_rate    = d.readInt();
            int blockalign   = d.readShort();
            int bps          = d.readShort();

            d.skip(4); // data
            int datasize = d.readInt();


            byte[] data = d.getSection(d.pos(), datasize);

            Play(data, channelCount, bps, sampleRate);
        }
Пример #2
0
        public void ReadParameters(FileData f, int count)
        {
            for (int i = 0; i < count; i++)
            {
                BCH_TextureParameter p = new BCH_TextureParameter()
                {
                    Value = f.readInt()
                };
                p.ParseParameter(f.readInt());

                Nodes.Add(p);

                if (p.Id == BCH_TextureParameter.Parameter.texUnit0Size)
                {
                    Width  = p.GetHalf1();
                    Height = p.GetHalf2();
                }
                if (p.Id == BCH_TextureParameter.Parameter.texUnit0Type)
                {
                    type = p.Value;
                }
                if (p.Id == BCH_TextureParameter.Parameter.texUnit0Address)
                {
                    data = f.getSection(p.Value, f.size() - p.Value);
                }
            }
            if (Width > 0 && Height > 0)
            {
                texture = _3DS.DecodeImage(data, Width, Height, (_3DS.Tex_Formats)type);
                //Texture glTex = new Texture2D(texture);
                //display = glTex.Id;
            }
        }
Пример #3
0
            public void ReadPACK(FileData d)
            {
                int start = d.pos();

                foreach (TONE_META meta in tones)
                {
                    meta.idsp = d.getSection(start + meta.offset + 8, meta.size);
                }
            }
Пример #4
0
        public void Read(FileData d)
        {
            d.Endian = Endianness.Big;

            d.seek(0x16);
            int count = d.readShort();

            d.seek(0x60);

            for (int i = 0; i < count; i++)
            {
                string name = d.readString(d.pos(), -1);
                d.skip(0x40);
                int unk      = d.readInt();
                int nextFile = d.readInt();
                int c2       = d.readShort();
                int c1       = d.readShort();
                d.skip(4); // padding?

                int[] partsizes = new int[4];
                for (int j = 0; j < 4; j++)
                {
                    partsizes[j] = d.readInt();
                }

                TreeNode part = new TreeNode();
                part.Text = name;
                Nodes.Add(part);

                int off = 0;
                for (int j = 0; j < c1; j++)
                {
                    TreeNode t = new TreeNode();
                    part.Nodes.Add(t);
                    int    decompressedSize = d.readInt();
                    byte[] dat = FileData.InflateZLIB(d.getSection(d.pos(), partsizes[j] - 4 - off));
                    d.skip(partsizes[j] - 4);
                    off += partsizes[j];
                    string mag = new FileData(dat).Magic();
                    t.Text = name + "." + mag;

                    if (mag.Equals("NTWD"))
                    {
                        Runtime.TextureContainers.Add(new NUT(new FileData(dat)));
                    }

                    if (mag.Equals("OMO "))
                    {
                        Runtime.Animations.Add(t.Text, OMOOld.read(new FileData(dat)));
                        MainForm.Instance.animList.treeView1.Nodes.Add(t.Text);
                    }
                }
            }
        }
Пример #5
0
        public SARC(String FileName)
        {
            FileData f = new FileData(FileName);


            f.skip(4); // magic check
            f.skip(2); // headerlength
            if (f.readShort() == 0xFEFF)
            {
                f.Endian = Endianness.Big;
            }
            else
            {
                f.Endian = Endianness.Little;
            }

            f.skip(4); // filesize
            int dataOffset = f.readInt();

            f.skip(4); // always 0x01000000

            // SFAT Header
            f.skip(4); // SFAT
            f.skip(2); // header size
            int nodeCount = f.readShort();

            f.skip(4); // hash multiplyer always 0x65

            // before nodes get strings
            int stringoff = f.pos() + 16 * nodeCount + 8;

            // nodes
            for (int i = 0; i < nodeCount; i++)
            {
                uint   hash      = (uint)f.readInt();
                byte   flag      = (byte)f.readByte();
                string name      = f.readString(stringoff + f.readThree() * 4, -1);
                int    nodeStart = f.readInt();
                int    size      = f.readInt() - nodeStart;

                byte[] data = f.getSection(nodeStart + dataOffset, size);

                //  Nodes.Add(name);

                FileData d     = new FileData(data);
                int      Magic = d.readInt();
                if (Magic == 0x46524563)
                {
                    Console.WriteLine(name);
                }
            }
        }
Пример #6
0
        public void ReadBNTX(FileData f)
        {
            textures.Clear();

            BFRES b = new BFRES();

            temp = f.pos();

            f.skip(8); //Magic
            int Version        = f.readInt();
            int ByteOrderMark  = f.readShort();
            int FormatRevision = f.readShort();

            Text = f.readString(f.readInt() + temp, -1);
            f.skip(2);
            int strOffset   = f.readShort();
            int relocOffset = f.readInt();
            int FileSize    = f.readInt();

            f.skip(4); //NX Magic
            int TexturesCount   = f.readInt();
            int InfoPtrsOffset  = f.readInt();
            int DataBlockOffset = f.readInt();
            int DictOffset      = f.readInt();
            int strDictSize     = f.readInt();

            Text = Text + ".bntx";

            BNTXFile = f.getSection(temp, FileSize);

            for (int i = 0; i < TexturesCount; i++)
            {
                f.seek(InfoPtrsOffset + temp + i * 8);
                BRTIOffset = f.readInt();


                f.seek(BRTIOffset + temp);

                //  textures.Add(new BRTI(f));
                BRTI texture = new BRTI(f);

                if (!textured.ContainsKey(texture.Text))
                {
                    textured.Add(texture.Text, texture);
                }

                textures.Add(texture);
            }
            Nodes.AddRange(textures.ToArray());
        }
Пример #7
0
        // temp stuff
        public static Dictionary <string, SkelAnimation> LoadAJ(string fname, VBN vbn)
        {
            // a note, I know that the main player file has the offsets for
            // animations, this is just for viewing
            FileData f = new FileData(fname);

            f.Endian = System.IO.Endianness.Big;

            int pos = 0;

            Dictionary <string, SkelAnimation> animations = new Dictionary <string, SkelAnimation>();
            AnimationGroupNode group = new AnimationGroupNode()
            {
                Text = fname
            };

            MainForm.Instance.animList.treeView1.Nodes.Add(group);
            while (pos < f.size())
            {
                Console.WriteLine(pos.ToString("x"));
                int           len  = f.readInt();
                DAT_Animation anim = new DAT_Animation();
                anim.Read(new FileData(f.getSection(pos, len)));
                AnimTrack track = new AnimTrack(anim);

                if (pos == 0)
                {
                    //track.Show();
                }
                group.Nodes.Add(track.toAnimation(vbn));
                SkelAnimation sa = track.BakeToSkel(vbn);
                //sa.Tag = track;
                //Runtime.Animations.Add(anim.Name, sa);
                // MainForm.Instance.animList.treeView1.Nodes.Add(anim.Name);
                animations.Add(anim.Name, sa);

                if (pos != 0)
                {
                    track.Dispose();
                    track.Close();
                }

                f.skip(len - 4);
                f.align(32);
                pos = f.pos();
            }

            return(animations);
        }
Пример #8
0
        public NUT.NUD_Texture toNUT_Texture()
        {
            NUT.NUD_Texture tex = new NUT.NUD_Texture();
            tex.id     = 0x48415348;
            tex.height = header.height;
            tex.width  = header.width;
            float size = 1;
            int   mips = 4;

            if (mips > header.mipmapCount)
            {
                mips = header.mipmapCount;
                throw new Exception("No mipmaps");
            }

            switch (header.dwFourCC)
            {
            case 0x0:
                size      = 4f;
                tex.type  = PixelInternalFormat.Rgba;
                tex.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;

            case 0x31545844:
                size     = 1 / 2f;
                tex.type = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case 0x35545844:
                size     = 1f;
                tex.type = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;
            }

            // now for mipmap data...
            FileData d = new FileData(data);
            int      off = 0, w = header.width, h = header.height;

            for (int i = 0; i < 4; i++)
            {
                int s = (int)((w * h) * size);
                w /= 2;
                h /= 2;
                tex.mipmaps.Add(d.getSection(off, s));
                off += s;
            }

            return(tex);
        }
Пример #9
0
        public void OpenTEX(string fname)
        {
            Edited = true;
            FileData d = new FileData(fname);

            d.Endian = System.IO.Endianness.Little;

            int width  = d.readInt();
            int height = d.readInt();
            int type   = d.readByte();
            int dunno  = d.readByte();

            d.skip(2); // padding

            string name = "";

            int i = d.readByte();

            while (i != 0x00)
            {
                name += (char)i;
                i     = d.readByte();
            }

            if (type > 0xD || type < 0)
            {
                return;
            }

            nameBox.Text = name;
            formatSelector.SelectedIndex = type;
            label3.Text = "Width: " + width;
            label4.Text = "Height: " + height;

            byte[] data = d.getSection(0x80, d.size() - 0x80);

            pictureBox1.Image = _3DS.DecodeImage(data, width, height, (_3DS.Tex_Formats)type);

            pictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipY);
        }
Пример #10
0
        public NutTexture toNUT_Texture()
        {
            NutTexture tex = new NutTexture();

            tex.HASHID = 0x48415348;
            tex.Height = header.height;
            tex.Width  = header.width;
            float size = 1;
            int   mips = header.mipmapCount;

            /*if (mips > header.mipmapCount)
             * {
             *  mips = header.mipmapCount;
             *  MessageBox.Show("Possible texture error: Only one mipmap");
             * }*/

            switch (header.dwFourCC)
            {
            case 0x0:
                size      = 4f;
                tex.type  = PixelInternalFormat.SrgbAlpha;
                tex.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;

            case 0x31545844:
                size     = 1 / 2f;
                tex.type = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case 0x35545844:
                size     = 1f;
                tex.type = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;

            case 0x32495441:
                size     = 1 / 2f;
                tex.type = PixelInternalFormat.CompressedRedRgtc1;
                break;

            case 0x31495441:
                size     = 1f;
                tex.type = PixelInternalFormat.CompressedRgRgtc2;
                break;

            default:
                MessageBox.Show("Unsupported DDS format - 0x" + header.dwFourCC.ToString("x"));
                break;
            }

            // now for mipmap data...
            FileData d = new FileData(data);
            int      off = 0, w = header.width, h = header.height;

            if (header.mipmapCount == 0)
            {
                header.mipmapCount = 1;
            }
            for (int i = 0; i < header.mipmapCount; i++)
            {
                int s = (int)((w * h) * size);
                if (s < 0x8)
                {
                    s = 0x8;
                }
                //Console.WriteLine(off.ToString("x") + " " + s.ToString("x"));
                w /= 2;
                h /= 2;
                tex.mipmaps.Add(d.getSection(off, s));
                off += s;
            }
            Console.WriteLine(off.ToString("x"));

            return(tex);
        }
Пример #11
0
        public void Read(FileData f, BNTX bntx) //Docs thanks to AboodXD!!
        {
            ImageKey         = "texture";
            SelectedImageKey = "texture";

            f.skip(4);

            int  BRTISize1 = f.readInt();
            long BRTISize2 = f.readInt64();

            surf = new TegraX1Swizzle.Surface();
            ushort Flags = (ushort)f.readShort();

            surf.dim      = (sbyte)f.readByte();
            surf.tileMode = (sbyte)f.readByte();
            surf.swizzle  = (ushort)f.readShort();
            surf.numMips  = (ushort)f.readShort();
            uint numSamples = (uint)f.readInt();

            surf.format = (uint)f.readInt();
            DataType    = (byte)(surf.format & 0xFF);
            uint accessFlags = (uint)f.readInt();

            surf.width  = f.readInt();
            surf.height = f.readInt();
            surf.depth  = f.readInt();
            int FaceCount = f.readInt();

            surf.sizeRange = f.readInt();
            uint unk38 = (uint)f.readInt();
            uint unk3C = (uint)f.readInt();
            uint unk40 = (uint)f.readInt();
            uint unk44 = (uint)f.readInt();
            uint unk48 = (uint)f.readInt();
            uint unk4C = (uint)f.readInt();

            surf.imageSize = f.readInt();
            surf.alignment = f.readInt();
            int ChannelType = f.readInt();
            int TextureType = f.readInt();

            Text = f.readString((int)f.readInt64() + BNTX.temp + 2, -1);
            long ParentOffset = f.readInt64();
            long PtrsOffset   = f.readInt64();

            format = surf.format;

            surf.data = new List <byte[]>();

            uint blk_dim = Formats.blk_dims(surf.format >> 8);

            blkWidth  = blk_dim >> 4;
            blkHeight = blk_dim & 0xF;

            f.seek((int)PtrsOffset + BNTX.temp);
            long firstMipOffset = f.readInt64();

            surf.data.Add(f.getSection((int)firstMipOffset + BNTX.temp, surf.imageSize));
            for (int mipLevel = 1; mipLevel < surf.numMips; mipLevel++)
            {
                long dataOff = f.readInt64();
                surf.data.Add(f.getSection((int)dataOff + BNTX.temp, (int)firstMipOffset + surf.imageSize - (int)dataOff));
                //    Debug.WriteLine($"{Name} Height {surf.height}wdith = {surf.width}allignment = {surf.alignment}blkwidth = {blkWidth}blkheight = {blkHeight}blkdims = {blk_dim} format = {surf.format} datatype = {DataType} dataoffset = {dataOff}");
            }
            bpp = Formats.bpps(surf.format >> 8);

            int target = 0;

            if (bntx.target == "NX  ")
            {
                target = 1;
            }

            int blockHeightLog2 = surf.sizeRange & 7;

            int linesPerBlockHeight = (1 << blockHeightLog2) * 8;
            int blockHeightShift    = 0;

            for (int mipLevel = 0; mipLevel < surf.numMips; mipLevel++)
            {
                uint width  = (uint)Math.Max(1, surf.width >> mipLevel);
                uint height = (uint)Math.Max(1, surf.height >> mipLevel);

                uint size = TegraX1Swizzle.DIV_ROUND_UP(width, blkWidth) * TegraX1Swizzle.DIV_ROUND_UP(height, blkHeight) * bpp;

                if (TegraX1Swizzle.pow2_round_up(TegraX1Swizzle.DIV_ROUND_UP(height, blkWidth)) < linesPerBlockHeight)
                {
                    blockHeightShift += 1;
                }

                byte[] result = TegraX1Swizzle.deswizzle(width, height, blkWidth, blkHeight, target, bpp, (uint)surf.tileMode, (uint)surf.alignment, Math.Max(0, blockHeightLog2 - blockHeightShift), surf.data[mipLevel], 0);
                //Create a copy and use that to remove uneeded data
                result_ = new byte[size];
                Array.Copy(result, 0, result_, 0, size);
                texture.mipmaps.Add(result_);
            }

            LoadFormats(texture, surf.format, 0, surf.width, surf.height);

            texture.width  = surf.width;
            texture.height = surf.height;

            Width  = surf.width;
            Height = surf.height;
        }
Пример #12
0
        public override void Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readShort();
                header.addressCount = f.readShort();
            }

            // Relocation table
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }

                f.seek((off * 4) + header.gpuCommandsOffset);
                if (header.backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();

            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }

            //Shaders (unused for now, until someone wants to add them)
            for (int index = 0; index < content.shadersPointerTableEntries; index++)
            {
                f.seek(content.shadersPointerTableOffset + (index * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);

                int shaderDataOffset = f.readInt();
                int shaderDataLength = f.readInt();
            }

            // Textures
            // WIP Section
            for (int index = 0; index < content.texturesPointerTableEntries; index++)
            {
                f.seek(content.texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                int textureCommandsOffset    = f.readInt();
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt(), -1);
                //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X"));
                f.seek(textureCommandsOffset);
                //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X"));
                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.height = f.readShort();
                tex.width  = f.readShort();
                f.skip(12);
                int doffset = f.readInt();
                //Debug.WriteLine("doffset: " + doffset.ToString("X"));
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);

                if (tex.type == 12)
                {
                    tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height));
                }
            }

            // Model data

            for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++)
            {
                f.seek(content.modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt();

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                model.materialsTableOffset  = f.readInt();
                model.materialsTableEntries = f.readInt();
                model.materialsNameOffset   = f.readInt();
                model.verticesTableOffset   = f.readInt();
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                model.verticesTableEntries = f.readInt();
                f.skip(0x28);
                model.skeletonOffset              = f.readInt();
                model.skeletonEntries             = f.readInt();
                model.skeletonNameOffset          = f.readInt();
                model.objectsNodeVisibilityOffset = f.readInt();
                model.objectsNodeCount            = f.readInt();
                model.name = f.readString(f.readInt(), -1);
                model.objectsNodeNameEntries = f.readInt();
                model.objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                model.metaDataPointerOffset = f.readInt();

                f.seek(model.objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[model.objectsNodeNameEntries];
                f.seek(model.objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt() + header.mainHeaderOffset;

                for (int i = 0; i < model.objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[model.materialsTableEntries];
                for (int index = 0; index < model.materialsTableEntries; index++)
                {
                    f.seek(model.materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt(), -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(model.verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                Debug.WriteLine(model.name);
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < model.verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    Console.WriteLine("Tex index" + mbn.mesh[index].texId);
                    f.skip(2); // flags
                    int nameId = f.readShort();
                    mbn.mesh[index].name = objectName[nameId];

                    // node visibility TODO: finish...
                    //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt();
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt();
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt();
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i] =  + mainheaderOffset

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }


                //Skeleton
                f.seek(model.skeletonOffset);
                for (int index = 0; index < model.skeletonEntries; index++)
                {
                    Bone bone      = new Smash_Forge.Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    f.skip(4); // Meta data

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
            }
        }
Пример #13
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);
                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.id = d.readInt();

                d.seek(gtxHeaderOffset);
                d.skip(0x04); // dim
                d.skip(0x04); // width
                d.skip(0x04); // height
                d.skip(0x04); // depth
                d.skip(0x04); // numMips
                int format = d.readInt();
                d.skip(0x04); // aa
                d.skip(0x04); // use
                int imageSize = d.readInt();
                d.skip(0x04); // imagePtr
                d.skip(0x04); // mipSize
                d.skip(0x04); // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);

                    //if (mipLevel == 0)
                    {
                        tex.mipmaps.Add(GTX.swizzleBC(
                                            d.getSection(dataOffset, mipSize),
                                            (tex.width >> mipLevel),
                                            (tex.height >> mipLevel),
                                            format,
                                            tileMode,
                                            pitch,
                                            swizzle
                                            ));
                    }

                    dataOffset += mipSize;
                }

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Пример #14
0
        public NutTexture ToNutTexture()
        {
            NutTexture tex = new NutTexture();

            tex.isDds  = true;
            tex.HashId = 0x48415348;
            tex.Height = (int)header.height;
            tex.Width  = (int)header.width;
            byte surfaceCount = 1;
            bool isCubemap    = (header.caps2 & (uint)DDSCAPS2.CUBEMAP) == (uint)DDSCAPS2.CUBEMAP;

            if (isCubemap)
            {
                if ((header.caps2 & (uint)DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDSCAPS2.CUBEMAP_ALLFACES)
                {
                    surfaceCount = 6;
                }
                else
                {
                    throw new NotImplementedException($"Unsupported cubemap face amount for texture. Six faces are required.");
                }
            }

            bool isBlock = true;

            switch (header.ddspf.fourCC)
            {
            case 0x00000000:     //RGBA
                isBlock = false;
                tex.pixelInternalFormat = PixelInternalFormat.Rgba;
                tex.pixelFormat         = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;

            case 0x31545844:     //DXT1
                tex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case 0x33545844:     //DXT3
                tex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                break;

            case 0x35545844:     //DXT5
                tex.pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;

            case 0x31495441:     //ATI1
            case 0x55344342:     //BC4U
                tex.pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
                break;

            case 0x32495441:     //ATI2
            case 0x55354342:     //BC5U
                tex.pixelInternalFormat = PixelInternalFormat.CompressedRgRgtc2;
                break;

            default:
                MessageBox.Show("Unsupported DDS format - 0x" + header.ddspf.fourCC.ToString("x"));
                break;
            }

            uint formatSize = getFormatSize(header.ddspf.fourCC);

            FileData d = new FileData(bdata);

            if (header.mipmapCount == 0)
            {
                header.mipmapCount = 1;
            }

            uint off = 0;

            for (byte i = 0; i < surfaceCount; ++i)
            {
                TextureSurface surface = new TextureSurface();
                uint           w = header.width, h = header.height;
                for (int j = 0; j < header.mipmapCount; ++j)
                {
                    //If texture is DXT5 and isn't square, limit the mipmaps to an amount such that width and height are each always >= 4
                    if (tex.pixelInternalFormat == PixelInternalFormat.CompressedRgbaS3tcDxt5Ext && tex.Width != tex.Height && (w < 4 || h < 4))
                    {
                        break;
                    }

                    uint s = (w * h); //Total pixels
                    if (isBlock)
                    {
                        s = (uint)(s * ((float)formatSize / 0x10)); //Bytes per 16 pixels
                        if (s < formatSize)                         //Make sure it's at least one block
                        {
                            s = formatSize;
                        }
                    }
                    else
                    {
                        s = (uint)(s * (formatSize)); //Bytes per pixel
                    }

                    w /= 2;
                    h /= 2;
                    surface.mipmaps.Add(d.getSection((int)off, (int)s));
                    off += s;
                }
                tex.surfaces.Add(surface);
            }

            return(tex);
        }
Пример #15
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(8);
            int mainHeaderOffset      = f.readInt();
            int stringTableOffset     = f.readInt();
            int gpuCommandOffset      = f.readInt();
            int dataOffset            = f.readInt();
            int dataExtendOffset      = f.readInt();
            int relocationTableOffset = f.readInt();

            int mainHeaderLength      = f.readInt();
            int stringTableLength     = f.readInt();
            int gpuCommandLength      = f.readInt();
            int dataLength            = f.readInt();
            int dataExtendLength      = f.readInt();
            int relocationTableLength = f.readInt();

            int datsSecLength = f.readInt();
            int desSecLength  = f.readInt();

            int flags        = f.readShort();
            int addressCount = f.readShort();

            // TODO: Finished Relocation table stuff
            for (int i = 0; i < relocationTableLength; i += 4)
            {
                f.seek(relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + mainHeaderOffset);

                    break;
                }
            }

            // Content Header
            f.seek(mainHeaderOffset);
            int modelsPointerTableOffset        = f.readInt() + mainHeaderOffset;
            int modelsPointerTableEntries       = f.readInt();
            int modelsNameOffset                = f.readInt() + mainHeaderOffset;
            int materialsPointerTableOffset     = f.readInt() + mainHeaderOffset;
            int materialsPointerTableEntries    = f.readInt();
            int materialsNameOffset             = f.readInt() + mainHeaderOffset;
            int shadersPointerTableOffset       = f.readInt() + mainHeaderOffset;
            int shadersPointerTableEntries      = f.readInt();
            int shadersNameOffset               = f.readInt() + mainHeaderOffset;
            int texturesPointerTableOffset      = f.readInt() + mainHeaderOffset;
            int texturesPointerTableEntries     = f.readInt();
            int texturesNameOffset              = f.readInt() + mainHeaderOffset;
            int materialsLUTPointerTableOffset  = f.readInt() + mainHeaderOffset;
            int materialsLUTPointerTableEntries = f.readInt();
            int materialsLUTNameOffset          = f.readInt() + mainHeaderOffset;
            int lightsPointerTableOffset        = f.readInt() + mainHeaderOffset;
            int lightsPointerTableEntries       = f.readInt();
            int lightsNameOffset                = f.readInt() + mainHeaderOffset;
            int camerasPointerTableOffset       = f.readInt() + mainHeaderOffset;
            int camerasPointerTableEntries      = f.readInt();
            int camerasNameOffset               = f.readInt() + mainHeaderOffset;
            int fogsPointerTableOffset          = f.readInt() + mainHeaderOffset;
            int fogsPointerTableEntries         = f.readInt();
            int fogsNameOffset = f.readInt() + mainHeaderOffset;
            int skeletalAnimationsPointerTableOffset    = f.readInt() + mainHeaderOffset;
            int skeletalAnimationsPointerTableEntries   = f.readInt();
            int skeletalAnimationsNameOffset            = f.readInt() + mainHeaderOffset;
            int materialAnimationsPointerTableOffset    = f.readInt() + mainHeaderOffset;
            int materialAnimationsPointerTableEntries   = f.readInt();
            int materialAnimationsNameOffset            = f.readInt() + mainHeaderOffset;
            int visibilityAnimationsPointerTableOffset  = f.readInt() + mainHeaderOffset;
            int visibilityAnimationsPointerTableEntries = f.readInt();
            int visibilityAnimationsNameOffset          = f.readInt() + mainHeaderOffset;
            int lightAnimationsPointerTableOffset       = f.readInt() + mainHeaderOffset;
            int lightAnimationsPointerTableEntries      = f.readInt();
            int lightAnimationsNameOffset           = f.readInt() + mainHeaderOffset;
            int cameraAnimationsPointerTableOffset  = f.readInt() + mainHeaderOffset;
            int cameraAnimationsPointerTableEntries = f.readInt();
            int cameraAnimationsNameOffset          = f.readInt() + mainHeaderOffset;
            int fogAnimationsPointerTableOffset     = f.readInt() + mainHeaderOffset;
            int fogAnimationsPointerTableEntries    = f.readInt();
            int fogAnimationsNameOffset             = f.readInt() + mainHeaderOffset;
            int scenePointerTableOffset             = f.readInt() + mainHeaderOffset;
            int scenePointerTableEntries            = f.readInt();
            int sceneNameOffset = f.readInt() + mainHeaderOffset;

            // Textures
            // WIP Section
            for (int index = 0; index < texturesPointerTableEntries; index++)
            {
                f.seek(texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset + mainHeaderOffset);

                int textureCommandsOffset    = f.readInt() + gpuCommandOffset;
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt() + stringTableOffset, -1);

                f.seek(textureCommandsOffset);

                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.height = f.readShort();
                tex.width  = f.readShort();
                f.skip(12);
                int doffset = f.readInt() + dataOffset;
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);
                if (tex.type == 12)
                {
                    tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height));
                }
            }

            // Model data
            for (int modelIndex = 0; modelIndex < modelsPointerTableEntries; modelIndex++)
            {
                f.seek(modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt() + mainHeaderOffset;

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt() + mainHeaderOffset;
                int materialsTableEntries = f.readInt();
                int materialsNamesOffset  = f.readInt() + mainHeaderOffset;
                int verticesTableOffset   = f.readInt() + mainHeaderOffset;
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                int verticesTableEntries = f.readInt();
                f.skip(0x28);
                int skeletonOffset              = f.readInt() + mainHeaderOffset;
                int skeletonEntries             = f.readInt();
                int skeletonNameOffset          = f.readInt() + mainHeaderOffset;
                int objectsNodeVisibilityOffset = f.readInt() + mainHeaderOffset;
                int objectsNodeCount            = f.readInt();
                model.name = f.readString(f.readInt() + stringTableOffset, -1);
                int objectsNodeNameEntries = f.readInt();
                int objectsNodeNameOffset  = f.readInt() + mainHeaderOffset;
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt() + mainHeaderOffset;

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt() + mainHeaderOffset;

                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt() + stringTableOffset, -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[materialsTableEntries];
                for (int index = 0; index < materialsTableEntries; index++)
                {
                    f.seek(materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt() + stringTableOffset, -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                Debug.WriteLine(model.name);
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    f.skip(2); // flags
                    int nameId = f.readShort();
                    mbn.mesh[index].name = objectName[nameId];

                    // node visibility TODO: finish...
                    //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt() + mainHeaderOffset;
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt() + mainHeaderOffset;
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt() + mainHeaderOffset;
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i] =  + mainheaderOffset

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }


                //Skeleton
                f.seek(skeletonOffset);
                for (int index = 0; index < skeletonEntries; index++)
                {
                    Bone bone      = new Smash_Forge.Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.boneName = f.readString(f.readInt() + stringTableOffset, -1).ToCharArray();

                    f.skip(4); // Meta data

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
            }
        }
Пример #16
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);

                // check for cubemap
                bool cmap = (d.readInt() == d.readInt());
                d.seek(d.pos() - 8);
                if (cmap)
                {
                    Console.WriteLine("cubemap detected");
                }

                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.id = d.readInt();

                d.seek(gtxHeaderOffset);
                d.skip(0x04); // dim
                d.skip(0x04); // width
                d.skip(0x04); // height
                d.skip(0x04); // depth
                d.skip(0x04); // numMips
                int format = d.readInt();
                d.skip(0x04); // aa
                d.skip(0x04); // use
                int imageSize = d.readInt();
                d.skip(0x04); // imagePtr
                d.skip(0x04); // mipSize
                d.skip(0x04); // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);
                    int p       = pitch >> mipLevel;

                    //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
                    //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

                    //if (cmap) tex.height *= 2;

                    int w = (tex.width >> mipLevel);
                    int h = (tex.height >> mipLevel);

                    //if (mipSize % 0x10 != 0) mipSize += mipSize % 0x10;
                    //if (cmap) mipSize /= 6;

                    //if (p <= 16) p = 64;
                    {
                        tex.mipmaps.Add(GTX.swizzleBC(
                                            d.getSection(dataOffset, mipSize),
                                            w,
                                            h,
                                            format,
                                            tileMode,
                                            p,
                                            swizzle
                                            ));
                    }
                    dataOffset += mipSize;

                    /*if (cmap)
                     * {
                     *  for(int k = 0; k < 5; k++)
                     *  {
                     *      p = pitch >> (mipLevel + k + 1);
                     *      tex.mipmaps.Add(GTX.swizzleBC(
                     *          d.getSection(dataOffset, mipSize),
                     *          w,
                     *          h,
                     *          format,
                     *          tileMode,
                     *          p,
                     *          swizzle
                     *      ));
                     *
                     *      dataOffset += mipSize;
                     *  }
                     * }*/

                    //while (dataOffset % 1024 != 0) dataOffset++;
                    //if (mipSize == 0x4000) dataOffset += 0x400;
                }

                // fix mipmap swizzle for rgba types
                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    Console.WriteLine("Endian swap");
                    // swap
                    foreach (byte[] mip in tex.mipmaps)
                    {
                        for (int t = 0; t < mip.Length; t += 4)
                        {
                            /*byte t1 = mip[t];
                             * byte t2 = mip[t+1];
                             * mip[t] = mip[t + 3];
                             * mip[t + 1] = mip[t + 2];
                             * mip[t + 2] = t2;
                             * mip[t + 3] = t1;*/
                        }
                    }
                }

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Пример #17
0
        public void ReadNTP3(FileData d)
        {
            d.skip(0x2);
            int count = d.readShort();

            d.skip(0x8);

            int dataPtr = 0;

            for (int i = 0; i < count; i++)
            {
                Debug.WriteLine(d.pos().ToString("x"));
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4); // padding

                int dataSize   = d.readInt();
                int headerSize = d.readShort();
                d.skip(3);
                int numMips = d.readByte();
                Debug.WriteLine(numMips);
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // padding?

                int dataOffset = d.readInt() + dataPtr + 0x10;
                d.skip(0x0C);

                int[] mipSizes = new int[numMips];

                if (numMips == 1)
                {
                    mipSizes[0] = dataSize;
                }
                else
                {
                    for (int j = 0; j < numMips; j++)
                    {
                        mipSizes[j] = d.readInt();
                    }
                }
                d.align(16);

                d.skip(0x18);
                tex.id = d.readInt();
                d.skip(4); // padding align 8

                // add mipmap data
                for (int miplevel = 0; miplevel < numMips; miplevel++)
                {
                    byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);
                    tex.mipmaps.Add(texArray);
                    dataOffset += mipSizes[miplevel];
                }

                dataPtr += headerSize;

                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    Console.WriteLine("Endian swap");
                    // swap
                    foreach (byte[] mip in tex.mipmaps)
                    {
                        for (int t = 0; t < mip.Length; t += 4)
                        {
                            byte t1 = mip[t];
                            mip[t]     = mip[t + 1];
                            mip[t + 1] = mip[t + 2];
                            mip[t + 2] = mip[t + 3];
                            mip[t + 3] = t1;

                            /*byte t1 = mip[t];
                             * byte t2 = mip[t+1];
                             * mip[t] = mip[t + 3];
                             * mip[t + 1] = mip[t + 2];
                             * mip[t + 2] = t2;
                             * mip[t + 3] = t1;*/
                        }
                    }
                }

                textures.Add(tex);

                /*for (int miplevel = 0; miplevel < numMips; miplevel++)
                 * {
                 *  byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);
                 *
                 *  if (tex.getNutFormat() == 14)
                 *  {
                 *      byte[] oldArray = texArray;
                 *      for (int pos = 0; pos < mipSizes[miplevel]; pos+=4)
                 *      {
                 *
                 *          for (int p = 0; p < 4; p++)
                 *          {
                 *              if (p == 0)
                 *                  texArray[pos + 3] = oldArray[pos];
                 *              else
                 *                  texArray[pos + p - 1] = oldArray[pos + p];
                 *          }
                 *
                 *      }
                 *  }
                 *  tex.mipmaps.Add(texArray);
                 *  dataOffset += mipSizes[miplevel];
                 * }*/
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex, true));
                }
            }
        }
Пример #18
0
        public void ReadNTWU(FileData d)
        {
            d.seek(0x4);

            Version = d.readUShort();
            ushort count = d.readUShort();

            d.skip(0x8);
            int headerPtr = 0x10;

            for (ushort i = 0; i < count; ++i)
            {
                d.seek(headerPtr);

                NutTexture tex = new NutTexture();
                tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4);
                int dataSize   = d.readInt();
                int headerSize = d.readUShort();
                d.skip(2);

                d.skip(1);
                byte mipmapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.readInt(); //Always 1?
                uint caps2 = d.readUInt();

                bool isCubemap    = false;
                byte surfaceCount = 1;
                if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP)
                {
                    //Only supporting all six faces
                    if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
                    {
                        isCubemap    = true;
                        surfaceCount = 6;
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required.");
                    }
                }

                int dataOffset      = d.readInt() + headerPtr;
                int mipDataOffset   = d.readInt() + headerPtr;
                int gtxHeaderOffset = d.readInt() + headerPtr;
                d.readInt();

                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int imageSize = 0; //Total size of first mipmap of every surface
                int mipSize   = 0; //Total size of mipmaps other than the first of every surface
                if (mipmapCount == 1)
                {
                    if (isCubemap)
                    {
                        imageSize = cmapSize1;
                    }
                    else
                    {
                        imageSize = dataSize;
                    }
                }
                else
                {
                    imageSize = d.readInt();
                    mipSize   = d.readInt();
                    d.skip((mipmapCount - 2) * 4);
                    d.align(0x10);
                }

                d.skip(0x10); //eXt data - always the same

                d.skip(4);    //GIDX
                d.readInt();  //Always 0x10
                tex.HashId = d.readInt();
                d.skip(4);    // padding align 8

                d.seek(gtxHeaderOffset);
                GTX.GX2Surface gtxHeader = new GTX.GX2Surface();

                gtxHeader.dim       = d.readInt();
                gtxHeader.width     = d.readInt();
                gtxHeader.height    = d.readInt();
                gtxHeader.depth     = d.readInt();
                gtxHeader.numMips   = d.readInt();
                gtxHeader.format    = d.readInt();
                gtxHeader.aa        = d.readInt();
                gtxHeader.use       = d.readInt();
                gtxHeader.imageSize = d.readInt();
                gtxHeader.imagePtr  = d.readInt();
                gtxHeader.mipSize   = d.readInt();
                gtxHeader.mipPtr    = d.readInt();
                gtxHeader.tileMode  = d.readInt();
                gtxHeader.swizzle   = d.readInt();
                gtxHeader.alignment = d.readInt();
                gtxHeader.pitch     = d.readInt();

                //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset)
                //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1])
                //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i])
                int[] mipOffsets = new int[mipmapCount];
                mipOffsets[0] = 0;
                for (byte mipLevel = 1; mipLevel < mipmapCount; ++mipLevel)
                {
                    mipOffsets[mipLevel] = 0;
                    mipOffsets[mipLevel] = mipOffsets[1] + d.readInt();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    tex.surfaces.Add(new TextureSurface());
                }

                int w = tex.Width, h = tex.Height;
                for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                {
                    int p = gtxHeader.pitch / (gtxHeader.width / w);

                    int size;
                    if (mipmapCount == 1)
                    {
                        size = imageSize;
                    }
                    else if (mipLevel + 1 == mipmapCount)
                    {
                        size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel];
                    }
                    else
                    {
                        size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel];
                    }

                    size /= surfaceCount;

                    for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                    {
                        gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size);

                        //Real size
                        //Leave the below line commented for now because it breaks RGBA textures
                        //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8);
                        if (size < (GTX.getBPP(gtxHeader.format) / 8))
                        {
                            size = (GTX.getBPP(gtxHeader.format) / 8);
                        }

                        byte[] deswiz = GTX.swizzleBC(
                            gtxHeader.data,
                            w,
                            h,
                            gtxHeader.format,
                            gtxHeader.tileMode,
                            p,
                            gtxHeader.swizzle
                            );
                        tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size));
                    }

                    w /= 2;
                    h /= 2;

                    if (w < 1)
                    {
                        w = 1;
                    }
                    if (h < 1)
                    {
                        h = 1;
                    }
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }
        }
Пример #19
0
        public void ReadNTP3(FileData d)
        {
            d.seek(0x4);

            Version = d.readUShort();
            ushort count = d.readUShort();

            if (Version == 0x100)
            {
                count -= 1;
            }

            d.skip(0x8);
            int headerPtr = 0x10;

            for (ushort i = 0; i < count; ++i)
            {
                d.seek(headerPtr);

                NutTexture tex = new NutTexture();
                tex.isDds = true;
                tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4);
                int dataSize   = d.readInt();
                int headerSize = d.readUShort();
                d.skip(2);

                //It might seem that mipmapCount and pixelFormat would be shorts, but they're bytes because they stay in the same place regardless of endianness
                d.skip(1);
                byte mipmapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.skip(4);
                uint caps2 = d.readUInt();

                bool isCubemap    = false;
                byte surfaceCount = 1;
                if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP)
                {
                    //Only supporting all six faces
                    if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
                    {
                        isCubemap    = true;
                        surfaceCount = 6;
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required.");
                    }
                }

                int dataOffset = d.readInt() + headerPtr;
                d.readInt();
                d.readInt();
                d.readInt();

                //The size of a single cubemap face (discounting mipmaps). I don't know why it is repeated. If mipmaps are present, this is also specified in the mipSize section anyway.
                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int[] mipSizes = new int[mipmapCount];
                if (mipmapCount == 1)
                {
                    if (isCubemap)
                    {
                        mipSizes[0] = cmapSize1;
                    }
                    else
                    {
                        mipSizes[0] = dataSize;
                    }
                }
                else
                {
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        mipSizes[mipLevel] = d.readInt();
                    }
                    d.align(0x10);
                }

                d.skip(0x10); //eXt data - always the same

                d.skip(4);    //GIDX
                d.readInt();  //Always 0x10
                tex.HashId = d.readInt();
                d.skip(4);    // padding align 8

                if (Version == 0x100)
                {
                    dataOffset = d.pos();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    TextureSurface surface = new TextureSurface();
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        byte[] texArray = d.getSection(dataOffset, mipSizes[mipLevel]);
                        surface.mipmaps.Add(texArray);
                        dataOffset += mipSizes[mipLevel];
                    }
                    tex.surfaces.Add(surface);
                }

                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    tex.SwapChannelOrderUp();
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }
        }
Пример #20
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;
            f.skip(4);
            int backwardCompatibility = f.readByte();
            int forwardCompatibility  = f.readByte();
            int version = f.readShort();

            int mainHeaderOffset   = f.readInt();
            int stringTableOffset  = f.readInt();
            int gpuCommandsOffset  = f.readInt();
            int dataOffset         = f.readInt();
            int dataExtendedOffset = 0;
            int dataExtendedLength = 0;

            if (backwardCompatibility > 0x20)
            {
                dataExtendedOffset = f.readInt();
            }
            int relocationTableOffset = f.readInt();

            int mainHeaderLength  = f.readInt();
            int stringTableLength = f.readInt();
            int gpuCommandsLength = f.readInt();
            int dataLength        = f.readInt();

            if (backwardCompatibility > 0x20)
            {
                dataExtendedLength = f.readInt();
            }
            int relocationTableLength = f.readInt();

            int uninitializedDataSectionLength        = f.readInt();
            int uninitializedDescriptionSectionLength = f.readInt();

            if (backwardCompatibility > 7)
            {
                int flags        = f.readShort();
                int addressCount = f.readShort();
            }

            // Relocation table
            for (int i = 0; i < relocationTableLength; i += 4)
            {
                f.seek(relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + mainHeaderOffset);
                    f.writeInt((off) + mainHeaderOffset, f.readInt() + stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + dataOffset);
                    break;
                }

                f.seek((off * 4) + gpuCommandsOffset);
                if (backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + int gpuCommandsOffset, ((f.readInt() + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + int dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }

            File.WriteAllBytes(filename + "_offset", f.getSection(0, f.size()));

            f.seek(mainHeaderOffset);
            int modelsPointerTableOffset        = f.readInt();
            int modelsPointerTableEntries       = f.readInt();
            int modelsNameOffset                = f.readInt();
            int materialsPointerTableOffset     = f.readInt();
            int materialsPointerTableEntries    = f.readInt();
            int materialsNameOffset             = f.readInt();
            int shadersPointerTableOffset       = f.readInt();
            int shadersPointerTableEntries      = f.readInt();
            int shadersNameOffset               = f.readInt();
            int texturesPointerTableOffset      = f.readInt();
            int texturesPointerTableEntries     = f.readInt();
            int texturesNameOffset              = f.readInt();
            int materialsLUTPointerTableOffset  = f.readInt();
            int materialsLUTPointerTableEntries = f.readInt();
            int materialsLUTNameOffset          = f.readInt();
            int lightsPointerTableOffset        = f.readInt();
            int lightsPointerTableEntries       = f.readInt();
            int lightsNameOffset                = f.readInt();
            int camerasPointerTableOffset       = f.readInt();
            int camerasPointerTableEntries      = f.readInt();
            int camerasNameOffset               = f.readInt();
            int fogsPointerTableOffset          = f.readInt();
            int fogsPointerTableEntries         = f.readInt();
            int fogsNameOffset = f.readInt();
            int skeletalAnimationsPointerTableOffset    = f.readInt();
            int skeletalAnimationsPointerTableEntries   = f.readInt();
            int skeletalAnimationsNameOffset            = f.readInt();
            int materialAnimationsPointerTableOffset    = f.readInt();
            int materialAnimationsPointerTableEntries   = f.readInt();
            int materialAnimationsNameOffset            = f.readInt();
            int visibilityAnimationsPointerTableOffset  = f.readInt();
            int visibilityAnimationsPointerTableEntries = f.readInt();
            int visibilityAnimationsNameOffset          = f.readInt();
            int lightAnimationsPointerTableOffset       = f.readInt();
            int lightAnimationsPointerTableEntries      = f.readInt();
            int lightAnimationsNameOffset           = f.readInt();
            int cameraAnimationsPointerTableOffset  = f.readInt();
            int cameraAnimationsPointerTableEntries = f.readInt();
            int cameraAnimationsNameOffset          = f.readInt();
            int fogAnimationsPointerTableOffset     = f.readInt();
            int fogAnimationsPointerTableEntries    = f.readInt();
            int fogAnimationsNameOffset             = f.readInt();
            int scenePointerTableOffset             = f.readInt();
            int scenePointerTableEntries            = f.readInt();
            int sceneNameOffset = f.readInt();

            Console.WriteLine(modelsPointerTableEntries > 0 ? "Has Models" : "");
            Console.WriteLine(shadersPointerTableEntries > 0 ? "Has Shaders" : "");
            Console.WriteLine(texturesPointerTableEntries > 0 ? "Has Textures" : "");
            Console.WriteLine(materialsPointerTableEntries > 0 ? "Has Materials" : "");
            Console.WriteLine(materialsLUTPointerTableEntries > 0 ? "Has Material LUT" : "");
            Console.WriteLine(materialAnimationsPointerTableEntries > 0 ? "Has Material Animation" : "");
            Console.WriteLine(lightsPointerTableEntries > 0 ? "Has Lights" : "");
            Console.WriteLine(lightAnimationsPointerTableEntries > 0 ? "Has LightAnimations" : "");
            Console.WriteLine(camerasPointerTableEntries > 0 ? "Has Camera" : "");
            Console.WriteLine(cameraAnimationsPointerTableEntries > 0 ? "Has CameraAnimation" : "");
            Console.WriteLine(fogsPointerTableEntries > 0 ? "Has Fog" : "");
            Console.WriteLine(fogAnimationsPointerTableEntries > 0 ? "Has FogAnimation" : "");
            Console.WriteLine(skeletalAnimationsPointerTableEntries > 0 ? "Has Skeletal Animations" : "");
            Console.WriteLine(visibilityAnimationsPointerTableEntries > 0 ? "Has Visibility" : "");
            Console.WriteLine(scenePointerTableEntries > 0 ? "Has Scene" : "");

            // Textures
            for (int index = 0; index < texturesPointerTableEntries; index++)
            {
                f.seek(texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                // one for each mip I assume
                int textureCommandsOffset     = f.readInt();
                int textureCommandsWordCount  = f.readInt();
                int textureCommandsOffset2    = f.readInt();
                int textureCommandsWordCount2 = f.readInt();
                int textureCommandsOffset3    = f.readInt();
                int textureCommandsWordCount3 = f.readInt();

                int unk = f.readInt();

                BCH_Texture tex = new BCH_Texture();
                tex.Text = f.readString(f.readInt(), -1);
                Textures.Nodes.Add(tex);

                f.seek(textureCommandsOffset);
                tex.ReadParameters(f, textureCommandsWordCount);
            }


            //Models

            for (int index = 0; index < modelsPointerTableEntries; index++)
            {
                f.seek(modelsPointerTableOffset + (index * 4));

                f.seek(f.readInt());

                BCH_Model model = new BCH_Model();
                Models.Nodes.Add(model);
                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();
                model.worldTransform            = new OpenTK.Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt();
                int materialsTableEntries = f.readInt();
                int materialNameOffset    = f.readInt();
                int verticesTableOffset   = f.readInt();
                int verticesTableEntries  = f.readInt();
                f.skip(0x28);
                int skeletonOffset              = f.readInt();
                int skeletonEntries             = f.readInt();
                int skeletonNameOffset          = f.readInt();
                int objectsNodeVisibilityOffset = f.readInt();
                int objectsNodeCount            = f.readInt();
                model.Text = f.readString(f.readInt(), -1);
                int objectsNodeNameEntries = f.readInt();
                int objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt();

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt();
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt();

                Console.WriteLine(f.readString(rootNameOffset, -1) + " " + rootLeftNode + " " + rootRightNode);
                // Object name tree
                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    Console.WriteLine(i + " " + objectName[i] + " " + leftNode + " " + rightNode);
                }

                //TODO: Metadata, boundingbox, normal mesh, materials
                f.seek(verticesTableOffset);
                for (int i = 0; i < verticesTableEntries; i++)
                {
                    BCH_Mesh Mesh = new BCH_Mesh();
                    model.Nodes.Add(Mesh);
                    Mesh.MaterialIndex = f.readShort();
                    int mflags = f.readShort();
                    int nameId = f.readShort();
                    Mesh.Text = objectName[nameId];

                    // node visibility TODO: finish...
                    Mesh.Checked = ((nodeVisibility & (1 << nameId)) > 0);

                    Mesh.renderPriority = f.readShort();

                    int vshAttBufferCommandOffset = f.readInt();
                    int vshAttBufferCommandCount  = f.readInt();
                    int faceOffset = f.readInt();
                    int faceCount  = f.readInt();
                    int vshAttBufferCommandOffsetEx = f.readInt();
                    int vshAttBufferCommandCountEx  = f.readInt();

                    Vector3 Center     = new Vector3(f.readFloat(), f.readFloat(), f.readFloat());
                    int     flagoffset = f.readInt(); // flagsOffset
                    f.skip(4);                        // 0?
                    int boundingBoxOffset = f.readInt();
                }


                //Materials
                Console.WriteLine(materialsTableOffset.ToString("x") + " " + materialsPointerTableOffset.ToString("x"));
                for (int i = 0; i < materialsTableEntries; i++)
                {
                    f.seek(materialsTableOffset + (i * 0x2c));
                    int paramOffset = f.readInt();
                    f.skip(12); // other offsets
                    int texCommandOffset = f.readInt();
                    int texCommandCount  = f.readInt();
                    int mapperOffset     = f.readInt();

                    BCH_Material mat = new BCH_Material();
                    Materials.Nodes.Add(mat);
                    mat.Text = f.readString(f.readInt(), -1);
                    Console.WriteLine(mat.Text);
                    //Console.WriteLine(f.readString(f.readInt(), -1));
                    //Console.WriteLine(f.readString(f.readInt(), -1));
                    //Console.WriteLine(f.readString(f.readInt(), -1));

                    // TODO: Parameters
                }


                //Skeleton
                f.seek(skeletonOffset);
                for (int bindex = 0; bindex < skeletonEntries; bindex++)
                {
                    Bone bone      = new Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    int metaDataPointerOffset2 = f.readInt();
                    if (metaDataPointerOffset2 != 0)
                    {
                        int position = f.pos();
                        f.seek(metaDataPointerOffset2);
                        //bone.userData = getMetaData(input);
                        f.seek(position);
                    }

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
                model.skeleton.update();
            }
        }
Пример #21
0
        public override void Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readShort();
                header.addressCount = f.readShort();
            }

            // TODO: Finished Relocation table stuff
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }

                /*f.seek((off * 4) + header.gpuCommandsOffset);
                 * if (header.backwardCompatibility < 6)
                 * {
                 *  switch (flag)
                 *  {
                 *      case 0x23: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Texture
                 *      case 0x25: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Vertex
                 *      // Trying to understand the mess first
                 *      case 0x26: f.writeInt((off * 4) + header.mainHeaderOffset, Convert.ToInt32(((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000)); break; //Index 16 bits mode
                 *                                                                                                                                                           //case 0x27: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode
                 *  }
                 * }
                 *              else if (header.backwardCompatibility < 8)
                 *              {
                 *                  switch (flag)
                 *                  {
                 *                      case 0x24: writer.Write(peek(input) + header.dataOffset); break; //Texture
                 *                      case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex
                 *                      case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                 *                      case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode
                 *                  }
                 *              }
                 *              else if (header.backwardCompatibility < 0x21)
                 *              {
                 *                  switch (flag)
                 *                  {
                 *                      case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture
                 *                      case 0x27: writer.Write(peek(input) + header.dataOffset); break; //Vertex
                 *                      case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                 *                      case 0x29: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode
                 *                  }
                 *              }
                 *              else
                 *              {
                 *                  switch (flag)
                 *                  {
                 *                      case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture
                 *                      case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex relative to Data Offset
                 *                      case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                 *                      case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset
                 *                      case 0x2b: writer.Write(peek(input) + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset
                 *                      case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                 *                      case 0x2d: writer.Write((peek(input) + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset
                 *                  }
                 *              }
                 */
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();

            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }

            //Shaders (unused for now, until someone wants to add them)
            for (int index = 0; index < content.shadersPointerTableEntries; index++)
            {
                f.seek(content.shadersPointerTableOffset + (index * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);

                int shaderDataOffset = f.readInt();
                int shaderDataLength = f.readInt();
            }

            // Textures
            // WIP Section
            for (int index = 0; index < content.texturesPointerTableEntries; index++)
            {
                f.seek(content.texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);
                Debug.WriteLine("dOffset: " + dOffset.ToString("X"));
                int textureCommandsOffset    = f.readInt();
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt(), -1);
                //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X"));
                f.seek(textureCommandsOffset);
                //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X"));
                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.height = f.readShort();
                tex.width  = f.readShort();
                f.skip(12);
                int doffset = f.readInt();
                //Debug.WriteLine("doffset: " + doffset.ToString("X"));
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);

                if (tex.type == 12)
                {
                    tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height));
                }
            }

            // Model data

            for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++)
            {
                f.seek(content.modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt();

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                model.materialsTableOffset  = f.readInt();
                model.materialsTableEntries = f.readInt();
                model.materialsNameOffset   = f.readInt();
                model.verticesTableOffset   = f.readInt();
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                model.verticesTableEntries = f.readInt();
                f.skip(0x28);
                model.skeletonOffset              = f.readInt();
                model.skeletonEntries             = f.readInt();
                model.skeletonNameOffset          = f.readInt();
                model.objectsNodeVisibilityOffset = f.readInt();
                model.objectsNodeCount            = f.readInt();
                model.name = f.readString(f.readInt(), -1);
                model.objectsNodeNameEntries = f.readInt();
                model.objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                model.metaDataPointerOffset = f.readInt();

                f.seek(model.objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[model.objectsNodeNameEntries];
                f.seek(model.objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt() + header.mainHeaderOffset;

                for (int i = 0; i < model.objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[model.materialsTableEntries];
                for (int index = 0; index < model.materialsTableEntries; index++)
                {
                    f.seek(model.materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt(), -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(model.verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                Debug.WriteLine(model.name);
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < model.verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    Console.WriteLine("Tex index" + mbn.mesh[index].texId);
                    f.skip(2); // flags
                    int nameId = f.readShort();
                    mbn.mesh[index].name = objectName[nameId];

                    // node visibility TODO: finish...
                    //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt();
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt();
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt();
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i] =  + mainheaderOffset

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }


                //Skeleton
                f.seek(model.skeletonOffset);
                for (int index = 0; index < model.skeletonEntries; index++)
                {
                    Bone bone      = new Smash_Forge.Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.boneName = f.readString(f.readInt(), -1).ToCharArray();

                    f.skip(4); // Meta data

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();

/*                //Skeletal Animations
 *
 *              SkelAnimation anim = new SkelAnimation();
 *
 *              for (int index = 0; index < content.skeletalAnimationsPointerTableEntries; index++)
 *               {
 *                  f.seek(content.skeletalAnimationsPointerTableOffset + (index * 4));
 *                  int dataOffset = f.readInt();
 *                  f.seek(dataOffset);
 *
 *                  RenderBase.OSkeletalAnimation skeletalAnimation = new RenderBase.OSkeletalAnimation();
 *
 *                  skeletalAnimation.name = f.readString(f.readInt(), -1);
 *                  int animationFlags = f.readInt();
 *                  skeletalAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1);
 *                  skeletalAnimation.frameSize = f.readFloat();
 *                  int boneTableOffset = f.readInt();
 *                  int boneTableEntries = f.readInt();
 *                  int metaDataPointerOffset = f.readInt();
 *
 * //                    /*if (metaDataPointerOffset != 0)
 * //                    {
 * //                        data.Seek(metaDataPointerOffset, SeekOrigin.Begin);
 * //                        skeletalAnimation.userData = getMetaData(input);
 * //                    }
 *
 *                  for (int i = 0; i < boneTableEntries; i++)
 *                  {
 *                      f.seek(boneTableOffset + (i * 4));
 *                      int offset = f.readInt();
 *
 *                      RenderBase.OSkeletalAnimationBone bone = new RenderBase.OSkeletalAnimationBone();
 *
 *                      f.seek(offset);
 *                      bone.name = f.readString(f.readInt(), -1);
 *                      int animationTypeFlags = f.readInt();
 *
 *                      int flags = f.readInt();
 *
 *                      RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf);
 *                                      switch (segmentType)
 *                                      {
 *                          case RenderBase.OSegmentType.transform:
 *                              f.seek(offset + 0x18);
 *
 *                              uint notExistMask = 0x80000;
 *                              uint constantMask = 0x200;
 *
 *                              for (int j = 0; j < 2; j++)
 *                              {
 *                                  for (int axis = 0; axis < 3; axis++)
 *                                  {
 *                                      bool notExist = (flags & notExistMask) > 0;
 *                                      bool constant = (flags & constantMask) > 0;
 *
 *                                      RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup();
 *                                      frame.exists = !notExist;
 *                                      if (frame.exists)
 *                                      {
 *                                          if (constant)
 *                                          {
 *                                              frame.interpolation = RenderBase.OInterpolationMode.linear;
 *                                              frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0));
 *                                          }
 *                                          else
 *                                          {
 *                                              int frameOffset = f.readInt();
 *                                              long position = data.Position;
 *                                              f.seek(frameOffset);
 *                                              getAnimationKeyFrame(input, frame);
 *                                              f.seek(position);
 *                                          }
 *                                      }
 *                                      else
 *                                          data.Seek(4, SeekOrigin.Current);
 *
 *                                      if (j == 0)
 *                                      {
 *                                          switch (axis)
 *                                          {
 *                                              case 0: bone.rotationX = frame; break;
 *                                              case 1: bone.rotationY = frame; break;
 *                                              case 2: bone.rotationZ = frame; break;
 *                                          }
 *                                      }
 *                                      else
 *                                      {
 *                                          switch (axis)
 *                                          {
 *                                              case 0: bone.translationX = frame; break;
 *                                              case 1: bone.translationY = frame; break;
 *                                              case 2: bone.translationZ = frame; break;
 *                                          }
 *                                      }
 *
 *                                      notExistMask <<= 1;
 *                                      constantMask <<= 1;
 *                                  }
 *
 *                                  constantMask <<= 1;
 *                              }
 *
 *                              break;
 *                          case RenderBase.OSegmentType.transformQuaternion:
 *                              bone.isFrameFormat = true;
 *
 *                              uint scaleOffset = input.ReadUInt32();
 *                              uint rotationOffset = input.ReadUInt32();
 *                              uint translationOffset = input.ReadUInt32();
 *
 *                              if ((flags & 0x20) == 0)
 *                              {
 *                                  bone.scale.exists = true;
 *                                  data.Seek(scaleOffset, SeekOrigin.Begin);
 *
 *                                  if ((flags & 4) > 0)
 *                                  {
 *                                      bone.scale.vector.Add(new RenderBase.OVector4(
 *                                          input.ReadSingle(),
 *                                          input.ReadSingle(),
 *                                          input.ReadSingle(),
 *                                          0));
 *                                  }
 *                                  else
 *                                  {
 *                                      bone.scale.startFrame = input.ReadSingle();
 *                                      bone.scale.endFrame = input.ReadSingle();
 *
 *                                      uint scaleFlags = input.ReadUInt32();
 *                                      uint scaleDataOffset = input.ReadUInt32();
 *                                      uint scaleEntries = input.ReadUInt32();
 *
 *                                      data.Seek(scaleDataOffset, SeekOrigin.Begin);
 *                                      for (int j = 0; j < scaleEntries; j++)
 *                                      {
 *                                          bone.scale.vector.Add(new RenderBase.OVector4(
 *                                              input.ReadSingle(),
 *                                              input.ReadSingle(),
 *                                              input.ReadSingle(),
 *                                              0));
 *                                      }
 *                                  }
 *                              }
 *
 *                              if ((flags & 0x10) == 0)
 *                                              {
 *                                                  bone.rotationQuaternion.exists = true;
 *                                                  data.Seek(rotationOffset, SeekOrigin.Begin);
 *
 *                                                  if ((flags & 2) > 0)
 *                                                  {
 *                                                      bone.rotationQuaternion.vector.Add(new RenderBase.OVector4(
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle()));
 *                                                  }
 *                                                  else
 *                                                  {
 *                                                      bone.rotationQuaternion.startFrame = input.ReadSingle();
 *                                                      bone.rotationQuaternion.endFrame = input.ReadSingle();
 *
 *                                                      uint rotationFlags = input.ReadUInt32();
 *                                                      uint rotationDataOffset = input.ReadUInt32();
 *                                                      uint rotationEntries = input.ReadUInt32();
 *
 *                                                      data.Seek(rotationDataOffset, SeekOrigin.Begin);
 *                                                      for (int j = 0; j < rotationEntries; j++)
 *                                                      {
 *                                                          bone.rotationQuaternion.vector.Add(new RenderBase.OVector4(
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle()));
 *                                                      }
 *                                                  }
 *                                              }
 *
 *                                              if ((flags & 8) == 0)
 *                                              {
 *                                                  bone.translation.exists = true;
 *                                                  data.Seek(translationOffset, SeekOrigin.Begin);
 *
 *                                                  if ((flags & 1) > 0)
 *                                                  {
 *                                                      bone.translation.vector.Add(new RenderBase.OVector4(
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          0));
 *                                                  }
 *                                                  else
 *                                                  {
 *                                                      bone.translation.startFrame = input.ReadSingle();
 *                                                      bone.translation.endFrame = input.ReadSingle();
 *
 *                                                      uint translationFlags = input.ReadUInt32();
 *                                                      uint translationDataOffset = input.ReadUInt32();
 *                                                      uint translationEntries = input.ReadUInt32();
 *
 *                                                      data.Seek(translationDataOffset, SeekOrigin.Begin);
 *                                                      for (int j = 0; j < translationEntries; j++)
 *                                                      {
 *                                                          bone.translation.vector.Add(new RenderBase.OVector4(
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              0));
 *                                                      }
 *                                                  }
 *                                              }
 *
 *                                              break;
 *                                          case RenderBase.OSegmentType.transformMatrix:
 *                                              bone.isFullBakedFormat = true;
 *
 *                                              input.ReadUInt32();
 *                                              input.ReadUInt32();
 *                                              uint matrixOffset = input.ReadUInt32();
 *                                              uint entries = input.ReadUInt32();
 *
 *                                              data.Seek(matrixOffset, SeekOrigin.Begin);
 *                                              for (int j = 0; j < entries; j++)
 *                                              {
 *                                                  RenderBase.OMatrix transform = new RenderBase.OMatrix();
 *                                                  transform.M11 = input.ReadSingle();
 *                                                  transform.M21 = input.ReadSingle();
 *                                                  transform.M31 = input.ReadSingle();
 *                                                  transform.M41 = input.ReadSingle();
 *
 *                                                  transform.M12 = input.ReadSingle();
 *                                                  transform.M22 = input.ReadSingle();
 *                                                  transform.M32 = input.ReadSingle();
 *                                                  transform.M42 = input.ReadSingle();
 *
 *                                                  transform.M13 = input.ReadSingle();
 *                                                  transform.M23 = input.ReadSingle();
 *                                                  transform.M33 = input.ReadSingle();
 *                                                  transform.M43 = input.ReadSingle();
 *
 *                                                  bone.transform.Add(transform);
 *                                              }
 *
 *                                              break;
 *                                          default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name));
 *                                      }
 *
 *                                      skeletalAnimation.bone.Add(bone);
 *                                  }
 *
 *                                  models.skeletalAnimation.list.Add(skeletalAnimation);
 *                              }
 *
 *                              //Material Animations
 *                              for (int index = 0; index < contentHeader.materialAnimationsPointerTableEntries; index++)
 *                              {
 *                                  data.Seek(contentHeader.materialAnimationsPointerTableOffset + (index * 4), SeekOrigin.Begin);
 *                                  uint dataOffset = input.ReadUInt32();
 *                                  data.Seek(dataOffset, SeekOrigin.Begin);
 *
 *                                  RenderBase.OMaterialAnimation materialAnimation = new RenderBase.OMaterialAnimation();
 *
 *                                  materialAnimation.name = readString(input);
 *                                  uint animationFlags = input.ReadUInt32();
 *                                  materialAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1);
 *                                  materialAnimation.frameSize = input.ReadSingle();
 *                                  uint dataTableOffset = input.ReadUInt32();
 *                                  uint dataTableEntries = input.ReadUInt32();
 *                                  input.ReadUInt32();
 *                                  uint textureNameTableOffset = input.ReadUInt32();
 *                                  uint textureNameTableEntries = input.ReadUInt32();
 *
 *                                  data.Seek(textureNameTableOffset, SeekOrigin.Begin);
 *                                  for (int i = 0; i < textureNameTableEntries; i++)
 *                                  {
 *                                      string name = readString(input);
 *                                      materialAnimation.textureName.Add(name);
 *                                  }
 *
 *                                  for (int i = 0; i < dataTableEntries; i++)
 *                                  {
 *                                      data.Seek(dataTableOffset + (i * 4), SeekOrigin.Begin);
 *                                      uint offset = input.ReadUInt32();
 *
 *                                      RenderBase.OMaterialAnimationData animationData = new RenderBase.OMaterialAnimationData();
 *
 *                                      data.Seek(offset, SeekOrigin.Begin);
 *                                      animationData.name = readString(input);
 *                                      uint animationTypeFlags = input.ReadUInt32();
 *                                      uint flags = input.ReadUInt32();
 *
 *                                      animationData.type = (RenderBase.OMaterialAnimationType)(animationTypeFlags & 0xff);
 *                                      RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf);
 *
 *                                      int segmentCount = 0;
 *                                      switch (segmentType)
 *                                      {
 *                                          case RenderBase.OSegmentType.rgbaColor: segmentCount = 4; break;
 *                                          case RenderBase.OSegmentType.vector2: segmentCount = 2; break;
 *                                          case RenderBase.OSegmentType.single: segmentCount = 1; break;
 *                                          case RenderBase.OSegmentType.integer: segmentCount = 1; break;
 *                                      }
 *
 *                                      for (int j = 0; j < segmentCount; j++)
 *                                      {
 *                                          RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup();
 *
 *                                          data.Seek(offset + 0xc + (j * 4), SeekOrigin.Begin);
 *
 *                                          frame.exists = (flags & (0x100 << j)) == 0;
 *                                          bool constant = (flags & (1 << j)) > 0;
 *
 *                                          if (frame.exists)
 *                                          {
 *                                              if (constant)
 *                                              {
 *                                                  frame.interpolation = RenderBase.OInterpolationMode.linear;
 *                                                  frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0));
 *                                              }
 *                                              else
 *                                              {
 *                                                  uint frameOffset = input.ReadUInt32();
 *                                                  data.Seek(frameOffset, SeekOrigin.Begin);
 *                                                  getAnimationKeyFrame(input, frame);
 *                                              }
 *                                          }
 *
 *                                          animationData.frameList.Add(frame);
 *                                      }
 *
 *                                      materialAnimation.data.Add(animationData);
 *                                  }
 *
 *                                  models.materialAnimation.list.Add(materialAnimation);
 *                              }
 *
 */
            }
        }
Пример #22
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NutTexture tex = new NutTexture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.Width  = d.readShort();
                tex.Height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);

                // check for cubemap
                bool cmap = (d.readInt() == d.readInt());
                d.seek(d.pos() - 8);
                if (cmap)
                {
                    Console.WriteLine("cubemap detected");
                }

                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.HASHID = d.readInt();

                Console.WriteLine(gtxHeaderOffset.ToString("x"));
                d.seek(gtxHeaderOffset);
                d.skip(0x04);              // dim
                d.skip(0x04);              // width
                d.skip(0x04);              // height
                d.skip(0x04);              // depth
                d.skip(0x04);              // numMips
                int format = d.readInt();
                d.skip(0x04);              // aa
                d.skip(0x04);              // use
                int imageSize = d.readInt();
                d.skip(0x04);              // imagePtr
                int maxSize = d.readInt(); // mipSize
                d.skip(0x04);              // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                int ds   = dataOffset;
                int s1   = 0;
                int size = 0;
                Console.WriteLine(totalSize.ToString("x"));
                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);
                    int p       = pitch >> mipLevel;

                    size = d.readInt();
                    //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + totalSize - dataOffset : size));

                    //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
                    //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

                    //if (cmap) tex.height *= 2;

                    int w = (tex.Width >> mipLevel);
                    int h = (tex.Height >> mipLevel);

                    {
                        byte[] deswiz = GTX.swizzleBC(
                            d.getSection(dataOffset, d.size() - dataOffset),
                            w,
                            h,
                            format,
                            tileMode,
                            p,
                            swizzle
                            );
                        tex.mipmaps.Add(new FileData(deswiz).getSection(0, mipSize));
                    }
                    if (mipLevel == 0)
                    {
                        s1         = size;
                        dataOffset = ds + size;
                    }
                    else
                    {
                        dataOffset = ds + s1 + size;
                    }
                    //dataOffset += mipSize;

                    /*if (cmap)
                     * {
                     *  for(int k = 0; k < 5; k++)
                     *  {
                     *      p = pitch >> (mipLevel + k + 1);
                     *      tex.mipmaps.Add(GTX.swizzleBC(
                     *          d.getSection(dataOffset, mipSize),
                     *          w,
                     *          h,
                     *          format,
                     *          tileMode,
                     *          p,
                     *          swizzle
                     *      ));
                     *
                     *      dataOffset += mipSize;
                     *  }
                     * }*/

                    //while (dataOffset % 1024 != 0) dataOffset++;
                    //if (mipSize == 0x4000) dataOffset += 0x400;
                }

                Nodes.Add(tex);
            }

            foreach (NutTexture tex in Nodes)
            {
                if (!draw.ContainsKey(tex.HASHID))
                {
                    draw.Add(tex.HASHID, loadImage(tex, false));
                }

                // redo mipmaps

                /*GL.BindTexture(TextureTarget.Texture2D, draw[tex.id]);
                 * for (int k = 1; k < tex.mipmaps.Count; k++)
                 * {
                 *  tex.mipmaps[k] = new byte[tex.mipmaps[k].Length];
                 *  GCHandle pinnedArray = GCHandle.Alloc(tex.mipmaps[k], GCHandleType.Pinned);
                 *  IntPtr pointer = pinnedArray.AddrOfPinnedObject();
                 *  GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, pointer);
                 *  pinnedArray.Free();
                 * }*/
            }


            //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray);

            //Console.WriteLine(GL.GetError());

            /*int j = 0;
             * foreach(byte[] b in textures[0].mipmaps)
             * {
             *  if (j == 3)
             *  {
             *      for(int w = 3; w < 8; w++)
             *      {
             *          for (int p = 3; p < 6; p++)
             *          {
             *              byte[] deswiz = GTX.swizzleBC(
             *                  b,
             *                  (int)Math.Pow(2, w),
             *                  64,
             *                  51,
             *                  4,
             *                   (int)Math.Pow(2, p),
             *                  197632
             *              );
             *              File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz);
             *          }
             *      }
             *
             *  }
             *  j++;
             * }*/
        }
Пример #23
0
        public BRTI(FileData f) //Docs thanks to gdkchan!!
        {
            ImageKey         = "texture";
            SelectedImageKey = "texture";

            f.skip(4);

            int  BRTISize1 = f.readInt();
            long BRTISize2 = (f.readInt() | f.readInt() << 32);

            surf = new Swizzle.Surface();

            surf.tileMode = (sbyte)f.readByte();
            surf.dim      = (sbyte)f.readByte();
            ushort Flags = (ushort)f.readShort();

            surf.swizzle = (ushort)f.readShort();
            surf.numMips = (ushort)f.readShort();
            uint unk18 = (uint)f.readInt();

            surf.format = (uint)f.readInt();
            DataType    = (byte)(surf.format & 0xFF);
            uint unk20 = (uint)f.readInt();

            surf.width  = f.readInt();
            surf.height = f.readInt();
            surf.depth  = f.readInt();
            int FaceCount = f.readInt();

            surf.sizeRange = f.readInt();
            uint unk38 = (uint)f.readInt();
            uint unk3C = (uint)f.readInt();
            uint unk40 = (uint)f.readInt();
            uint unk44 = (uint)f.readInt();
            uint unk48 = (uint)f.readInt();
            uint unk4C = (uint)f.readInt();

            surf.imageSize = f.readInt();
            surf.alignment = f.readInt();
            int ChannelType = f.readInt();
            int TextureType = f.readInt();

            Text = f.readString((f.readInt() | f.readInt() << 32) + BNTX.temp + 2, -1);
            long ParentOffset = f.readInt() | f.readInt() << 32;
            long PtrsOffset   = f.readInt() | f.readInt() << 32;

            format = surf.format;

            f.seek((int)PtrsOffset + BNTX.temp);
            long dataOff = f.readInt() | f.readInt() << 32;

            surf.data = f.getSection((int)dataOff + BNTX.temp, surf.imageSize);
            //Console.WriteLine(surf.data.Length + " " + dataOff.ToString("x") + " " + surf.imageSize);

            uint blk_dim   = Formats.blk_dims(surf.format >> 8);
            uint blkWidth  = blk_dim >> 4;
            uint blkHeight = blk_dim & 0xF;

            uint bpp = Formats.bpps(surf.format >> 8);

            //     Console.WriteLine($"{Name} Height {surf.height}wdith = {surf.width}allignment = {surf.alignment}blkwidth = {blkWidth}blkheight = {blkHeight}blkdims = {blk_dim} format = {surf.format} datatype = {DataType} dataoffset = {dataOff}");


            // byte[] result = surf.data;



            byte[] result = Swizzle.deswizzle((uint)surf.width, (uint)surf.height, blkWidth, blkHeight, bpp, (uint)surf.tileMode, (uint)surf.alignment, surf.sizeRange, surf.data, 0);


            uint width  = Swizzle.DIV_ROUND_UP((uint)surf.width, blkWidth);
            uint height = Swizzle.DIV_ROUND_UP((uint)surf.height, blkHeight);

            result_ = new byte[width * height * bpp];

            Array.Copy(result, 0, result_, 0, width * height * bpp);

            texture.data   = result_;
            texture.width  = surf.width;
            texture.height = surf.height;

            Width  = surf.width;
            Height = surf.height;

            texture.mipmaps.Add(result_);

            switch (surf.format >> 8)
            {
            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC1):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt1Ext;
                }
                else
                {
                    throw new Exception("Unsupported data type for BC1");
                }

                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC2):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt3Ext;
                }
                else
                {
                    throw new Exception("Unsupported data type for BC2");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC3):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.type = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.type = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
                }
                else
                {
                    throw new Exception("Unsupported data type for BC3");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC4):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    texture.type = PixelInternalFormat.CompressedRedRgtc1;

                    /*    byte[] fixBC4 = DecompressBC4(texture.data, texture.width, texture.height, false);
                     *  texture.data = fixBC4;
                     *  texture.type = PixelInternalFormat.Rgba;
                     *  texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;*/
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SNORM)
                {
                    texture.type = PixelInternalFormat.CompressedSignedRedRgtc1;

                    /*     byte[] fixBC4 = DecompressBC4(texture.data, texture.width, texture.height, true);
                     *   texture.data = fixBC4;
                     *   texture.type = PixelInternalFormat.Rgba;
                     *   texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;*/
                }
                else
                {
                    throw new Exception("Unsupported data type for BC4");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC5):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    //      byte[] fixBC5 = DecompressBC5(texture.data, texture.width, texture.height, false);
                    //    texture.data = fixBC5;
                    texture.type = PixelInternalFormat.CompressedRgRgtc2;
                    //    texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SNORM)
                {
                    byte[] fixBC5 = DecompressBC5(texture.data, texture.width, texture.height, true);
                    texture.data  = fixBC5;
                    texture.type  = PixelInternalFormat.Rgba;
                    texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                }
                else
                {
                    Console.WriteLine("Unsupported data type for BC5");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_BC7):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM)
                {
                    /*         ProcessStartInfo startInfo = new ProcessStartInfo();
                     *       startInfo.CreateNoWindow = false;
                     *       startInfo.UseShellExecute = false;
                     *       startInfo.FileName = "lib\texconv.exe";
                     *       startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                     *       startInfo.Arguments = "-ft png -f R10G10B10A2_UNORM -y";*/
                }
                else if (DataType == (byte)Formats.BNTXImageTypes.SNORM)
                {
                }
                else
                {
                    Console.WriteLine("Unsupported data type for BC7");
                }
                break;

            case ((uint)Formats.BNTXImageFormat.IMAGE_FORMAT_R8_G8_B8_A8):
                if (DataType == (byte)Formats.BNTXImageTypes.UNORM || DataType == (byte)Formats.BNTXImageTypes.SRGB)
                {
                    texture.type  = PixelInternalFormat.Rgba;
                    texture.utype = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                }
                else
                {
                    throw new Exception("Unsupported data type for R8_G8_B8_A8");
                }
                break;
            }
            texture.display = loadImage(texture);
            display         = texture.display;

            RenderableTex.Add(texture);
        }
Пример #24
0
        public void ReadNTP3(FileData d)
        {
            d.skip(0x2);
            int count = d.readShort();

            d.skip(0x10);

            int headerPtr = d.pos();
            int dataPtr   = 0;

            for (int i = 0; i < count; i++)
            {
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                headerPtr += headerSize;

                int numMips = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;
                d.skip(0x0C);

                int[] mipSizes = new int[numMips];

                if (headerSize == 0x50)
                {
                    mipSizes[0] = totalSize;
                }
                else
                {
                    for (int j = 0; j < numMips; j++)
                    {
                        mipSizes[j] = d.readInt();
                    }
                }

                // NOTE: I have no clue what these other header sizes are.
                // pls send help.
                if (headerSize > 0x60)
                {
                    d.skip(headerSize - 0x60);
                }

                d.skip(0x18);
                tex.id = d.readInt();
                for (int miplevel = 0; miplevel < numMips; miplevel++)
                {
                    byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);

                    if (tex.getNutFormat() == 14)
                    {
                        byte[] oldArray = texArray;
                        for (int pos = 0; pos < mipSizes[miplevel]; pos += 4)
                        {
                            for (int p = 0; p < 4; p++)
                            {
                                if (p == 0)
                                {
                                    texArray[pos + 3] = oldArray[pos];
                                }
                                else
                                {
                                    texArray[pos + p - 1] = oldArray[pos + p];
                                }
                            }
                        }
                    }
                    tex.mipmaps.Add(texArray);
                    dataOffset += mipSizes[miplevel];
                }

                dataPtr += headerSize;

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Пример #25
0
        public override void Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readUShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readUShort();
                header.addressCount = f.readUShort();
            }

            // Relocation table
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }

                f.seek((off * 4) + header.gpuCommandsOffset);
                if (header.backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();

            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }


            //Skeletal animation
            for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++)
            {
                f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);


                string skeletalAnimationName = f.readString(f.readInt(), -1);
                int    animationFlags        = f.readInt();
                //int skeletalAnimationloopMode = f.readByte();  //pas ça du tout
                float skeletalAnimationframeSize = f.readFloat();
                int   boneTableOffset            = f.readInt();
                int   boneTableEntries           = f.readInt();
                int   metaDataPointerOffset      = f.readInt();

                //Debug.WriteLine("Animation Name: " + skeletalAnimationName);
                //Debug.WriteLine("BonetableOffset: " + boneTableOffset.ToString("X"));
                //Debug.WriteLine("BonetableEntry: " + boneTableEntries.ToString("X"));

                for (int i = 0; i < boneTableEntries; i++)
                {
                    f.seek(boneTableOffset + (i * 4));
                    int offset = f.readInt();

                    OSkeletalAnimationBone bone = new OSkeletalAnimationBone();

                    f.seek(offset);
                    bone.name = f.readString(f.readInt(), -1);
                    Console.WriteLine("Bone Name: " + bone.name);
                    int animationTypeFlags = f.readInt();
                    int flags = f.readInt();

                    OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf);
                    switch (segmentType)
                    {
                    case OSegmentType.transform:
                        f.seek(offset + 0x18);

                        int notExistMask = 0x80000;
                        int constantMask = 0x200;

                        for (int j = 0; j < 2; j++)
                        {
                            for (int axis = 0; axis < 3; axis++)
                            {
                                bool notExist = (flags & notExistMask) > 0;
                                bool constant = (flags & constantMask) > 0;

                                OAnimationKeyFrameGroup frame = new OAnimationKeyFrameGroup();
                                frame.exists = !notExist;
                                if (frame.exists)
                                {
                                    if (constant)
                                    {
                                        frame.interpolation = OInterpolationMode.linear;
                                        frame.keyFrames.Add(new OAnimationKeyFrame(f.readFloat(), 0));
                                    }
                                    else
                                    {
                                        int frameOffset = f.readInt();
                                        int position    = f.pos();
                                        f.seek(frameOffset);
                                        //getAnimationKeyFrame(input, frame);
                                        f.seek(position);
                                    }
                                }
                                else
                                {
                                    f.seek(f.pos() + 0x04);
                                }

                                if (j == 0)
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.rotationX = frame; break;

                                    case 1: bone.rotationY = frame; break;

                                    case 2: bone.rotationZ = frame; break;
                                    }
                                }
                                else
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.translationX = frame; break;

                                    case 1: bone.translationY = frame; break;

                                    case 2: bone.translationZ = frame; break;
                                    }
                                }

                                notExistMask <<= 1;
                                constantMask <<= 1;
                            }

                            constantMask <<= 1;
                        }

                        break;

                    case OSegmentType.transformQuaternion:
                        bone.isFrameFormat = true;

                        int scaleOffset       = f.readInt();
                        int rotationOffset    = f.readInt();
                        int translationOffset = f.readInt();

                        if ((flags & 0x20) == 0)
                        {
                            bone.scale.exists = true;
                            f.seek(scaleOffset);

                            if ((flags & 4) > 0)
                            {
                                bone.scale.vector.Add(new Vector4(
                                                          f.readFloat(),
                                                          f.readFloat(),
                                                          f.readFloat(),
                                                          0));
                            }
                            else
                            {
                                bone.scale.startFrame = f.readFloat();
                                bone.scale.endFrame   = f.readFloat();

                                int scaleFlags      = f.readInt();
                                int scaleDataOffset = f.readInt();
                                int scaleEntries    = f.readInt();

                                f.seek(scaleDataOffset);
                                for (int j = 0; j < scaleEntries; j++)
                                {
                                    bone.scale.vector.Add(new Vector4(
                                                              f.readFloat(),
                                                              f.readFloat(),
                                                              f.readFloat(),
                                                              0));
                                }
                            }
                        }

                        if ((flags & 0x10) == 0)
                        {
                            bone.rotationQuaternion.exists = true;
                            f.seek(rotationOffset);

                            if ((flags & 2) > 0)
                            {
                                bone.rotationQuaternion.vector.Add(new Vector4(
                                                                       f.readFloat(),
                                                                       f.readFloat(),
                                                                       f.readFloat(),
                                                                       f.readFloat()));
                            }
                            else
                            {
                                bone.rotationQuaternion.startFrame = f.readFloat();
                                bone.rotationQuaternion.endFrame   = f.readFloat();

                                int rotationFlags      = f.readInt();
                                int rotationDataOffset = f.readInt();
                                int rotationEntries    = f.readInt();

                                f.seek(rotationDataOffset);
                                for (int j = 0; j < rotationEntries; j++)
                                {
                                    bone.rotationQuaternion.vector.Add(new Vector4(
                                                                           f.readFloat(),
                                                                           f.readFloat(),
                                                                           f.readFloat(),
                                                                           f.readFloat()));
                                }
                            }
                        }

                        if ((flags & 8) == 0)
                        {
                            bone.translation.exists = true;
                            f.seek(translationOffset);

                            if ((flags & 1) > 0)
                            {
                                bone.translation.vector.Add(new Vector4(
                                                                f.readFloat(),
                                                                f.readFloat(),
                                                                f.readFloat(),
                                                                0));
                            }
                            else
                            {
                                bone.translation.startFrame = f.readFloat();
                                bone.translation.endFrame   = f.readFloat();

                                int translationFlags      = f.readInt();
                                int translationDataOffset = f.readInt();
                                int translationEntries    = f.readInt();

                                f.seek(translationDataOffset);
                                for (int j = 0; j < translationEntries; j++)
                                {
                                    bone.translation.vector.Add(new Vector4(
                                                                    f.readFloat(),
                                                                    f.readFloat(),
                                                                    f.readFloat(),
                                                                    0));
                                }
                            }
                        }

                        break;

                    case OSegmentType.transformMatrix:
                        bone.isFullBakedFormat = true;

                        f.readInt();
                        f.readInt();
                        int matrixOffset = f.readInt();
                        int entries      = f.readInt();

                        f.seek(matrixOffset);
                        for (int j = 0; j < entries; j++)
                        {
                            /*OMatrix transform = new OMatrix();
                             * transform.M11 = f.readFloat();
                             * transform.M21 = f.readFloat();
                             * transform.M31 = f.readFloat();
                             * transform.M41 = f.readFloat();
                             *
                             * transform.M12 = f.readFloat();
                             * transform.M22 = f.readFloat();
                             * transform.M32 = f.readFloat();
                             * transform.M42 = f.readFloat();
                             *
                             * transform.M13 = f.readFloat();
                             * transform.M23 = f.readFloat();
                             * transform.M33 = f.readFloat();
                             * transform.M43 = f.readFloat();
                             *
                             * bone.transform.Add(transform);*/
                        }

                        break;

                    default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name));
                    }

                    //skeletalAnimation.bone.Add(bone);
                }
            }

            //Shaders (unused for now, until someone wants to add them)
            for (int index = 0; index < content.shadersPointerTableEntries; index++)
            {
                f.seek(content.shadersPointerTableOffset + (index * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);

                int shaderDataOffset = f.readInt();
                int shaderDataLength = f.readInt();
            }

            // Textures
            // WIP Section
            for (int index = 0; index < content.texturesPointerTableEntries; index++)
            {
                f.seek(content.texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                int textureCommandsOffset    = f.readInt();
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt(), -1);
                f.seek(textureCommandsOffset);
                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.Height = f.readUShort();
                tex.Width  = f.readUShort();
                f.skip(12);
                int doffset = f.readInt();
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);

                tex.texture = _3DS.DecodeImage(tex.data, tex.Width, tex.Height, (_3DS.Tex_Formats)tex.type);
                //Texture texture = new Texture2D(tex.texture);
                //tex.display = texture.Id;
            }

            // Model data

            for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++)
            {
                f.seek(content.modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt();

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readUShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt();
                int materialsTableEntries = f.readInt();
                int materialsNameOffset   = f.readInt();
                int verticesTableOffset   = f.readInt();
                int verticesTableEntries  = f.readInt();
                f.skip(0x28);
                int    skeletonOffset              = f.readInt();
                int    skeletonEntries             = f.readInt();
                int    skeletonNameOffset          = f.readInt();
                int    objectsNodeVisibilityOffset = f.readInt();
                int    objectsNodeCount            = f.readInt();
                String name = f.readString(f.readInt(), -1);
                int    objectsNodeNameEntries = f.readInt();
                int    objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt();

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readUShort();
                int rootRightNode    = f.readUShort();
                int rootNameOffset   = f.readInt();

                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = f.readShort();
                    short rightNode    = f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[materialsTableEntries];
                for (int index = 0; index < materialsTableEntries; index++)
                {
                    f.seek(materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt(), -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readUShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    Console.WriteLine("Tex index" + mbn.mesh[index].texId);
                    f.skip(2); // flags
                    int nameId = f.readUShort();
                    mbn.mesh[index].Text = objectName[nameId];

                    // node visibility TODO: finish...
                    mbn.mesh[index].Checked = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readUShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt();
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt();
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt();
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i]
                }

                //Skeleton
                f.seek(skeletonOffset);
                for (int index = 0; index < skeletonEntries; index++)
                {
                    Bone bone      = new Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = f.readShort();
                    short boneSpace = f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    f.skip(4); // Meta data
                    bones.bones.Add(bone);


                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
                model.skeleton.update();
            }
        }
Пример #26
0
        public void ReadNTWU(FileData d)
        {
            d.seek(0x4);

            Version = d.readUShort();
            ushort count = d.readUShort();

            d.skip(0x8);
            int headerPtr = 0x10;

            for (ushort i = 0; i < count; ++i)
            {
                d.seek(headerPtr);

                NutTexture tex = new NutTexture();
                tex.type = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4);
                int dataSize   = d.readInt();
                int headerSize = d.readUShort();
                d.skip(2);

                d.skip(1);
                byte mipMapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.readInt(); //Always 1?
                uint caps2 = d.readUInt();

                bool isCubemap    = false;
                byte surfaceCount = 1;
                if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP)
                {
                    //Only supporting all six faces
                    if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
                    {
                        isCubemap    = true;
                        surfaceCount = 6;
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HASHID:X}. Six faces are required.");
                    }
                }

                int dataOffset      = d.readInt() + headerPtr;
                int mipDataOffset   = d.readInt() + headerPtr;
                int gtxHeaderOffset = d.readInt() + headerPtr;
                d.readInt();

                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int imageSize = 0; //Total size of first mipmap of every surface
                int mipSize   = 0; //Total size of mipmaps other than the first of every surface
                if (mipMapCount == 1)
                {
                    if (isCubemap)
                    {
                        imageSize = cmapSize1;
                    }
                    else
                    {
                        imageSize = dataSize;
                    }
                }
                else
                {
                    imageSize = d.readInt();
                    mipSize   = d.readInt();
                    d.skip((mipMapCount - 2) * 4);
                    d.align(0x10);
                }

                d.skip(0x10); //eXt data - always the same

                d.skip(4);    //GIDX
                d.readInt();  //Always 0x10
                tex.HASHID = d.readInt();
                d.skip(4);    // padding align 8

                d.seek(gtxHeaderOffset);
                GTX.GX2Surface gtxHeader = new GTX.GX2Surface();

                gtxHeader.dim       = d.readInt();
                gtxHeader.width     = d.readInt();
                gtxHeader.height    = d.readInt();
                gtxHeader.depth     = d.readInt();
                gtxHeader.numMips   = d.readInt();
                gtxHeader.format    = d.readInt();
                gtxHeader.aa        = d.readInt();
                gtxHeader.use       = d.readInt();
                gtxHeader.imageSize = d.readInt();
                gtxHeader.imagePtr  = d.readInt();
                gtxHeader.mipSize   = d.readInt();
                gtxHeader.mipPtr    = d.readInt();
                gtxHeader.tileMode  = d.readInt();
                gtxHeader.swizzle   = d.readInt();
                gtxHeader.alignment = d.readInt();
                gtxHeader.pitch     = d.readInt();

                //mipOffsets[0] is not in this list and is simply the start of the data (dataOffset)
                //mipOffsets[1] is relative to the start of the data (dataOffset + mipOffsets[1])
                //Other mipOffsets are relative to mipOffset[1] (dataOffset + mipOffsets[1] + mipOffsets[i])
                int[] mipOffsets = new int[mipMapCount];
                mipOffsets[0] = 0;
                for (byte mipLevel = 1; mipLevel < mipMapCount; ++mipLevel)
                {
                    mipOffsets[mipLevel] = 0;
                    mipOffsets[mipLevel] = mipOffsets[1] + d.readInt();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    tex.surfaces.Add(new TextureSurface());
                }

                int w = tex.Width, h = tex.Height;
                for (byte mipLevel = 0; mipLevel < mipMapCount; ++mipLevel)
                {
                    int p = gtxHeader.pitch / (gtxHeader.width / w);

                    int size;
                    if (mipMapCount == 1)
                    {
                        size = imageSize;
                    }
                    else if (mipLevel + 1 == mipMapCount)
                    {
                        size = (mipSize + mipOffsets[1]) - mipOffsets[mipLevel];
                    }
                    else
                    {
                        size = mipOffsets[mipLevel + 1] - mipOffsets[mipLevel];
                    }

                    size /= surfaceCount;

                    for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                    {
                        gtxHeader.data = d.getSection(dataOffset + mipOffsets[mipLevel] + (size * surfaceLevel), size);

                        //Real size
                        //Leave the below line commented for now because it breaks RGBA textures
                        //size = ((w + 3) >> 2) * ((h + 3) >> 2) * (GTX.getBPP(gtxHeader.format) / 8);
                        if (size < (GTX.getBPP(gtxHeader.format) / 8))
                        {
                            size = (GTX.getBPP(gtxHeader.format) / 8);
                        }

                        byte[] deswiz = GTX.swizzleBC(
                            gtxHeader.data,
                            w,
                            h,
                            gtxHeader.format,
                            gtxHeader.tileMode,
                            p,
                            gtxHeader.swizzle
                            );
                        tex.surfaces[surfaceLevel].mipmaps.Add(new FileData(deswiz).getSection(0, size));
                    }

                    w /= 2;
                    h /= 2;

                    if (w < 1)
                    {
                        w = 1;
                    }
                    if (h < 1)
                    {
                        h = 1;
                    }
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }

            RefreshGlTexturesByHashId();

            //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + dataSize - dataOffset : size));

            //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
            //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

            //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray);

            //Console.WriteLine(GL.GetError());

            /*int j = 0;
             * foreach(byte[] b in textures[0].mipmaps)
             * {
             *  if (j == 3)
             *  {
             *      for(int w = 3; w < 8; w++)
             *      {
             *          for (int p = 3; p < 6; p++)
             *          {
             *              byte[] deswiz = GTX.swizzleBC(
             *                  b,
             *                  (int)Math.Pow(2, w),
             *                  64,
             *                  51,
             *                  4,
             *                   (int)Math.Pow(2, p),
             *                  197632
             *              );
             *              File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz);
             *          }
             *      }
             *
             *  }
             *  j++;
             * }*/
        }