Exemple #1
0
        private void SaveMaterialToFile(string fileName)
        {
            FileOutput m = new FileOutput();
            FileOutput s = new FileOutput();

            int[] c = NUD.WriteMaterial(m, currentMaterialList, s);

            FileOutput fin = new FileOutput();

            fin.writeInt(0);

            fin.writeInt(20 + c[0]);
            for (int i = 1; i < 4; i++)
            {
                fin.writeInt(c[i] == c[i - 1] ? 0 : 20 + c[i]);
            }

            for (int i = 0; i < 4 - c.Length; i++)
            {
                fin.writeInt(0);
            }

            fin.writeOutput(m);
            fin.align(32, 0xFF);
            fin.writeIntAt(fin.size(), 0);
            fin.writeOutput(s);
            fin.save(fileName);
        }
Exemple #2
0
                public int Rebuild(FileOutput o)
                {
                    int size = o.size();

                    o.writeInt(hash);
                    o.writeInt(unk1);

                    o.writeByte(name.Length + 1);
                    o.writeString(name);
                    o.writeByte(0);
                    o.align(4);

                    o.writeInt(0);
                    o.writeInt(8);

                    o.writeInt(offset);
                    o.writeInt(this.size);

                    // write data
                    foreach (float f in param)
                    {
                        o.writeFloat(f);
                    }

                    o.writeInt(offsets.Length);
                    foreach (int f in offsets)
                    {
                        o.writeInt(f);
                    }

                    o.writeInt(unkvalues.Length);
                    int v = 0;

                    foreach (float f in unkvalues)
                    {
                        o.writeInt(v++);
                        o.writeFloat(f);
                    }

                    foreach (int f in unkending)
                    {
                        o.writeInt(f);
                    }

                    foreach (int f in end)
                    {
                        o.writeInt(f);
                    }

                    return(o.size() - size);
                }
Exemple #3
0
            public int Rebuild(FileOutput o)
            {
                o.writeString("PROP");
                int sizeoff = o.size();

                o.writeInt(0);
                int size = o.size();

                o.writeInt(0);
                o.writeInt(unk1);
                o.writeShort(0);
                o.writeShort(unk2);

                o.writeByte(project.Length + 1);
                o.writeString(project);
                o.writeByte(0);
                o.writeByte(0);
                o.writeByte(0);
                o.writeByte(0);
                o.align(4);
                o.writeShort(unk3);
                o.align(4);


                o.writeByte(timestamp.Length + 1);
                o.writeString(timestamp);
                o.writeByte(0);
                o.writeByte(0);
                o.writeByte(0);
                o.writeByte(0);
                o.align(4);

                size = o.size() - size;
                o.writeIntAt(size, sizeoff);
                return(size);
            }
Exemple #4
0
            public int Rebuild(FileOutput o)
            {
                o.writeString("GRP ");
                int sizeoff = o.size();

                o.writeInt(0);
                int size = o.size();

                o.writeInt(names.Count);

                int        start = names.Count * 8 + 4;
                FileOutput name  = new FileOutput();

                name.Endian = Endianness.Little;

                int c = 0;

                foreach (string na in names)
                {
                    o.writeInt(start + name.size());

                    int ns = name.pos();
                    name.writeInt(1);
                    name.writeByte(na.Length == 0 ? 0xFF : na.Length + 1);
                    name.writeString(na);
                    name.writeByte(0);
                    name.align(4);
                    if (c != names.Count - 1)
                    {
                        name.writeInt(0); // padding
                    }
                    else
                    {
                        ns -= 4;
                    }
                    c++;

                    o.writeInt(name.pos() - ns);
                }
                o.writeInt(0);
                o.writeOutput(name);

                size = o.size() - size;
                o.writeIntAt(size, sizeoff);
                return(size);
            }
Exemple #5
0
        //Saving Mat
        private void savePresetButton_Click(object sender, EventArgs e)
        {
            using (var sfd = new SaveFileDialog())
            {
                sfd.Filter = "Namco Material (NMT)|*.nmt|" +
                             "All files(*.*)|*.*";

                sfd.InitialDirectory = Path.Combine(MainForm.executableDir, "materials\\");
                Console.WriteLine(sfd.InitialDirectory);
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    sfd.FileName         = sfd.FileName;
                    sfd.RestoreDirectory = true;

                    if (sfd.FileName.EndsWith(".nmt"))
                    {
                        FileOutput m = new FileOutput();
                        FileOutput s = new FileOutput();

                        int[] c = NUD.WriteMaterial(m, currentMaterialList, s);

                        FileOutput fin = new FileOutput();

                        fin.writeInt(0);

                        fin.writeInt(20 + c[0]);
                        for (int i = 1; i < 4; i++)
                        {
                            fin.writeInt(c[i] == c[i - 1] ? 0 : 20 + c[i]);
                        }

                        for (int i = 0; i < 4 - c.Length; i++)
                        {
                            fin.writeInt(0);
                        }

                        fin.writeOutput(m);
                        fin.align(32, 0xFF);
                        fin.writeIntAt(fin.size(), 0);
                        fin.writeOutput(s);
                        fin.save(sfd.FileName);
                    }
                }
            }
        }
Exemple #6
0
                public int Rebuild(FileOutput o)
                {
                    int size = o.size();

                    o.writeInt(hash);
                    o.writeInt(unk1);
                    o.writeByte(name.Length + 1);
                    o.writeString(name);
                    o.writeByte(0);
                    o.align(4);

                    // write data
                    foreach (float f in data)
                    {
                        o.writeFloat(f);
                    }

                    return(o.size() - size);
                }
Exemple #7
0
            public int Rebuild(FileOutput o)
            {
                o.writeString("BINF");
                int sizeoff = o.size();

                o.writeInt(0);
                int size = o.size();

                o.writeInt(0);
                o.writeInt(unk1);

                o.writeByte(name.Length + 1);
                o.writeString(name);
                o.writeByte(0);
                o.align(4);
                o.writeInt(flag);

                size = o.size() - size;
                o.writeIntAt(size, sizeoff);
                return(size);
            }
Exemple #8
0
        public override byte[] Rebuild()
        {
            FileOutput f = new FileOutput();

            f.Endian = Endianness.Little;
            FileOutput fv = new FileOutput();

            fv.Endian = Endianness.Little;

            f.writeShort(format);
            f.writeShort(unknown);
            f.writeInt(flags);
            f.writeInt(mode);
            bool hasNameTable = (flags & 2) > 0;

            f.writeInt(mesh.Count);

            int vertSize = 0;

            // Vertex Bank
            for (int i = 0; i < 1; i++)
            {
                if (mode == 0 || i == 0)
                {
                    Descriptor des = descript[i];

                    if (format != 4)
                    {
                        foreach (Vertex v in vertices)
                        {
                            for (int k = 0; k < des.type.Length; k++)
                            {
                                fv.align(2, 0x00);
                                switch (des.type[k])
                                {
                                case 0:     //Position
                                    writeType(fv, v.pos.X, des.format[k], des.scale[k]);
                                    writeType(fv, v.pos.Y, des.format[k], des.scale[k]);
                                    writeType(fv, v.pos.Z, des.format[k], des.scale[k]);
                                    break;

                                case 1:     //Normal
                                    writeType(fv, v.nrm.X, des.format[k], des.scale[k]);
                                    writeType(fv, v.nrm.Y, des.format[k], des.scale[k]);
                                    writeType(fv, v.nrm.Z, des.format[k], des.scale[k]);
                                    break;

                                case 2:     //Color
                                    writeType(fv, v.col.X, des.format[k], des.scale[k]);
                                    writeType(fv, v.col.Y, des.format[k], des.scale[k]);
                                    writeType(fv, v.col.Z, des.format[k], des.scale[k]);
                                    writeType(fv, v.col.W, des.format[k], des.scale[k]);
                                    break;

                                case 3:     //Tex0
                                    writeType(fv, v.tx[0].X, des.format[k], des.scale[k]);
                                    writeType(fv, v.tx[0].Y, des.format[k], des.scale[k]);
                                    break;

                                case 4:     //Tex1
                                    writeType(fv, v.tx[1].X, des.format[k], des.scale[k]);
                                    writeType(fv, v.tx[1].Y, des.format[k], des.scale[k]);
                                    break;

                                case 5:     //Bone Index
                                    fv.writeByte(v.node[0]);
                                    fv.writeByte(v.node[1]);
                                    break;

                                case 6:     //Bone Weight
                                    writeType(fv, v.weight[0], des.format[k], des.scale[k]);
                                    writeType(fv, v.weight[1], des.format[k], des.scale[k]);
                                    break;
                                    //default:
                                    //    Console.WriteLine("WTF is this");
                                }
                            }
                        }
                        vertSize = fv.size();
                        fv.align(32, 0xFF);
                    }
                }


                for (int j = 0; j < mesh.Count; j++)
                {
                    foreach (List <int> l in mesh[j].faces)
                    {
                        foreach (int index in l)
                        {
                            fv.writeShort(index);
                        }
                        fv.align(32, 0xFF);
                    }
                }
            }


            for (int i = 0; i < mesh.Count; i++)
            {
                if (i == 0 && mode == 1)
                {
                    descript[0].WriteDescription(f);
                    f.writeInt(vertSize);
                }

                f.writeInt(mesh[i].nodeList.Count);
                //Console.WriteLine(mesh[i].faces.Count + " " + mesh[i].nodeList.Count);
                for (int j = 0; j < mesh[i].nodeList.Count; j++)
                {
                    f.writeInt(mesh[i].nodeList[j].Count);

                    for (int k = 0; k < mesh[i].nodeList[j].Count; k++)
                    {
                        f.writeInt(mesh[i].nodeList[j][k]);
                    }

                    f.writeInt(mesh[i].faces[j].Count);

                    // TODO: This stuff
                    if (hasNameTable)
                    {
                        //int nameId = d.readInt();
                    }

                    /*if (mode == 0)
                     * {
                     *  if (format == 4)
                     *  {
                     *      int[] buffer = new int[primitiveCount];
                     *      for (int k = 0; k < primitiveCount; k++)
                     *      {
                     *          buffer[k] = d.readShort();
                     *      }
                     *      d.align(4);
                     *      List<int> buf = new List<int>();
                     *      buf.AddRange(buffer);
                     *      m.faces.Add(buf);
                     *  }
                     *  else
                     *  {
                     *      Descriptor des = new Descriptor();
                     *      des.ReadDescription(d);
                     *      descript.Add(des);
                     *  }
                     *
                     * }*/
                }
            }

            // TODO: STRING TABLE

            /*if (hasNameTable)
             * {
             *  for (int i = 0; i < mesh.Count; i++)
             *  {
             *      int index = d.readByte();
             *      nameTable.Add(d.readString());
             *  }
             * }*/


            if (format != 4)
            {
                f.align(32, 0xFF);
            }

            f.writeOutput(fv);

            return(f.getBytes());
        }
Exemple #9
0
        public void SaveAsMBN(string fname)
        {
            int        format = 6;
            FileOutput o      = new FileOutput();

            o.Endian = Endianness.Little;

            o.writeShort(format);
            o.writeShort(0xFFFF);
            o.writeInt(0); //flags
            o.writeInt(1); //mode
            o.writeInt(Nodes.Count);

            // Write Vertex Attributes
            {
                o.writeInt(Attributes.Count);
                foreach (VertexAttribute va in Attributes)
                {
                    o.writeInt(va.type);
                    o.writeInt(va.format);
                    o.writeFloat(va.scale);
                }
            }


            //Vertex Buffer
            FileOutput vertexBuffer = new FileOutput();

            vertexBuffer.Endian = Endianness.Little;

            for (int i = 0; i < Vertices.Length; i++)
            {
                foreach (VertexAttribute va in Attributes)
                {
                    //Write Data
                    va.WriteVertex(vertexBuffer, ref Vertices[i]);
                }
            }

            o.writeInt(vertexBuffer.size()); // Vertex Buffer Size

            //Mesh Information
            FileOutput indexBuffer = new FileOutput();

            indexBuffer.Endian = Endianness.Little;
            foreach (BCH_Mesh mesh in Nodes)
            {
                o.writeInt(mesh.Nodes.Count);
                foreach (BCH_PolyGroup pg in mesh.Nodes)
                {
                    // Node List
                    o.writeInt(pg.BoneList.Length);
                    foreach (int b in pg.BoneList)
                    {
                        o.writeInt(b);
                    }

                    // Triangle Count
                    o.writeInt(pg.Faces.Length);
                    // o.writeInt(0); something if format == 4

                    // Index Buffer
                    foreach (int i in pg.Faces)
                    {
                        indexBuffer.writeShort(i);
                    }
                    indexBuffer.align(0x20, 0xFF);
                }
            }

            if (format != 4)
            {
                o.align(0x20, 0xFF);
            }

            o.writeOutput(vertexBuffer);
            o.align(0x20, 0xFF);
            o.writeOutput(indexBuffer);
            o.save(fname);
        }
Exemple #10
0
        public override byte[] Rebuild()
        {
            FileOutput o    = new FileOutput();
            FileOutput data = new FileOutput();

            o.writeInt(0x4E545033); // "NTP3"
            o.writeShort(0x0200);
            o.writeShort(textures.Count);
            o.writeInt(0);
            o.writeInt(0);

            //calculate total header size
            int headerLength = 0;

            foreach (var texture in textures)
            {
                int headerSize = 0x50;

                if (texture.mipmaps.Count > 1)
                {
                    headerSize += texture.mipmaps.Count * 4;
                    while (headerSize % 16 != 0)
                    {
                        headerSize += 4;
                    }
                }
                headerLength += headerSize;
            }

            // write headers+data
            foreach (var texture in textures)
            {
                int size = 0;

                foreach (var mip in texture.mipmaps)
                {
                    size += mip.Length;
                    while (size % 16 != 0)
                    {
                        size += 1;
                    }
                }

                int headerSize = 0x50;

                // calculate header size
                if (texture.mipmaps.Count > 1)
                {
                    headerSize += texture.mipmaps.Count * 4;
                    //align to 16
                    while (headerSize % 16 != 0)
                    {
                        headerSize += 1;
                    }
                }

                o.writeInt(size + headerSize);
                o.writeInt(0x00);         //padding
                o.writeInt(size);
                o.writeShort(headerSize); //+ (texture.mipmaps.Count - 4 > 0 ? texture.mipmaps.Count - 4 : 0) * 4
                o.writeShort(0);
                o.writeShort(texture.mipmaps.Count);
                o.writeShort(texture.getNutFormat());
                o.writeShort(texture.width);
                o.writeShort(texture.height);
                o.writeInt(0);
                o.writeInt(0);
                o.writeInt(headerLength + data.size());
                headerLength -= headerSize;
                o.writeInt(0);
                o.writeInt(0);
                o.writeInt(0);

                if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17)
                {
                    foreach (byte[] mip in texture.mipmaps)
                    {
                        for (int t = 0; t < mip.Length; t += 4)
                        {
                            byte t1 = mip[t + 3];
                            mip[t + 3] = mip[t + 2];
                            mip[t + 2] = mip[t + 1];
                            mip[t + 1] = mip[t];
                            mip[t]     = t1;
                        }
                    }
                }

                foreach (var mip in texture.mipmaps)
                {
                    int ds = data.size();
                    data.writeBytes(mip);
                    data.align(0x10);
                    if (texture.mipmaps.Count > 1)
                    {
                        o.writeInt(data.size() - ds);
                    }
                }
                o.align(16);

                if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17)
                {
                    foreach (byte[] mip in texture.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;
                        }
                    }
                }

                o.writeInt(0x65587400); // "eXt\0"
                o.writeInt(0x20);
                o.writeInt(0x10);
                o.writeInt(0x00);
                o.writeInt(0x47494458); // "GIDX"
                o.writeInt(0x10);

                o.writeInt(texture.id);
                o.writeInt(0);
            }
            o.writeOutput(data);

            return(o.getBytes());
        }
Exemple #11
0
        public override byte[] Rebuild()
        {
            FileOutput o    = new FileOutput();
            FileOutput data = new FileOutput();

            o.writeUInt(0x4E545033); // "NTP3"
            o.writeUShort(Version);
            o.writeUShort((ushort)Nodes.Count);
            o.writeInt(0);
            o.writeInt(0);

            //calculate total header size
            uint headerLength = 0;

            foreach (NutTexture texture in Nodes)
            {
                byte surfaceCount = (byte)texture.surfaces.Count;
                bool isCubemap    = surfaceCount == 6;
                if (surfaceCount < 1 || surfaceCount > 6)
                {
                    throw new NotImplementedException($"Unsupported surface amount {surfaceCount} for texture with hash 0x{texture.HashId:X}. 1 to 6 faces are required.");
                }
                else if (surfaceCount > 1 && surfaceCount < 6)
                {
                    throw new NotImplementedException($"Unsupported cubemap face amount for texture with hash 0x{texture.HashId:X}. Six faces are required.");
                }
                byte mipmapCount = (byte)texture.surfaces[0].mipmaps.Count;

                ushort headerSize = 0x50;
                if (isCubemap)
                {
                    headerSize += 0x10;
                }
                if (mipmapCount > 1)
                {
                    headerSize += (ushort)(mipmapCount * 4);
                    while (headerSize % 0x10 != 0)
                    {
                        headerSize += 1;
                    }
                }

                headerLength += headerSize;
            }

            // write headers+data
            foreach (NutTexture texture in Nodes)
            {
                byte surfaceCount = (byte)texture.surfaces.Count;
                bool isCubemap    = surfaceCount == 6;
                byte mipmapCount  = (byte)texture.surfaces[0].mipmaps.Count;

                uint dataSize = 0;

                foreach (var mip in texture.GetAllMipmaps())
                {
                    dataSize += (uint)mip.Length;
                    while (dataSize % 0x10 != 0)
                    {
                        dataSize += 1;
                    }
                }

                ushort headerSize = 0x50;
                if (isCubemap)
                {
                    headerSize += 0x10;
                }
                if (mipmapCount > 1)
                {
                    headerSize += (ushort)(mipmapCount * 4);
                    while (headerSize % 0x10 != 0)
                    {
                        headerSize += 1;
                    }
                }

                o.writeUInt(dataSize + headerSize);
                o.writeUInt(0);
                o.writeUInt(dataSize);
                o.writeUShort(headerSize);
                o.writeUShort(0);

                o.writeByte(0);
                o.writeByte(mipmapCount);
                o.writeByte(0);
                o.writeByte(texture.getNutFormat());
                o.writeShort(texture.Width);
                o.writeShort(texture.Height);
                o.writeInt(0);
                o.writeUInt(texture.DdsCaps2);

                o.writeUInt((uint)(headerLength + data.size()));
                headerLength -= headerSize;
                o.writeInt(0);
                o.writeInt(0);
                o.writeInt(0);

                if (isCubemap)
                {
                    o.writeInt(texture.surfaces[0].mipmaps[0].Length);
                    o.writeInt(texture.surfaces[0].mipmaps[0].Length);
                    o.writeInt(0);
                    o.writeInt(0);
                }

                if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17)
                {
                    texture.SwapChannelOrderDown();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        int ds = data.size();
                        data.writeBytes(texture.surfaces[surfaceLevel].mipmaps[mipLevel]);
                        data.align(0x10);
                        if (mipmapCount > 1 && surfaceLevel == 0)
                        {
                            o.writeInt(data.size() - ds);
                        }
                    }
                }
                o.align(0x10);

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

                o.writeUInt(0x65587400); // "eXt\0"
                o.writeInt(0x20);
                o.writeInt(0x10);
                o.writeInt(0x00);

                o.writeUInt(0x47494458); // "GIDX"
                o.writeInt(0x10);
                o.writeInt(texture.HashId);
                o.writeInt(0);
            }
            o.writeOutput(data);

            return(o.getBytes());
        }
        public static void Rebuild(string fname, List <Animation> animations)
        {
            // poopity doo da
            // headery deadery
            FileOutput o = new FileOutput();

            o.writeString("BCH");
            o.align(4);
            o.writeByte(0x21);    // version stuffs
            o.writeByte(0x21);    // version stuffs
            o.Endian = System.IO.Endianness.Little;
            o.writeShort(0xA755); // version

            FileOutput d_Main = new FileOutput();

            d_Main.Endian = System.IO.Endianness.Little;
            FileOutput d_Main2 = new FileOutput();

            d_Main2.Endian = System.IO.Endianness.Little;
            FileOutput d_Main3 = new FileOutput();

            d_Main3.Endian = System.IO.Endianness.Little;
            FileOutput d_String = new FileOutput();

            d_String.Endian = System.IO.Endianness.Little;
            FileOutput d_GPU = new FileOutput();

            d_GPU.Endian = System.IO.Endianness.Little;
            FileOutput d_Data = new FileOutput();

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

            FileOutput Reloc = new FileOutput();

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

            //Offsets
            o.writeInt(0); //main
            o.writeInt(0); //string
            o.writeInt(0); //gpu
            o.writeInt(0); //data
            o.writeInt(0); //dataext
            o.writeInt(0); //relocationtable

            //Length
            o.writeInt(0);   //main
            o.writeInt(0);   //string
            o.writeInt(0);   //gpu
            o.writeInt(0);   //data
            o.writeInt(0);   //dataext
            o.writeInt(0);   //relocationtable

            o.writeInt(0);   //datasection
            o.writeInt(0);   //

            o.writeShort(1); //flag
            o.writeShort(0); //addcount

            //Contents in the main header......

            d_Main.writeInt(0);                                // Model
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Material
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Shader
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Texture
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // MaterialLUT
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Lights
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Camera
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Fog
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            // SkeAnim
            {
                // Names need to be in patricia tree.......
                Dictionary <string, int> NameBank = new Dictionary <string, int>();

                NameBank.Add("BustN", d_String.size());
                d_String.writeString("BustN");
                d_String.writeByte(0);

                List <PatriciaTree.PatriciaTreeNode> Nodes = new List <PatriciaTree.PatriciaTreeNode>();
                int maxlength = 0;
                foreach (Animation a in animations)
                {
                    maxlength = Math.Max(maxlength, a.Text.Length);
                }

                Nodes.Add(new PatriciaTree.PatriciaTreeNode()
                {
                    ReferenceBit = uint.MaxValue
                });
                foreach (Animation a in animations)
                {
                    PatriciaTree.Insert(Nodes, new PatriciaTree.PatriciaTreeNode()
                    {
                        Name = a.Text
                    }, maxlength);
                }

                int nameOff = 0xb4 + d_Main2.size();
                foreach (PatriciaTree.PatriciaTreeNode node in Nodes)
                {
                    d_Main2.writeInt((int)node.ReferenceBit);
                    d_Main2.writeShort(node.LeftNodeIndex);
                    d_Main2.writeShort(node.RightNodeIndex);
                    if (node.Name.Equals(""))
                    {
                        d_Main2.writeInt(0);
                    }
                    else
                    {
                        NameBank.Add(node.Name, d_String.size());
                        d_Main2.WriteOffset(d_String.size(), d_String);
                        d_String.writeString(node.Name);
                        d_String.writeByte(0);
                    }
                }
                // bones


                // Okay, first create the animation data then create the table pointng to it side by side

                int dataOff = 0xb4 + d_Main2.size();
                foreach (Animation a in animations)
                {
                    d_Main2.WriteOffset(d_Main3.size(), d_Main2);

                    // now create the actual animation data I guess
                    d_Main3.WriteOffset(NameBank[a.Text], d_String);   // name offset
                    d_Main3.writeInt(0x2);                             // Flags TODO: What are these
                    d_Main3.writeFloat(a.FrameCount + 1);
                    d_Main3.WriteOffset(d_Main3.size() + 12, d_Main3); // bone offset
                    d_Main3.writeInt(a.Bones.Count);                   // bonecount
                    d_Main3.writeInt(0);                               // metadata nonsense

                    FileOutput boneHeader = new FileOutput();
                    boneHeader.Endian = System.IO.Endianness.Little;
                    FileOutput keyData = new FileOutput();
                    keyData.Endian = System.IO.Endianness.Little;
                    int start = d_Main3.size() + (a.Bones.Count * 4);
                    int track = 0;
                    foreach (Animation.KeyNode node in a.Bones)
                    {
                        d_Main3.WriteOffset(start + boneHeader.size(), d_Main3); // bone offset
                        // name type and flags
                        if (!NameBank.ContainsKey(node.Text))
                        {
                            NameBank.Add(node.Text, d_String.size());
                            d_String.writeString(node.Text);
                            d_String.writeByte(0);
                        }
                        boneHeader.WriteOffset(NameBank[node.Text], d_String); // name offset
                        boneHeader.writeInt(0x040000);                         // animation type flags, default is just simply transform
                        // Actual Flags
                        int flags = 0;
                        flags |= (((node.XSCA.Keys.Count > 0) ? 0 : 1) << (16 + 0));
                        flags |= (((node.YSCA.Keys.Count > 0) ? 0 : 1) << (16 + 1));
                        flags |= (((node.ZSCA.Keys.Count > 0) ? 0 : 1) << (16 + 2));
                        flags |= (((node.XROT.Keys.Count > 0) ? 0 : 1) << (16 + 3));
                        flags |= (((node.YROT.Keys.Count > 0) ? 0 : 1) << (16 + 4));
                        flags |= (((node.ZROT.Keys.Count > 0) ? 0 : 1) << (16 + 5));
                        flags |= (((node.XPOS.Keys.Count > 0) ? 0 : 1) << (16 + 6));
                        flags |= (((node.YPOS.Keys.Count > 0) ? 0 : 1) << (16 + 7));
                        flags |= (((node.ZPOS.Keys.Count > 0) ? 0 : 1) << (16 + 8));

                        flags |= (((node.XSCA.Keys.Count == 1) ? 1 : 0) << (6 + 0));
                        flags |= (((node.YSCA.Keys.Count == 1) ? 1 : 0) << (6 + 1));
                        flags |= (((node.ZSCA.Keys.Count == 1) ? 1 : 0) << (6 + 2));
                        flags |= (((node.XROT.Keys.Count == 1) ? 1 : 0) << (6 + 3));
                        flags |= (((node.YROT.Keys.Count == 1) ? 1 : 0) << (6 + 4));
                        flags |= (((node.ZROT.Keys.Count == 1) ? 1 : 0) << (6 + 5));
                        flags |= (((node.XPOS.Keys.Count == 1) ? 1 : 0) << (6 + 7));
                        flags |= (((node.YPOS.Keys.Count == 1) ? 1 : 0) << (6 + 8));
                        flags |= (((node.ZPOS.Keys.Count == 1) ? 1 : 0) << (6 + 9));
                        boneHeader.writeInt(flags);

                        // Create KeyFrame Data
                        int sta = start + (a.Bones.Count * 12 * 4);
                        WriteKeyData(node.XSCA, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.YSCA, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.ZSCA, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.XROT, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.YROT, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.ZROT, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.XPOS, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.YPOS, boneHeader, keyData, d_Main3, sta, ref track);
                        WriteKeyData(node.ZPOS, boneHeader, keyData, d_Main3, sta, ref track);
                    }
                    d_Main3.writeOutput(boneHeader);
                    d_Main3.writeOutput(keyData);
                }

                d_Main.WriteOffset(dataOff, d_Main);
                d_Main.writeInt(animations.Count);   //
                d_Main.WriteOffset(nameOff, d_Main); //
            }


            d_Main.writeInt(0);                                // MaterialAnim
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // VisAnim
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // LightAnim
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // CameraAnim
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // FogAnim
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeInt(0);                                // Scene
            d_Main.writeInt(0);                                //
            d_Main.WriteOffset(0xB4 + d_Main2.size(), d_Main); //

            d_Main2.writeInt(0);
            d_Main2.writeInt(0);
            d_Main2.writeInt(0);

            d_Main.writeOutput(d_Main2);
            d_Main.writeOutput(d_Main3);

            int headSize = o.size();

            o.writeIntAt(headSize, 0x08);
            o.writeIntAt(d_Main.size(), 0x20);
            o.writeOutput(d_Main);
            o.align(4);

            int stringSize = o.size();

            o.writeIntAt(stringSize, 0x0C);
            o.writeIntAt(d_String.size(), 0x24);
            o.writeOutput(d_String);
            o.align(4);

            int gpuSize = o.size();

            o.writeIntAt(d_GPU.size() > 0 ? gpuSize : 0, 0x10);
            o.writeIntAt(d_GPU.size(), 0x28);
            o.writeOutput(d_GPU);
            o.align(0x100);

            int dataSize = o.size();

            o.writeIntAt(dataSize, 0x14);
            o.writeIntAt(dataSize, 0x18);
            o.writeIntAt(d_Data.size(), 0x2C);
            o.writeIntAt(d_Data.size(), 0x30);
            o.writeOutput(d_Data);

            //Create Relocation Table
            // Flag is 7 bits
            // 0 - main 1 - string 2 - gpu 3 - data
            foreach (FileOutput.RelocOffset off in o.Offsets)
            {
                int size = 0;
                int code = 0;
                int div  = 4;
                if (off.output == d_Main || off.output == d_Main2 || off.output == d_Main3)
                {
                    size = headSize;
                    code = 0;
                    if (off.output == d_Main3)
                    {
                        off.Value += headSize;
                    }
                    if (off.output == d_Main2)
                    {
                        off.Value += d_Main2.size() + headSize;
                    }
                }
                if (off.output == d_String)
                {
                    size = stringSize;
                    code = 1;
                    div  = 1;
                }
                if (off.output == d_GPU)
                {
                    size = gpuSize;
                    code = 2;
                }
                if (off.output == d_Data)
                {
                    size = dataSize;
                    code = 3;
                }

                o.writeIntAt(off.Value - size, off.Position);
                int reloc = (code << 25) | (((off.Position - headSize) / div) & 0x1FFFFFF);
                Reloc.writeInt(reloc);
            }

            int relocSize = o.size();

            o.writeIntAt(relocSize, 0x1C);
            o.writeIntAt(Reloc.size(), 0x34);
            o.writeOutput(Reloc);

            o.save(fname);
        }
Exemple #13
0
        public override byte[] Rebuild()
        {
            FileOutput o    = new FileOutput();
            FileOutput data = new FileOutput();

            //We always want BE for the first six bytes
            o.Endian    = Endianness.Big;
            data.Endian = Endianness.Big;

            if (Endian == Endianness.Big)
            {
                o.writeUInt(0x4E545033); //NTP3
            }
            else if (Endian == Endianness.Little)
            {
                o.writeUInt(0x4E545744); //NTWD
            }

            //Most NTWU NUTs are 0x020E, which isn't valid for NTP3/NTWD
            if (Version > 0x0200)
            {
                Version = 0x0200;
            }
            o.writeUShort(Version);

            //After that, endian is used appropriately
            o.Endian    = Endian;
            data.Endian = Endian;

            o.writeUShort((ushort)Nodes.Count);
            o.writeInt(0);
            o.writeInt(0);

            //calculate total header size
            uint headerLength = 0;

            foreach (NutTexture texture in Nodes)
            {
                byte surfaceCount = (byte)texture.surfaces.Count;
                bool isCubemap    = surfaceCount == 6;
                if (surfaceCount < 1 || surfaceCount > 6)
                {
                    throw new NotImplementedException($"Unsupported surface amount {surfaceCount} for texture with hash 0x{texture.HashId:X}. 1 to 6 faces are required.");
                }
                else if (surfaceCount > 1 && surfaceCount < 6)
                {
                    throw new NotImplementedException($"Unsupported cubemap face amount for texture with hash 0x{texture.HashId:X}. Six faces are required.");
                }
                byte mipmapCount = (byte)texture.surfaces[0].mipmaps.Count;

                ushort headerSize = 0x50;
                if (isCubemap)
                {
                    headerSize += 0x10;
                }
                if (mipmapCount > 1)
                {
                    headerSize += (ushort)(mipmapCount * 4);
                    while (headerSize % 0x10 != 0)
                    {
                        headerSize += 1;
                    }
                }

                headerLength += headerSize;
            }

            // write headers+data
            foreach (NutTexture texture in Nodes)
            {
                byte surfaceCount = (byte)texture.surfaces.Count;
                bool isCubemap    = surfaceCount == 6;
                byte mipmapCount  = (byte)texture.surfaces[0].mipmaps.Count;

                uint dataSize = 0;

                foreach (var mip in texture.GetAllMipmaps())
                {
                    dataSize += (uint)mip.Length;
                    while (dataSize % 0x10 != 0)
                    {
                        dataSize += 1;
                    }
                }

                ushort headerSize = 0x50;
                if (isCubemap)
                {
                    headerSize += 0x10;
                }
                if (mipmapCount > 1)
                {
                    headerSize += (ushort)(mipmapCount * 4);
                    while (headerSize % 0x10 != 0)
                    {
                        headerSize += 1;
                    }
                }

                o.writeUInt(dataSize + headerSize);
                o.writeUInt(0);
                o.writeUInt(dataSize);
                o.writeUShort(headerSize);
                o.writeUShort(0);

                o.writeByte(0);
                o.writeByte(mipmapCount);
                o.writeByte(0);
                o.writeByte(texture.getNutFormat());
                o.writeShort(texture.Width);
                o.writeShort(texture.Height);
                o.writeInt(0);
                o.writeUInt(texture.DdsCaps2);

                if (Version < 0x0200)
                {
                    o.writeUInt(0);
                }
                else if (Version >= 0x0200)
                {
                    o.writeUInt((uint)(headerLength + data.size()));
                }
                headerLength -= headerSize;
                o.writeInt(0);
                o.writeInt(0);
                o.writeInt(0);

                if (isCubemap)
                {
                    o.writeInt(texture.surfaces[0].mipmaps[0].Length);
                    o.writeInt(texture.surfaces[0].mipmaps[0].Length);
                    o.writeInt(0);
                    o.writeInt(0);
                }

                if (texture.getNutFormat() == 14 || texture.getNutFormat() == 17)
                {
                    texture.SwapChannelOrderDown();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        int ds = data.size();
                        data.writeBytes(texture.surfaces[surfaceLevel].mipmaps[mipLevel]);
                        data.align(0x10);
                        if (mipmapCount > 1 && surfaceLevel == 0)
                        {
                            o.writeInt(data.size() - ds);
                        }
                    }
                }
                o.align(0x10);

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

                o.writeBytes(new byte[] { 0x65, 0x58, 0x74, 0x00 }); // "eXt\0"
                o.writeInt(0x20);
                o.writeInt(0x10);
                o.writeInt(0x00);

                o.writeBytes(new byte[] { 0x47, 0x49, 0x44, 0x58 }); // "GIDX"
                o.writeInt(0x10);
                o.writeInt(texture.HashId);
                o.writeInt(0);

                if (Version < 0x0200)
                {
                    o.writeOutput(data);
                    data = new FileOutput();
                }
            }

            if (Version >= 0x0200)
            {
                o.writeOutput(data);
            }

            return(o.getBytes());
        }