Beispiel #1
0
        public void save(FileOutput f)
        {
            f.writeHex(magic);

            f.writeByte(1);
            f.writeString(name.PadRight(0x38, (char)0));

            f.writeByte(1);
            f.writeString(subname.PadRight(0x40, (char)0));

            f.writeByte(1);
            for (int i = 0; i < 3; i++)
            {
                f.writeFloat(startPos[i]);
            }
            f.writeFlag(useStartPos);

            f.writeByte(1);
            f.writeInt(unk1);

            f.writeByte(1);
            foreach (float i in unk2)
            {
                f.writeFloat(i);
            }
            f.writeInt(unk3);

            f.writeByte(1);
            f.writeChars(boneName);
        }
Beispiel #2
0
        public override byte[] Rebuild()
        {
            FileOutput file = new FileOutput();
            if (file != null)
            {
                
                if (Endian == Endianness.Little) {
                    file.Endian = Endianness.Little;
                    file.writeString(" NBV");
                }
                if (Endian == Endianness.Big) {
                    file.Endian = Endianness.Big;
                    file.writeString("VBN ");
                }

                file.writeShort(0x01);
                file.writeShort(0x02);
                file.writeInt(bones.Count);
                if (boneCountPerType[0] == 0)
                    boneCountPerType[0] = (uint)bones.Count;
                for (int i = 0; i < 4; i++)
                    file.writeInt((int)boneCountPerType[i]);

                for (int i = 0; i < bones.Count; i++)
                {
                    file.writeString(new string(bones[i].boneName));
                    for (int j = 0; j < 64 - bones[i].boneName.Length; j++)
                        file.writeByte(0);
                    file.writeInt((int)bones[i].boneType);
                    if(bones[i].parentIndex == -1)
                        file.writeInt(0x0FFFFFFF);
                    else
                        file.writeInt(bones[i].parentIndex);
                    file.writeInt((int)bones[i].boneId);
                }

                for (int i = 0; i < bones.Count; i++)
                {
                    file.writeFloat(bones[i].position[0]);
                    file.writeFloat(bones[i].position[1]);
                    file.writeFloat(bones[i].position[2]);
                    file.writeFloat(bones[i].rotation[0]);
                    file.writeFloat(bones[i].rotation[1]);
                    file.writeFloat(bones[i].rotation[2]);
                    file.writeFloat(bones[i].scale[0]);
                    file.writeFloat(bones[i].scale[1]);
                    file.writeFloat(bones[i].scale[2]);
                }
            }
            return file.getBytes();
        }
Beispiel #3
0
        public static byte[] FromIDSP(byte[] idsp)
        {
            File.WriteAllBytes("temp.idsp", idsp);
            IntPtr vgm = VGMStreamNative.InitVGMStream("temp.idsp");

            if (vgm == IntPtr.Zero)
            {
                throw new Exception("Error loading idsp");
            }

            int channelCount = VGMStreamNative.GetVGMStreamChannelCount(vgm);
            int bitsPerFrame = VGMStreamNative.GetVGMStreamFrameSize(vgm);
            int size         = VGMStreamNative.GetVGMStreamTotalSamples(vgm);
            int samplerate   = VGMStreamNative.GetVGMStreamSampleRate(vgm);

            int total = (int)((samplerate * bitsPerFrame * channelCount * (size / 24576000f)) / 8 * 1024);

            short[] buffer = new short[total];
            VGMStreamNative.RenderVGMStream(buffer, buffer.Length / 2, vgm);

            FileOutput o = new FileOutput();

            o.Endian = Endianness.Little;

            o.writeString("RIFF");
            o.writeInt(0);
            o.writeString("WAVEfmt ");

            o.writeInt(0x10);
            o.writeShort(1);
            o.writeShort(channelCount);
            o.writeInt(samplerate);
            o.writeInt(size);
            o.writeShort(2);
            o.writeShort(0x10);

            o.writeString("data");
            o.writeInt(buffer.Length);

            for (int i = 0; i < buffer.Length / 2; i++)
            {
                o.writeShort(buffer[i]);
            }

            o.writeIntAt(o.size() - 8, 4);

            VGMStreamNative.CloseVGMStream(vgm);
            File.Delete("temp.idsp");
            return(o.getBytes());
        }
Beispiel #4
0
 public void save(FileOutput f)
 {
     f.writeHex("030401017735BB750000000201");
     f.writeString(name.PadRight(0x38, (char)0));
     f.writeByte(1);
     f.writeString(subname.PadRight(0x40, (char)0));
     f.writeByte(1);
     foreach (float i in startPos)
     {
         f.writeFloat(i);
     }
     f.writeFlag(useStartPos);
     f.writeByte(1);
     f.writeInt(unk2);
     f.writeByte(1);
     f.writeBytes(unk3);
     f.writeHex("FFFFFFFF01");
     f.writeChars(unk4);
     f.writeFlag(flag1);
     f.writeFlag(flag2);
     f.writeFlag(flag3);
     f.writeFlag(flag4);
     f.writeByte(1);
     f.writeInt(verts.Count);
     foreach (Vector2D v in verts)
     {
         f.writeByte(1);
         f.writeFloat(v.x);
         f.writeFloat(v.y);
     }
     f.writeByte(1);
     f.writeInt(normals.Count);
     foreach (Vector2D n in normals)
     {
         f.writeByte(1);
         f.writeFloat(n.x);
         f.writeFloat(n.y);
     }
     f.writeByte(1);
     f.writeInt(0);
     f.writeByte(1);
     f.writeInt(materials.Count);
     foreach (CollisionMat m in materials)
     {
         f.writeByte(1);
         f.writeBytes(m.material);
     }
 }
Beispiel #5
0
            public int Rebuild(FileOutput o)
            {
                o.writeString("DTON");
                int sizeoff = o.size();

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

                o.writeInt(destone.Count);

                FileOutput dat = new FileOutput();

                dat.Endian = Endianness.Little;

                int start = destone.Count * 8 + 4;

                for (int i = 0; i < destone.Count; i++)
                {
                    o.writeInt(start + dat.size());
                    o.writeInt(destone[i].Rebuild(dat) + 4);

                    if (i != destone.Count - 1)
                    {
                        dat.writeInt(0);
                    }
                }

                o.writeInt(0);
                o.writeOutput(dat);

                size = o.size() - size;
                o.writeIntAt(size, sizeoff);
                return(size);
            }
Beispiel #6
0
            public int Rebuild(FileOutput o)
            {
                o.writeString("TONE");
                int sizeoff = o.size();

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

                o.writeInt(tones.Count);

                FileOutput dat = new FileOutput();

                dat.Endian = Endianness.Little;

                int start = tones.Count * 8 + 4;

                for (int i = 0; i < tones.Count; i++)
                {
                    o.writeInt(start + dat.size());
                    o.writeInt(tones[i].Rebuild(dat));
                }

                o.writeInt(0);
                o.writeOutput(dat);

                size = o.size() - size - 4;
                o.writeIntAt(size, sizeoff);
                return(size);
            }
Beispiel #7
0
 private void injectRom(object sender, EventArgs e)
 {
     using (OpenFileDialog ofd = new OpenFileDialog())
     {
         ofd.Title = "Select NES ROM";
         if (ofd.ShowDialog() == DialogResult.OK)
         {
             using (SaveFileDialog sfd = new SaveFileDialog())
             {
                 sfd.Title = "Select Save Location";
                 if (sfd.ShowDialog() == DialogResult.OK)
                 {
                     byte[]     rom = File.ReadAllBytes(ofd.FileName);
                     FileOutput f   = new FileOutput();
                     f.Endian = Endianness.Little;
                     f.writeInt(0);
                     f.writeInt(0x30 + rom.Length);
                     f.writeInt(0x30);
                     f.writeInt(0x20 + rom.Length);
                     f.writeInt(0x30 + rom.Length);
                     f.writeInt(0);
                     f.writeInt(0x1B + rom.Length);
                     f.writeInt(0x1B + rom.Length);
                     f.writeString("JAM WAS HERE");
                     f.writeInt(0);
                     f.writeBytes(rom);
                     f.save(sfd.FileName);
                 }
             }
         }
     }
 }
Beispiel #8
0
        public void ExportTEX(string filename)
        {
            FileOutput o = new FileOutput();

            o.Endian = Endianness.Little;

            o.writeInt(pictureBox1.Image.Width);
            o.writeInt(pictureBox1.Image.Height);
            o.writeByte(formatSelector.SelectedIndex);
            o.writeByte(1);
            o.writeShort(0);
            o.writeString(nameBox.Text);
            for (int i = 0; i < 0x74 - nameBox.Text.Length; i++)
            {
                o.writeByte(0);
            }

            pictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipY);

            o.writeBytes(_3DS.EncodeImage(new Bitmap(pictureBox1.Image), (_3DS.Tex_Formats)formatSelector.SelectedIndex));

            pictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipY);

            o.save(filename);
        }
Beispiel #9
0
        public override byte[] Rebuild()
        {
            FileOutput o = new FileOutput();

            o.Endian = Endianness.Little;

            FileOutput d = new FileOutput();

            d.Endian = Endianness.Little;

            o.writeString("NUS3");
            o.writeInt(0);

            o.writeString("BANKTOC ");
            o.writeInt(0x3C);
            o.writeInt(0x07);

            // write each section
            o.writeString("PROP");
            o.writeInt(prop.Rebuild(d));

            o.writeString("BINF");
            o.writeInt(binf.Rebuild(d));

            o.writeString("GRP ");
            o.writeInt(grp.Rebuild(d));

            o.writeString("DTON");
            o.writeInt(dton.Rebuild(d));

            o.writeString("TONE");
            o.writeInt(tone.Rebuild(d));

            o.writeString("JUNK");
            o.writeInt(4);
            //d.writeString("JUNK");
            d.writeInt(4);
            d.writeInt(0);

            o.writeString("PACK");
            o.writeInt(0);

            o.writeOutput(d);

            o.writeIntAt(o.size(), 4);

            // something extra with bgm??

            return(o.getBytes());
        }
Beispiel #10
0
        public override byte[] Rebuild()
        {
            FileOutput buf = new FileOutput();

            buf.Endian = Endianness.Little;

            var flagsOffset   = 0x10;
            var entriesOffset = flagsOffset + (atlases.Count * 4);
            var stringsOffset = entriesOffset + (textures.Count * 0x20);

            buf.writeInt(0x544C5354); // TLST
            buf.writeShort(0);        // idk
            buf.writeShort((short)atlases.Count);
            buf.writeShort((short)textures.Count);
            buf.writeShort((short)flagsOffset);
            buf.writeShort((short)entriesOffset);
            buf.writeShort((short)stringsOffset);

            // flags
            foreach (var flag in atlases)
            {
                buf.writeInt((int)flag);
            }

            // entries
            int namePtr = 0;

            foreach (var texture in textures)
            {
                buf.writeInt(namePtr);
                buf.writeInt(namePtr);
                namePtr += texture.name.Length + 1;

                buf.writeFloat(texture.topLeft.X);
                buf.writeFloat(texture.topLeft.Y);
                buf.writeFloat(texture.botRight.X);
                buf.writeFloat(texture.botRight.Y);

                buf.writeShort(texture.width);
                buf.writeShort(texture.height);
                buf.writeShort(texture.atlasId);
                buf.writeShort(0); // pad
            }

            //strings
            foreach (var texture in textures)
            {
                buf.writeString(texture.name);
                buf.writeByte(0);
            }

            buf.writeByte(0);

            return(buf.getBytes());
        }
Beispiel #11
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);
            }
Beispiel #12
0
        public override byte[] Rebuild()
        {
            FileOutput o = new FileOutput();

            o.Endian = Endianness.Little;

            o.writeString(" BWS");
            o.writeShort(0x05);
            o.writeShort(0x01);
            o.writeInt(bones.Count);

            foreach (SBEntry s in bones)
            {
                o.writeInt((int)s.hash);
                o.writeFloat(s.param1_1);
                o.writeInt(s.param1_2);
                o.writeInt(s.param1_3);
                o.writeFloat(s.param2_1);
                o.writeFloat(s.param2_2);
                o.writeInt(s.param2_3);
                o.writeFloat(s.rx1);
                o.writeFloat(s.rx2);
                o.writeFloat(s.ry1);
                o.writeFloat(s.ry2);
                o.writeFloat(s.rz1);
                o.writeFloat(s.rz2);

                for (int j = 0; j < 8; j++)
                {
                    o.writeInt((int)s.boneHashes[j]);
                }

                for (int j = 0; j < 4; j++)
                {
                    o.writeFloat(s.unks1[j]);
                }

                for (int j = 0; j < 6; j++)
                {
                    o.writeFloat(s.unks2[j]);
                }

                o.writeFloat(s.factor);

                for (int j = 0; j < 3; j++)
                {
                    o.writeInt(s.ints[j]);
                }
            }

            return(o.getBytes());
        }
Beispiel #13
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);
                }
Beispiel #14
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);
            }
Beispiel #15
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);
            }
Beispiel #16
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);
                }
Beispiel #17
0
        public byte[] Rebuild(int pos)
        {
            FileOutput f = new FileOutput();

            f.Endian = Endianness.Big;

            f.writeInt(pos + f.pos() + 0x20);
            f.writeInt(unknown);
            f.writeInt(valueCount);
            f.writeInt(frames.Count);
            f.writeShort(unknown2);
            f.writeShort(unknown3);
            int position = pos + f.pos() + 0xC + name.Length + 1;

            while (position % 0x10 != 0)
            {
                position++;
            }

            f.writeInt(position);
            f.writeBytes(new byte[8]);
            f.writeString(name);
            f.writeByte(0);
            while ((pos + f.pos()) % 0x10 != 0)
            {
                f.writeByte(0);
            }

            foreach (frame fr in frames)
            {
                for (int i = 0; i < valueCount; i++)
                {
                    f.writeFloat(fr.values[i]);
                }
            }
            f.writeBytes(new byte[0x10]);

            return(f.getBytes());
        }
Beispiel #18
0
        public byte[] Rebuild(int pos)
        {
            FileOutput f = new FileOutput();

            f.Endian = Endianness.Big;

            f.writeInt(pos + f.pos() + 0x20);
            f.writeInt(Convert.ToInt32(unk1));
            int offset = pos + f.pos() + 0x18;

            offset += name.Length + 1;
            while (offset % 16 != 0)
            {
                offset++;
            }
            offset += 0x10;
            f.writeInt(offset);
            f.writeBytes(new byte[0x14]);
            f.writeString(name);
            f.writeByte(0);
            while ((pos + f.pos()) % 16 != 0)
            {
                f.writeByte(0);
            }
            f.writeBytes(new byte[0x10]);
            f.writeInt(frameCount);
            f.writeShort(Convert.ToInt32(unk2));
            f.writeShort(frames.Count);
            f.writeInt(pos + f.pos() + 0x18);
            f.writeBytes(new byte[0x14]);
            foreach (frame keyframe in frames)
            {
                f.writeShort(keyframe.frameNum);
                f.writeByte(keyframe.state);
                f.writeByte(keyframe.unknown);
            }

            return(f.getBytes());
        }
Beispiel #19
0
        public byte[] RebuildEntries(FileOutput f)
        {
            List <int> nameOffsets     = new List <int>();
            int        nameTableOffset = 0x30 + (0x20 * entries.Count);
            FileOutput nameTable       = new FileOutput()
            {
                Endian = Endianness.Big
            };

            foreach (Entry entry in entries)
            {
                nameOffsets.Add(nameTableOffset + nameTable.pos());
                nameTable.writeString(entry.name);
                nameTable.writeBytes(new byte[4 - (entry.name.Length % 4)]); //Pad to next word
            }
            while (nameTable.pos() % 0x10 != 0)
            {
                nameTable.writeByte(0);
            }

            for (int i = 0; i < entries.Count; i++)
            {
                entries[i].values[0] = nameOffsets[i];
            }

            foreach (Entry entry in entries)
            {
                foreach (int value in entry.values)
                {
                    f.writeInt(value);
                }
            }

            f.writeBytes(nameTable.getBytes());

            return(f.getBytes());
        }
Beispiel #20
0
        public void Save(string fname)
        {
            FileOutput f = new FileOutput();

            f.Endian = System.IO.Endianness.Little;
            f.writeString("DDS ");
            f.writeInt(header.size);
            f.writeInt(header.flags);
            f.writeInt(header.height);
            f.writeInt(header.width);
            f.writeInt(header.pitchOrLinear);
            f.writeInt(header.depth);
            f.writeInt(header.mipmapCount);
            for (int i = 0; i < 11; i++)
            {
                f.writeInt(0);
            }
            f.writeInt(header.dwSize);
            f.writeInt(header.dwFlags);
            f.writeInt(header.dwFourCC);
            f.writeInt(header.dwBitmask);
            f.writeInt((int)header.dwCaps);
            f.writeInt((int)header.dwCaps2);
            f.writeInt((int)header.dwCaps3);
            f.writeInt((int)header.dwCaps4);
            f.writeInt((int)header.reserve);

            for (int i = 0; i < 4; i++)
            {
                f.writeInt(0);
            }

            f.writeBytes(data);

            f.save(fname);
        }
Beispiel #21
0
        public void ExportTEX(string filename)
        {
            FileOutput o = new FileOutput();

            o.Endian = Endianness.Little;

            o.writeInt(pictureBox1.Image.Width);
            o.writeInt(pictureBox1.Image.Height);
            o.writeByte(formatSelector.SelectedIndex);
            o.writeByte(1);
            o.writeShort(0);
            o.writeString(nameBox.Text);
            for (int i = 0; i < 0x74 - nameBox.Text.Length; i++)
            {
                o.writeByte(0);
            }

            pictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipY);

            if (formatSelector.SelectedIndex == 0x0C)
            {
                o.writeBytes(Pixel.encodeETC(new Bitmap(pictureBox1.Image)));
            }
            if (formatSelector.SelectedIndex == 0x0D)
            {
                o.writeBytes(Pixel.encodeETCa4(new Bitmap(pictureBox1.Image)));
            }
            else
            {
                throw new Exception("Unsuppored format");
            }

            pictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipY);

            o.save(filename);
        }
Beispiel #22
0
        public static byte[] createOMO(SkelAnimation a, VBN vbn)
        {
            List <int> nodeid = a.getNodes(true, vbn);

            int startNode = 0;
            int sizeNode  = nodeid.Count;

            FileOutput o = new FileOutput();

            o.Endian = Endianness.Big;

            FileOutput t1 = new FileOutput();

            t1.Endian = Endianness.Big;

            FileOutput t2 = new FileOutput();

            t2.Endian = Endianness.Big;

            o.writeString("OMO ");
            o.writeShort(1);        //idk
            o.writeShort(3);        //idk

            o.writeInt(0x091E100C); //flags??


            o.writeShort(0);              //padding
            o.writeShort(sizeNode);       // numOfNodes

            o.writeShort(a.frames.Count); // frame size
            o.writeShort(0);              // frame start ??

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

            o.writeIntAt(o.size(), 0x14);


            // ASSESSMENT
            KeyNode[] minmax   = new KeyNode[sizeNode];
            bool[]    hasScale = new bool[sizeNode];
            bool[]    hasTrans = new bool[sizeNode];
            bool[]    hasRot   = new bool[sizeNode];

            bool[] conScale = new bool[sizeNode];
            bool[] conTrans = new bool[sizeNode];
            bool[] conRot   = new bool[sizeNode];

            a.setFrame(0);

            for (int i = 0; i < a.size(); i++)
            {
                a.nextFrame(vbn);

                for (int j = 0; j < nodeid.Count; j++)
                {
                    Bone node = getNodeId(vbn, nodeid[j]);

                    if (minmax[j] == null)
                    {
                        hasRot[j]   = false;
                        hasScale[j] = false;
                        hasTrans[j] = false;

                        KeyNode n = a.getFirstNode(nodeid[j]);
                        if (n != null)
                        {
                            if (n.r_type != -1)
                            {
                                hasRot[j] = true;
                            }
                            if (n.t_type != -1)
                            {
                                hasTrans[j] = true;
                            }
                            if (n.s_type != -1)
                            {
                                hasScale[j] = true;
                            }
                        }

                        minmax[j]    = new KeyNode();
                        minmax[j].t  = new Vector3(999f, 999f, 999f);
                        minmax[j].r  = new Quaternion(999f, 999f, 999f, 999f);
                        minmax[j].s  = new Vector3(999f, 999f, 999f);
                        minmax[j].t2 = new Vector3(-999f, -999f, -999f);
                        minmax[j].r2 = new Quaternion(-999f, -999f, -999f, -999f);
                        minmax[j].s2 = new Vector3(-999f, -999f, -999f);
                    }

                    if (node.pos.X < minmax[j].t.X)
                    {
                        minmax[j].t.X = node.pos.X;
                    }
                    if (node.pos.X > minmax[j].t2.X)
                    {
                        minmax[j].t2.X = node.pos.X;
                    }

                    if (node.pos.Y < minmax[j].t.Y)
                    {
                        minmax[j].t.Y = node.pos.Y;
                    }
                    if (node.pos.Y > minmax[j].t2.Y)
                    {
                        minmax[j].t2.Y = node.pos.Y;
                    }

                    if (node.pos.Z < minmax[j].t.Z)
                    {
                        minmax[j].t.Z = node.pos.Z;
                    }
                    if (node.pos.Z > minmax[j].t2.Z)
                    {
                        minmax[j].t2.Z = node.pos.Z;
                    }

                    //				float[] fix = Node.fix360(node.nrx, node.nry, node.nrz);
                    //float[] f = Bone.CalculateRotation(node.nrx, node.nry, node.nrz);
                    Quaternion r = node.rot;

                    if (r.X < minmax[j].r.X)
                    {
                        minmax[j].r.X = r.X;
                    }
                    if (r.X > minmax[j].r2.X)
                    {
                        minmax[j].r2.X = r.X;
                    }

                    if (r.Y < minmax[j].r.Y)
                    {
                        minmax[j].r.Y = r.Y;
                    }
                    if (r.Y > minmax[j].r2.Y)
                    {
                        minmax[j].r2.Y = r.Y;
                    }

                    if (r.Z < minmax[j].r.Z)
                    {
                        minmax[j].r.Z = r.Z;
                    }
                    if (r.Z > minmax[j].r2.Z)
                    {
                        minmax[j].r2.Z = r.Z;
                    }


                    if (node.sca.X < minmax[j].s.X)
                    {
                        minmax[j].s.X = node.sca.X;
                    }
                    if (node.sca.X > minmax[j].s2.X)
                    {
                        minmax[j].s2.X = node.sca.X;
                    }

                    if (node.sca.Y < minmax[j].s.Y)
                    {
                        minmax[j].s.Y = node.sca.Y;
                    }
                    if (node.sca.Y > minmax[j].s2.Y)
                    {
                        minmax[j].s2.Y = node.sca.Y;
                    }

                    if (node.sca.Z < minmax[j].s.Z)
                    {
                        minmax[j].s.Z = node.sca.Z;
                    }
                    if (node.sca.Z > minmax[j].s2.Z)
                    {
                        minmax[j].s2.Z = node.sca.Z;
                    }
                }
            }

            // NODE INFO

            int t2Size = 0;

            for (int i = 0; i < sizeNode; i++)
            {
                int flag = 0;

                conRot[i]   = false;
                conScale[i] = false;
                conTrans[i] = false;

                // check for constant
                if (minmax[i].t.Equals(minmax[i].t2))
                {
                    conTrans[i] = true;
                }
                if (minmax[i].r.Equals(minmax[i].r2))
                {
                    conRot[i] = true;
                }
                if (minmax[i].s.Equals(minmax[i].s2))
                {
                    conScale[i] = true;
                }

                if (hasTrans[i])
                {
                    flag |= 0x01000000;
                }
                if (hasRot[i])
                {
                    flag |= 0x02000000;
                }
                if (hasScale[i])
                {
                    flag |= 0x04000000;
                }

                if (conTrans[i] && hasTrans[i])
                {
                    flag |= 0x00200000;
                }
                else
                {
                    flag |= 0x00080000;
                }

                if (conRot[i] && hasRot[i])
                {
                    flag |= 0x00007000;
                }
                else
                {
                    flag |= 0x00005000;
                }

                if (conScale[i] && hasScale[i])
                {
                    flag |= 0x00000200;
                }
                else
                {
                    flag |= 0x00000080;
                }

                flag |= 0x00000001;

                int hash = (int)getNodeId(vbn, nodeid[i]).boneId;
                //if(hash == -1)
                //hash = (int)FileData.crc32(getNodeId(nodeid.get(i)).name);
                o.writeInt(flag);      // flags...
                o.writeInt(hash);      //hash
                o.writeInt(t1.size()); // Offset in 1 table
                o.writeInt(t2Size);    // Offset in 2 table

                // calculate size needed
                if (hasTrans[i])
                {
                    t1.writeFloat(minmax[i].t.X);
                    t1.writeFloat(minmax[i].t.Y);
                    t1.writeFloat(minmax[i].t.Z);

                    if (!conTrans[i])
                    {
                        minmax[i].t2.X -= minmax[i].t.X;
                        minmax[i].t2.Y -= minmax[i].t.Y;
                        minmax[i].t2.Z -= minmax[i].t.Z;

                        t1.writeFloat(minmax[i].t2.X);
                        t1.writeFloat(minmax[i].t2.Y);
                        t1.writeFloat(minmax[i].t2.Z);

                        t2Size += 6;
                    }
                }

                if (hasRot[i])
                {
                    t1.writeFloat(minmax[i].r.X);
                    t1.writeFloat(minmax[i].r.Y);
                    t1.writeFloat(minmax[i].r.Z);

                    if (!conRot[i])
                    {
                        minmax[i].r2.X -= minmax[i].r.X;
                        minmax[i].r2.Y -= minmax[i].r.Y;
                        minmax[i].r2.Z -= minmax[i].r.Z;

                        t1.writeFloat(minmax[i].r2.X);
                        t1.writeFloat(minmax[i].r2.Y);
                        t1.writeFloat(minmax[i].r2.Z);

                        t2Size += 6;
                    }
                }

                if (hasScale[i])
                {
                    t1.writeFloat(minmax[i].s.X);
                    t1.writeFloat(minmax[i].s.Y);
                    t1.writeFloat(minmax[i].s.Z);

                    if (!conScale[i])
                    {
                        minmax[i].s2.X -= minmax[i].s.X;
                        minmax[i].s2.Y -= minmax[i].s.Y;
                        minmax[i].s2.Z -= minmax[i].s.Z;

                        t1.writeFloat(minmax[i].s2.X);
                        t1.writeFloat(minmax[i].s2.Y);
                        t1.writeFloat(minmax[i].s2.Z);

                        t2Size += 6;
                    }
                }
            }

            o.writeIntAt(o.size(), 0x18);

            o.writeOutput(t1);

            o.writeIntAt(o.size(), 0x1C);

            // INTERPOLATION

            a.setFrame(0);

            for (int i = 0; i < a.size(); i++)
            {
                a.nextFrame(vbn);
                for (int j = 0; j < nodeid.Count; j++)
                {
                    Bone node = getNodeId(vbn, nodeid[j]);

                    if (hasTrans[j] && !conTrans[j])
                    {
                        t2.writeShort((int)(((node.pos.X - minmax[j].t.X) / minmax[j].t2.X) * 0xFFFF));
                        t2.writeShort((int)(((node.pos.Y - minmax[j].t.Y) / minmax[j].t2.Y) * 0xFFFF));
                        t2.writeShort((int)(((node.pos.Z - minmax[j].t.Z) / minmax[j].t2.Z) * 0xFFFF));
                    }

                    if (hasRot[j] && !conRot[j])
                    {
                        //					float[] fix = Node.fix360(node.nrx, node.nry, node.nrz);
                        //float[] f = CalculateRotation(node.nrx, node.nry, node.nrz);
                        Quaternion r = node.rot;

                        t2.writeShort((int)(((r.X - minmax[j].r.X) / minmax[j].r2.X) * 0xFFFF));
                        t2.writeShort((int)(((r.Y - minmax[j].r.Y) / minmax[j].r2.Y) * 0xFFFF));
                        t2.writeShort((int)(((r.Z - minmax[j].r.Z) / minmax[j].r2.Z) * 0xFFFF));
                    }

                    if (hasScale[j] && !conScale[j])
                    {
                        t2.writeShort((int)(((node.sca.X - minmax[j].s.X) / minmax[j].s2.X) * 0xFFFF));
                        t2.writeShort((int)(((node.sca.Y - minmax[j].s.Y) / minmax[j].s2.Y) * 0xFFFF));
                        t2.writeShort((int)(((node.sca.Z - minmax[j].s.Z) / minmax[j].s2.Z) * 0xFFFF));
                    }
                }

                if (i == 0)
                {
                    o.writeShortAt(t2.size(), 0x12);
                }
            }

            o.writeOutput(t2);
            return(o.getBytes());
        }
Beispiel #23
0
        public byte[] Rebuild(int pos)
        {
            FileOutput f = new FileOutput();

            f.Endian = Endianness.Big;

            f.writeInt(pos + f.pos() + 0x20);
            f.writeInt(matHash);
            f.writeInt(properties.Count);
            int nameOffset = pos + f.pos() + 0x15 + name.Length;

            while (nameOffset % 4 != 0)
            {
                nameOffset++;
            }
            f.writeInt(nameOffset);
            f.writeFlag(hasPat);
            f.writeBytes(new byte[3]);
            //Write all the mat data into a buffer (g) then write pat offset
            int        pos2 = pos + f.pos() + 4;
            FileOutput g    = new FileOutput();

            g.Endian = Endianness.Big;

            if (matHash2 != 0)
            {
                g.writeInt(pos2 + g.pos() + 0x8);
                g.writeInt(matHash);
            }
            else
            {
                g.writeBytes(new byte[8]);
            }

            g.writeString(name);
            g.writeByte(0);
            while ((pos2 + g.pos()) % 0x10 != 0)
            {
                g.writeByte(0);
            }

            int position = pos2 + g.pos() + properties.Count * 4;

            while (position % 16 != 0)
            {
                position++;
            }

            List <byte[]> builtProperties = new List <byte[]>();

            foreach (MatData prop in properties)
            {
                g.writeInt(position);
                byte[] b = prop.Rebuild(position);
                builtProperties.Add(b);
                position += b.Length;
                while (position % 16 != 0)
                {
                    position++;
                }
            }

            while ((pos2 + g.pos()) % 16 != 0)
            {
                g.writeByte(0);
            }

            foreach (byte[] b in builtProperties)
            {
                g.writeBytes(b);
                while ((pos2 + g.pos()) % 16 != 0)
                {
                    g.writeByte(0);
                }
            }

            f.writeInt(pos2 + g.pos());
            f.writeBytes(g.getBytes());
            if (hasPat)
            {
                f.writeBytes(pat0.Rebuild(f.pos()));
            }

            return(f.getBytes());
        }
Beispiel #24
0
        public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn)
        {
            if (vbn == null || a == null)
            {
                return new byte[] { }
            }
            ;

            // Test Actual Bones
            //-------------------------

            List <Animation.KeyNode> toRem = new List <Animation.KeyNode>();

            for (int j = 0; j < a.Bones.Count; j++)
            {
                Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]);
                Bone b = vbn.getBone(keynode.Text);

                if (b == null)
                {
                    toRem.Add(keynode);
                }
            }
            foreach (Animation.KeyNode r in toRem)
            {
                Console.WriteLine("Removing " + r.Text);
                a.Bones.Remove(r);
            }

            //-------------------------

            FileOutput o = new FileOutput();

            o.Endian = Endianness.Big;

            FileOutput t1 = new FileOutput();

            t1.Endian = Endianness.Big;

            FileOutput t2 = new FileOutput();

            t2.Endian = Endianness.Big;

            o.writeString("OMO ");
            o.writeShort(1);        //idk
            o.writeShort(3);        //idk

            o.writeInt(0x091E100C); //flags??


            o.writeShort(0);             //padding
            o.writeShort(a.Bones.Count); // numOfNodes

            o.writeShort(a.FrameCount);  // frame size
            o.writeShort(0);             // frame start ??

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

            o.writeIntAt(o.size(), 0x14);

            // ASSESSMENT
            Vector3[] maxT     = new Vector3[a.Bones.Count], minT = new Vector3[a.Bones.Count];
            Vector4[] maxR     = new Vector4[a.Bones.Count], minR = new Vector4[a.Bones.Count];
            Vector3[] maxS     = new Vector3[a.Bones.Count], minS = new Vector3[a.Bones.Count];
            bool[]    hasScale = new bool[a.Bones.Count];
            bool[]    hasTrans = new bool[a.Bones.Count];
            bool[]    hasRot   = new bool[a.Bones.Count];

            bool[] conScale = new bool[a.Bones.Count];
            bool[] conTrans = new bool[a.Bones.Count];
            bool[] conRot   = new bool[a.Bones.Count];

            a.SetFrame(0);

            List <List <Bone> > Frames = new List <List <Bone> >();

            {
                for (int j = 0; j < a.Bones.Count; j++)
                {
                    Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]);
                    if (keynode.XPOS.HasAnimation() || keynode.YPOS.HasAnimation() || keynode.ZPOS.HasAnimation())
                    {
                        hasTrans[j] = true;
                    }
                    if (keynode.XROT.HasAnimation())
                    {
                        hasRot[j] = true;
                    }
                    if (keynode.XSCA.HasAnimation() || keynode.YSCA.HasAnimation() || keynode.ZSCA.HasAnimation())
                    {
                        hasScale[j] = true;
                    }

                    maxT[j] = new Vector3(-999f, -999f, -999f);
                    minT[j] = new Vector3(999f, 999f, 999f);
                    maxS[j] = new Vector3(-999f, -999f, -999f);
                    minS[j] = new Vector3(999f, 999f, 999f);
                    maxR[j] = new Vector4(-999f, -999f, -999f, -999f);
                    minR[j] = new Vector4(999f, 999f, 999f, 999f);

                    foreach (Animation.KeyFrame key in keynode.XPOS.Keys)
                    {
                        maxT[j].X = Math.Max(maxT[j].X, key.Value);
                        minT[j].X = Math.Min(minT[j].X, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.YPOS.Keys)
                    {
                        maxT[j].Y = Math.Max(maxT[j].Y, key.Value);
                        minT[j].Y = Math.Min(minT[j].Y, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.ZPOS.Keys)
                    {
                        maxT[j].Z = Math.Max(maxT[j].Z, key.Value);
                        minT[j].Z = Math.Min(minT[j].Z, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.XSCA.Keys)
                    {
                        maxS[j].X = Math.Max(maxS[j].X, key.Value);
                        minS[j].X = Math.Min(minS[j].X, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.YSCA.Keys)
                    {
                        maxS[j].Y = Math.Max(maxS[j].Y, key.Value);
                        minS[j].Y = Math.Min(minS[j].Y, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.ZSCA.Keys)
                    {
                        maxS[j].Z = Math.Max(maxS[j].Z, key.Value);
                        minS[j].Z = Math.Min(minS[j].Z, key.Value);
                    }

                    Bone b = vbn.getBone(keynode.Text);
                    for (int i = 0; i < a.FrameCount; i++)
                    {
                        Quaternion r = new Quaternion();
                        if (keynode.RotType == Animation.RotationType.QUATERNION)
                        {
                            Animation.KeyFrame[] x  = keynode.XROT.GetFrame(i);
                            Animation.KeyFrame[] y  = keynode.YROT.GetFrame(i);
                            Animation.KeyFrame[] z  = keynode.ZROT.GetFrame(i);
                            Animation.KeyFrame[] w  = keynode.WROT.GetFrame(i);
                            Quaternion           q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value);
                            Quaternion           q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value);
                            if (x[0].Frame == i)
                            {
                                r = q1;
                            }
                            else
                            if (x[1].Frame == i)
                            {
                                r = q2;
                            }
                            else
                            {
                                r = Quaternion.Slerp(q1, q2, (i - x[0].Frame) / (x[1].Frame - x[0].Frame));
                            }
                        }
                        else
                        if (keynode.RotType == Animation.RotationType.EULER)
                        {
                            float x = keynode.XROT.HasAnimation() ? keynode.XROT.GetValue(i) : b.rotation[0];
                            float y = keynode.YROT.HasAnimation() ? keynode.YROT.GetValue(i) : b.rotation[1];
                            float z = keynode.ZROT.HasAnimation() ? keynode.ZROT.GetValue(i) : b.rotation[2];
                            r = Animation.EulerToQuat(z, y, x);
                        }
                        r.Normalize();

                        maxR[j].X = Math.Max(maxR[j].X, r.X);
                        minR[j].X = Math.Min(minR[j].X, r.X);
                        maxR[j].Y = Math.Max(maxR[j].Y, r.Y);
                        minR[j].Y = Math.Min(minR[j].Y, r.Y);
                        maxR[j].Z = Math.Max(maxR[j].Z, r.Z);
                        minR[j].Z = Math.Min(minR[j].Z, r.Z);
                    }

                    //if (b == null)continue;
                    if (b != null)
                    {
                        if (maxT[j].X == -999)
                        {
                            maxT[j].X = b.position[0];
                        }
                        if (maxT[j].Y == -999)
                        {
                            maxT[j].Y = b.position[1];
                        }
                        if (maxT[j].Z == -999)
                        {
                            maxT[j].Z = b.position[2];
                        }
                        if (minT[j].X == -999)
                        {
                            minT[j].X = b.position[0];
                        }
                        if (minT[j].Y == -999)
                        {
                            minT[j].Y = b.position[1];
                        }
                        if (minT[j].Z == -999)
                        {
                            minT[j].Z = b.position[2];
                        }

                        if (maxS[j].X == -999)
                        {
                            maxS[j].X = b.scale[0];
                        }
                        if (maxS[j].Y == -999)
                        {
                            maxS[j].Y = b.scale[1];
                        }
                        if (maxS[j].Z == -999)
                        {
                            maxS[j].Z = b.scale[2];
                        }
                        if (minS[j].X == -999)
                        {
                            minS[j].X = b.scale[0];
                        }
                        if (minS[j].Y == -999)
                        {
                            minS[j].Y = b.scale[1];
                        }
                        if (minS[j].Z == -999)
                        {
                            minS[j].Z = b.scale[2];
                        }
                    }
                }
            }

            //TODO: Euler Rotation Values

            /*VBN tempvbn = new VBN();
             * a.SetFrame(0);
             * for (int i = 0; i < a.FrameCount; i++)
             * {
             *  //Frames.Add(new List<Bone>());
             *  for (int j = 0; j < a.Bones.Count; j++)
             *  {
             *      Animation.KeyNode keynode = a.Bones[j];
             *      Bone b = vbn.getBone(keynode.Text);
             *      //if(b == null) continue;
             *      maxR[j].X = Math.Max(maxR[j].X, b.rot.X);
             *      minR[j].X = Math.Min(minR[j].X, b.rot.X);
             *      maxR[j].Y = Math.Max(maxR[j].Y, b.rot.Y);
             *      minR[j].Y = Math.Min(minR[j].Y, b.rot.Y);
             *      maxR[j].Z = Math.Max(maxR[j].Z, b.rot.Z);
             *      minR[j].Z = Math.Min(minR[j].Z, b.rot.Z);
             *
             *      Bone f1 = new Bone(tempvbn);
             *      f1.pos = b.pos;
             *      f1.rot = b.rot;
             *      f1.sca = b.sca;
             *      //Frames[i].Add(f1);
             *  }
             *  a.NextFrame(vbn);
             * }*/

            // NODE INFO

            int t2Size = 0;

            for (int i = 0; i < a.Bones.Count; i++)
            {
                int flag = 0;

                conRot[i]   = false;
                conScale[i] = false;
                conTrans[i] = false;

                // check for constant
                if (maxT[i].Equals(minT[i]))
                {
                    conTrans[i] = true;
                }
                if (maxR[i].Equals(minR[i]))
                {
                    conRot[i] = true;
                }
                if (maxS[i].Equals(minS[i]))
                {
                    conScale[i] = true;
                }

                if (hasTrans[i])
                {
                    flag |= 0x01000000;
                }
                if (hasRot[i])
                {
                    flag |= 0x02000000;
                }
                if (hasScale[i])
                {
                    flag |= 0x04000000;
                }

                if (conTrans[i] && hasTrans[i])
                {
                    flag |= 0x00200000;
                }
                else
                {
                    flag |= 0x00080000;
                }

                if (conRot[i] && hasRot[i])
                {
                    flag |= 0x00007000;
                }
                else
                {
                    flag |= 0x00005000;
                }

                if (conScale[i] && hasScale[i])
                {
                    flag |= 0x00000200;
                }
                else
                {
                    flag |= 0x00000080;
                }

                flag |= 0x00000001;

                //uint id = 999;

                Bone b    = vbn.getBone(a.Bones[i].Text);
                int  hash = -1;
                if (MainForm.Hashes.names.ContainsKey(a.Bones[i].Text))
                {
                    hash = (int)MainForm.Hashes.names[a.Bones[i].Text];
                }
                else
                {
                    if (b != null)
                    {
                        hash = (int)b.boneId;
                    }
                    else
                    {
                        continue;
                    }
                }
                //if(hash == -1)
                //hash = (int)FileData.crc32(getNodeId(nodeid.get(i)).name);
                o.writeInt(flag);      // flags...
                o.writeInt(hash);      //hash
                o.writeInt(t1.size()); // Offset in 1 table
                o.writeInt(t2Size);    // Offset in 2 table

                // calculate size needed
                if (hasTrans[i])
                {
                    t1.writeFloat(minT[i].X);
                    t1.writeFloat(minT[i].Y);
                    t1.writeFloat(minT[i].Z);

                    if (!conTrans[i])
                    {
                        maxT[i].X -= minT[i].X;
                        maxT[i].Y -= minT[i].Y;
                        maxT[i].Z -= minT[i].Z;

                        t1.writeFloat(maxT[i].X);
                        t1.writeFloat(maxT[i].Y);
                        t1.writeFloat(maxT[i].Z);

                        t2Size += 6;
                    }
                }

                if (hasRot[i])
                {
                    t1.writeFloat(minR[i].X);
                    t1.writeFloat(minR[i].Y);
                    t1.writeFloat(minR[i].Z);

                    if (!conRot[i])
                    {
                        maxR[i].X -= minR[i].X;
                        maxR[i].Y -= minR[i].Y;
                        maxR[i].Z -= minR[i].Z;

                        t1.writeFloat(maxR[i].X);
                        t1.writeFloat(maxR[i].Y);
                        t1.writeFloat(maxR[i].Z);

                        t2Size += 6;
                    }
                }

                if (hasScale[i])
                {
                    t1.writeFloat(minS[i].X);
                    t1.writeFloat(minS[i].Y);
                    t1.writeFloat(minS[i].Z);

                    if (!conScale[i])
                    {
                        maxS[i].X -= minS[i].X;
                        maxS[i].Y -= minS[i].Y;
                        maxS[i].Z -= minS[i].Z;

                        t1.writeFloat(maxS[i].X);
                        t1.writeFloat(maxS[i].Y);
                        t1.writeFloat(maxS[i].Z);

                        t2Size += 6;
                    }
                }
            }

            o.writeIntAt(o.size(), 0x18);

            o.writeOutput(t1);

            o.writeIntAt(o.size(), 0x1C);

            // INTERPOLATION

            a.SetFrame(0);

            bool go = true;

            for (int i = 0; i < a.FrameCount; i++)
            {
                //a.NextFrame(vbn);
                for (int j = 0; j < a.Bones.Count; j++)
                {
                    Bone node = vbn.getBone(a.Bones[j].Text);

                    Animation.KeyNode anode = a.Bones[j];
                    //if (node == null) continue;

                    if (hasTrans[j] && !conTrans[j])
                    {
                        t2.writeShort((int)(((anode.XPOS.GetValue(i) - minT[j].X) / maxT[j].X) * 0xFFFF));
                        t2.writeShort((int)(((anode.YPOS.GetValue(i) - minT[j].Y) / maxT[j].Y) * 0xFFFF));
                        t2.writeShort((int)(((anode.ZPOS.GetValue(i) - minT[j].Z) / maxT[j].Z) * 0xFFFF));
                    }

                    if (hasRot[j] && !conRot[j])
                    {
                        Quaternion r = new Quaternion();
                        if (anode.RotType == Animation.RotationType.QUATERNION)
                        {
                            Animation.KeyFrame[] x  = anode.XROT.GetFrame(i);
                            Animation.KeyFrame[] y  = anode.YROT.GetFrame(i);
                            Animation.KeyFrame[] z  = anode.ZROT.GetFrame(i);
                            Animation.KeyFrame[] w  = anode.WROT.GetFrame(i);
                            Quaternion           q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value);
                            Quaternion           q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value);
                            if (x[0].Frame == i)
                            {
                                r = q1;
                            }
                            else
                            if (x[1].Frame == i)
                            {
                                r = q2;
                            }
                            else
                            {
                                r = Quaternion.Slerp(q1, q2, (i - x[0].Frame) / (x[1].Frame - x[0].Frame));
                            }
                        }
                        else
                        if (anode.RotType == Animation.RotationType.EULER)
                        {
                            float x = anode.XROT.HasAnimation() ? anode.XROT.GetValue(i) : node.rotation[0];
                            float y = anode.YROT.HasAnimation() ? anode.YROT.GetValue(i) : node.rotation[1];
                            float z = anode.ZROT.HasAnimation() ? anode.ZROT.GetValue(i) : node.rotation[2];
                            r = Animation.EulerToQuat(z, y, x);
                        }
                        r.Normalize();
                        t2.writeShort((int)(((r.X - minR[j].X) / maxR[j].X) * 0xFFFF));
                        t2.writeShort((int)(((r.Y - minR[j].Y) / maxR[j].Y) * 0xFFFF));
                        t2.writeShort((int)(((r.Z - minR[j].Z) / maxR[j].Z) * 0xFFFF));
                    }

                    if (hasScale[j] && !conScale[j])
                    {
                        t2.writeShort((int)(((anode.XSCA.GetValue(i) - minS[j].X) / maxS[j].X) * 0xFFFF));
                        t2.writeShort((int)(((anode.YSCA.GetValue(i) - minS[j].Y) / maxS[j].Y) * 0xFFFF));
                        t2.writeShort((int)(((anode.ZSCA.GetValue(i) - minS[j].Z) / maxS[j].Z) * 0xFFFF));
                    }
                }

                if (go)
                {
                    o.writeShortAt(t2.size(), 0x12);
                    go = false;
                }
            }

            o.writeOutput(t2);
            return(o.getBytes());
        }
    }
Beispiel #25
0
        public override byte[] Rebuild()
        {
            FileOutput f = new FileOutput();

            f.Endian = Endianness.Big;

            f.writeString("MTA4");
            f.writeInt((int)unknown);
            f.writeInt((int)numFrames);
            f.writeInt(0);
            f.writeInt((int)numFrames - 1);
            f.writeInt((int)frameRate);
            f.writeInt(matEntries.Count);
            if (matEntries.Count > 0)
            {
                f.writeInt(0x38);
            }
            else
            {
                f.writeInt(0);
            }
            f.writeInt(visEntries.Count);
            if (visEntries.Count > 0)
            {
                f.writeInt(0x38 + 4 * matEntries.Count);
            }
            else
            {
                f.writeInt(0);
            }
            for (int i = 0; i < 0x10; i++)
            {
                f.writeByte(0);
            }

            List <byte[]> matEntriesBuilt = new List <byte[]>();
            List <byte[]> visEntriesBuilt = new List <byte[]>();

            int position = 0x38 + matEntries.Count + visEntries.Count;

            while (position % 0x10 != 0)
            {
                position++;
            }

            foreach (MatEntry m in matEntries)
            {
                byte[] b = m.Rebuild(position);
                matEntriesBuilt.Add(b);
                f.writeInt(position);
                position += b.Length;
                while (position % 0x10 != 0)
                {
                    position++;
                }
            }

            foreach (VisEntry v in visEntries)
            {
                byte[] b = v.Rebuild(position);
                matEntriesBuilt.Add(b);
                f.writeInt(position);
                position += b.Length;
                while (position % 0x10 != 0)
                {
                    position++;
                }
            }

            while (f.pos() % 0x10 != 0)
            {
                f.writeByte(0);
            }

            foreach (byte[] b in matEntriesBuilt)
            {
                f.writeBytes(b);
                while (f.pos() % 0x10 != 0)
                {
                    f.writeByte(0);
                }
            }

            foreach (byte[] b in visEntriesBuilt)
            {
                f.writeBytes(b);
                while (f.pos() % 0x10 != 0)
                {
                    f.writeByte(0);
                }
            }

            return(f.getBytes());
        }
Beispiel #26
0
        public static byte[] CreateOMOFromAnimation(Animation a, VBN vbn)
        {
            FileOutput o = new FileOutput();

            o.Endian = Endianness.Big;

            FileOutput t1 = new FileOutput();

            t1.Endian = Endianness.Big;

            FileOutput t2 = new FileOutput();

            t2.Endian = Endianness.Big;

            o.writeString("OMO ");
            o.writeShort(1);        //idk
            o.writeShort(3);        //idk

            o.writeInt(0x091E100C); //flags??


            o.writeShort(0);             //padding
            o.writeShort(a.Bones.Count); // numOfNodes

            o.writeShort(a.FrameCount);  // frame size
            o.writeShort(0);             // frame start ??

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

            o.writeIntAt(o.size(), 0x14);

            // ASSESSMENT
            Vector3[] maxT     = new Vector3[a.Bones.Count], minT = new Vector3[a.Bones.Count];
            Vector4[] maxR     = new Vector4[a.Bones.Count], minR = new Vector4[a.Bones.Count];
            Vector3[] maxS     = new Vector3[a.Bones.Count], minS = new Vector3[a.Bones.Count];
            bool[]    hasScale = new bool[a.Bones.Count];
            bool[]    hasTrans = new bool[a.Bones.Count];
            bool[]    hasRot   = new bool[a.Bones.Count];

            bool[] conScale = new bool[a.Bones.Count];
            bool[] conTrans = new bool[a.Bones.Count];
            bool[] conRot   = new bool[a.Bones.Count];

            a.SetFrame(0);

            //for (int i = 0; i < a.FrameCount; i++)
            {
                //a.NextFrame(vbn);

                for (int j = 0; j < a.Bones.Count; j++)
                {
                    Animation.KeyNode keynode = ((Animation.KeyNode)a.Bones[j]);
                    if (keynode.XPOS.HasAnimation() || keynode.YPOS.HasAnimation() || keynode.ZPOS.HasAnimation())
                    {
                        hasTrans[j] = true;
                    }
                    if (keynode.XROT.HasAnimation())
                    {
                        hasRot[j] = true;
                    }
                    if (keynode.XSCA.HasAnimation() || keynode.YSCA.HasAnimation() || keynode.ZSCA.HasAnimation())
                    {
                        hasScale[j] = true;
                    }

                    maxT[j] = new Vector3(-999f, -999f, -999f);
                    minT[j] = new Vector3(999f, 999f, 999f);
                    maxS[j] = new Vector3(-999f, -999f, -999f);
                    minS[j] = new Vector3(999f, 999f, 999f);
                    maxR[j] = new Vector4(-999f, -999f, -999f, -999f);
                    minR[j] = new Vector4(999f, 999f, 999f, 999f);

                    foreach (Animation.KeyFrame key in keynode.XPOS.Keys)
                    {
                        maxT[j].X = Math.Max(maxT[j].X, key.Value);
                        minT[j].X = Math.Min(minT[j].X, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.YPOS.Keys)
                    {
                        maxT[j].Y = Math.Max(maxT[j].Y, key.Value);
                        minT[j].Y = Math.Min(minT[j].Y, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.ZPOS.Keys)
                    {
                        maxT[j].Z = Math.Max(maxT[j].Z, key.Value);
                        minT[j].Z = Math.Min(minT[j].Z, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.XSCA.Keys)
                    {
                        maxS[j].X = Math.Max(maxS[j].X, key.Value);
                        minS[j].X = Math.Min(minS[j].X, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.YSCA.Keys)
                    {
                        maxS[j].Y = Math.Max(maxS[j].Y, key.Value);
                        minS[j].Y = Math.Min(minS[j].Y, key.Value);
                    }
                    foreach (Animation.KeyFrame key in keynode.ZSCA.Keys)
                    {
                        maxS[j].Z = Math.Max(maxS[j].Z, key.Value);
                        minS[j].Z = Math.Min(minS[j].Z, key.Value);
                    }
                    //TODO: Euler Rotation Values
                    a.SetFrame(0);
                    Bone b = vbn.getBone(keynode.Text);
                    if (b == null)
                    {
                        continue;
                    }
                    for (int i = 0; i < a.FrameCount; i++)
                    {
                        maxR[j].X = Math.Max(maxR[j].X, b.rot.X);
                        minR[j].X = Math.Min(minR[j].X, b.rot.X);
                        maxR[j].Y = Math.Max(maxR[j].Y, b.rot.Y);
                        minR[j].Y = Math.Min(minR[j].Y, b.rot.Y);
                        maxR[j].Z = Math.Max(maxR[j].Z, b.rot.Z);
                        minR[j].Z = Math.Min(minR[j].Z, b.rot.Z);
                        a.NextFrame(vbn);
                    }

                    if (b != null)
                    {
                        if (maxT[j].X == -999)
                        {
                            maxT[j].X = b.position[0];
                        }
                        if (maxT[j].Y == -999)
                        {
                            maxT[j].Y = b.position[1];
                        }
                        if (maxT[j].Z == -999)
                        {
                            maxT[j].Z = b.position[2];
                        }
                        if (minT[j].X == -999)
                        {
                            minT[j].X = b.position[0];
                        }
                        if (minT[j].Y == -999)
                        {
                            minT[j].Y = b.position[1];
                        }
                        if (minT[j].Z == -999)
                        {
                            minT[j].Z = b.position[2];
                        }

                        if (maxS[j].X == -999)
                        {
                            maxS[j].X = b.scale[0];
                        }
                        if (maxS[j].Y == -999)
                        {
                            maxS[j].Y = b.scale[1];
                        }
                        if (maxS[j].Z == -999)
                        {
                            maxS[j].Z = b.scale[2];
                        }
                        if (minS[j].X == -999)
                        {
                            minS[j].X = b.scale[0];
                        }
                        if (minS[j].Y == -999)
                        {
                            minS[j].Y = b.scale[1];
                        }
                        if (minS[j].Z == -999)
                        {
                            minS[j].Z = b.scale[2];
                        }
                    }
                }
            }

            // NODE INFO

            int t2Size = 0;

            for (int i = 0; i < a.Bones.Count; i++)
            {
                int flag = 0;

                conRot[i]   = false;
                conScale[i] = false;
                conTrans[i] = false;

                // check for constant
                if (maxT[i].Equals(minT[i]))
                {
                    conTrans[i] = true;
                }
                if (maxR[i].Equals(minR[i]))
                {
                    conRot[i] = true;
                }
                if (maxS[i].Equals(minS[i]))
                {
                    conScale[i] = true;
                }

                if (hasTrans[i])
                {
                    flag |= 0x01000000;
                }
                if (hasRot[i])
                {
                    flag |= 0x02000000;
                }
                if (hasScale[i])
                {
                    flag |= 0x04000000;
                }

                if (conTrans[i] && hasTrans[i])
                {
                    flag |= 0x00200000;
                }
                else
                {
                    flag |= 0x00080000;
                }

                if (conRot[i] && hasRot[i])
                {
                    flag |= 0x00007000;
                }
                else
                {
                    flag |= 0x00005000;
                }

                if (conScale[i] && hasScale[i])
                {
                    flag |= 0x00000200;
                }
                else
                {
                    flag |= 0x00000080;
                }

                flag |= 0x00000001;

                //uint id = 999;
                Bone b    = vbn.getBone(a.Bones[i].Text);
                int  hash = -1;
                if (b != null)
                {
                    hash = (int)b.boneId;
                }
                else
                {
                    continue;
                }
                //if(hash == -1)
                //hash = (int)FileData.crc32(getNodeId(nodeid.get(i)).name);
                o.writeInt(flag);      // flags...
                o.writeInt(hash);      //hash
                o.writeInt(t1.size()); // Offset in 1 table
                o.writeInt(t2Size);    // Offset in 2 table

                // calculate size needed
                if (hasTrans[i])
                {
                    t1.writeFloat(minT[i].X);
                    t1.writeFloat(minT[i].Y);
                    t1.writeFloat(minT[i].Z);

                    if (!conTrans[i])
                    {
                        maxT[i].X -= minT[i].X;
                        maxT[i].Y -= minT[i].Y;
                        maxT[i].Z -= minT[i].Z;

                        t1.writeFloat(maxT[i].X);
                        t1.writeFloat(maxT[i].Y);
                        t1.writeFloat(maxT[i].Z);

                        t2Size += 6;
                    }
                }

                if (hasRot[i])
                {
                    t1.writeFloat(minR[i].X);
                    t1.writeFloat(minR[i].Y);
                    t1.writeFloat(minR[i].Z);

                    if (!conRot[i])
                    {
                        maxR[i].X -= minR[i].X;
                        maxR[i].Y -= minR[i].Y;
                        maxR[i].Z -= minR[i].Z;

                        t1.writeFloat(maxR[i].X);
                        t1.writeFloat(maxR[i].Y);
                        t1.writeFloat(maxR[i].Z);

                        t2Size += 6;
                    }
                }

                if (hasScale[i])
                {
                    t1.writeFloat(minS[i].X);
                    t1.writeFloat(minS[i].Y);
                    t1.writeFloat(minS[i].Z);

                    if (!conScale[i])
                    {
                        maxS[i].X -= minS[i].X;
                        maxS[i].Y -= minS[i].Y;
                        maxS[i].Z -= minS[i].Z;

                        t1.writeFloat(maxS[i].X);
                        t1.writeFloat(maxS[i].Y);
                        t1.writeFloat(maxS[i].Z);

                        t2Size += 6;
                    }
                }
            }

            o.writeIntAt(o.size(), 0x18);

            o.writeOutput(t1);

            o.writeIntAt(o.size(), 0x1C);

            // INTERPOLATION

            a.SetFrame(0);

            for (int i = 0; i < a.FrameCount; i++)
            {
                //Console.WriteLine("Workin on" + i);
                a.NextFrame(vbn);
                for (int j = 0; j < a.Bones.Count; j++)
                {
                    Bone node = vbn.getBone(a.Bones[j].Text);
                    if (node == null)
                    {
                        continue;
                    }

                    if (hasTrans[j] && !conTrans[j])
                    {
                        t2.writeShort((int)(((node.pos.X - minT[j].X) / maxT[j].X) * 0xFFFF));
                        t2.writeShort((int)(((node.pos.Y - minT[j].Y) / maxT[j].Y) * 0xFFFF));
                        t2.writeShort((int)(((node.pos.Z - minT[j].Z) / maxT[j].Z) * 0xFFFF));
                    }

                    if (hasRot[j] && !conRot[j])
                    {
                        Quaternion r = node.rot;

                        t2.writeShort((int)(((r.X - minR[j].X) / maxR[j].X) * 0xFFFF));
                        t2.writeShort((int)(((r.Y - minR[j].Y) / maxR[j].Y) * 0xFFFF));
                        t2.writeShort((int)(((r.Z - minR[j].Z) / maxR[j].Z) * 0xFFFF));
                    }

                    if (hasScale[j] && !conScale[j])
                    {
                        t2.writeShort((int)(((node.sca.X - minS[j].X) / maxS[j].X) * 0xFFFF));
                        t2.writeShort((int)(((node.sca.Y - minS[j].Y) / maxS[j].Y) * 0xFFFF));
                        t2.writeShort((int)(((node.sca.Z - minS[j].Z) / maxS[j].Z) * 0xFFFF));
                    }
                }

                if (i == 0)
                {
                    o.writeShortAt(t2.size(), 0x12);
                }
            }

            //Console.WriteLine("Saving");
            o.writeOutput(t2);
            return(o.getBytes());
        }
Beispiel #27
0
        public override byte[] Rebuild()
        {
            FileOutput f = new FileOutput();

            f.Endian = Endianness.Big;

            f.writeHex("000000010A014C56443101");
            f.writeInt(collisions.Count);
            foreach (Collision c in collisions)
            {
                c.save(f);
            }
            f.writeByte(1);
            f.writeInt(spawns.Count);
            foreach (Point p in spawns)
            {
                f.writeHex("020401017735BB750000000201");
                f.writeString(p.name.PadRight(0x38, (char)0));
                f.writeByte(1);
                f.writeString(p.subname.PadRight(0x40, (char)0));
                f.writeByte(1);
                f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
                f.writeFloat(p.x);
                f.writeFloat(p.y);
            }
            f.writeByte(1);
            f.writeInt(respawns.Count);
            foreach (Point p in respawns)
            {
                f.writeHex("020401017735BB750000000201");
                f.writeString(p.name.PadRight(0x38, (char)0));
                f.writeByte(1);
                f.writeString(p.subname.PadRight(0x40, (char)0));
                f.writeByte(1);
                f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
                f.writeFloat(p.x);
                f.writeFloat(p.y);
            }
            f.writeByte(1);
            f.writeInt(cameraBounds.Count);
            foreach (Bounds b in cameraBounds)
            {
                f.writeHex("020401017735BB750000000201");
                f.writeString(b.name.PadRight(0x38, (char)0));
                f.writeByte(1);
                f.writeString(b.subname.PadRight(0x40, (char)0));
                f.writeByte(1);
                f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
                f.writeFloat(b.left);
                f.writeFloat(b.right);
                f.writeFloat(b.top);
                f.writeFloat(b.bottom);
            }
            f.writeByte(1);
            f.writeInt(blastzones.Count);
            foreach (Bounds b in blastzones)
            {
                f.writeHex("020401017735BB750000000201");
                f.writeString(b.name.PadRight(0x38, (char)0));
                f.writeByte(1);
                f.writeString(b.subname.PadRight(0x40, (char)0));
                f.writeByte(1);
                f.writeHex("00000000000000000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001");
                f.writeFloat(b.left);
                f.writeFloat(b.right);
                f.writeFloat(b.top);
                f.writeFloat(b.bottom);
            }

            for (int i = 0; i < 7; i++)
            {
                f.writeByte(1);
                f.writeInt(0);
            }

            f.writeByte(1);
            f.writeInt(items.Count);
            foreach (ItemSpawner item in items)
            {
                item.save(f);
            }

            f.writeByte(1);
            f.writeInt(generalShapes.Count);
            foreach (LVDGeneralShape shape in generalShapes)
            {
                shape.save(f);
            }


            f.writeByte(1);
            f.writeInt(generalPoints.Count);
            foreach (Point p in generalPoints)
            {
                f.writeHex("010401017735BB750000000201");
                f.writeChars(p.name.PadRight(0x38, (char)0).ToCharArray());
                f.writeByte(1);
                f.writeChars(p.subname.PadRight(0x40, (char)0).ToCharArray());
                f.writeByte(1);
                f.writeHex("00000000432100000000000000010000000001000000000000000000000000FFFFFFFF010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000004");
                f.writeFloat(p.x);
                f.writeFloat(p.y);
                f.writeBytes(new byte[0x14]);
            }

            for (int i = 0; i < 4; i++)
            {
                f.writeByte(1);
                f.writeInt(0);
            }

            return(f.getBytes());
        }
Beispiel #28
0
        public override byte[] Rebuild()
        {
            FileOutput file = new FileOutput();

            if (file != null)
            {
                if (Endian == Endianness.Little)
                {
                    file.Endian = Endianness.Little;
                    file.writeString(" NBV");
                    file.writeShort(0x02);
                    file.writeShort(0x01);
                }
                else if (Endian == Endianness.Big)
                {
                    file.Endian = Endianness.Big;
                    file.writeString("VBN ");
                    file.writeShort(0x01);
                    file.writeShort(0x02);
                }


                file.writeInt(bones.Count);
                if (boneCountPerType[0] == 0)
                {
                    boneCountPerType[0] = (uint)bones.Count;
                }

                List <Bone> Normal = new List <Bone>();
                List <Bone> Unk    = new List <Bone>();
                List <Bone> Helper = new List <Bone>();
                List <Bone> Swing  = new List <Bone>();

                string[] SpecialBones = new string[] { "TransN",
                                                       "RotN",
                                                       "HipN",
                                                       "LLegJ",
                                                       "LKneeJ",
                                                       "LFootJ",
                                                       "LToeN",
                                                       "RLegJ",
                                                       "RKneeJ",
                                                       "RFootJ",
                                                       "RToeN",
                                                       "WaistN",
                                                       "BustN",
                                                       "LShoulderN",
                                                       "LShoulderJ",
                                                       "LArmJ",
                                                       "LHandN",
                                                       "RShoulderN",
                                                       "RShoulderJ",
                                                       "RArmJ",
                                                       "RHandN",
                                                       "NeckN",
                                                       "HeadN",
                                                       "RHaveN",
                                                       "LHaveN",
                                                       "ThrowN" };
                Bone[] Special      = new Bone[SpecialBones.Length];
                int    specialCount = 0;
                // OrderPass
                foreach (Bone b in bones)
                {
                    for (int i = 0; i < SpecialBones.Length; i++)
                    {
                        if (b.Text.Equals(SpecialBones[i]) || (SpecialBones[i].Equals("RotN") && b.Text.Equals("XRotN")))
                        {
                            specialCount++;
                            Special[i] = b;
                            break;
                        }
                    }
                }
                Console.WriteLine(SpecialBones.Length + " " + specialCount);
                if (specialCount == SpecialBones.Length)
                {
                    Normal.AddRange(Special);
                }

                //Gather Each Bone Type
                foreach (Bone b in bones)
                {
                    switch (b.boneType)
                    {
                    case 0: if (!Normal.Contains(b))
                        {
                            Normal.Add(b);
                        }
                        break;

                    case 2: Helper.Add(b); break;

                    case 3: Swing.Add(b); break;

                    default: Unk.Add(b); break;
                    }
                }

                file.writeInt(Normal.Count);
                file.writeInt(Unk.Count);
                file.writeInt(Helper.Count);
                file.writeInt(Swing.Count);

                List <Bone> NewBoneOrder = new List <Bone>();
                NewBoneOrder.AddRange(Normal);
                NewBoneOrder.AddRange(Unk);
                NewBoneOrder.AddRange(Helper);
                NewBoneOrder.AddRange(Swing);
                bones.Clear();
                bones = NewBoneOrder;

                for (int i = 0; i < bones.Count; i++)
                {
                    file.writeString(bones[i].Text);
                    for (int j = 0; j < 64 - bones[i].Text.Length; j++)
                    {
                        file.writeByte(0);
                    }
                    file.writeInt((int)bones[i].boneType);
                    if (bones[i].parentIndex == -1)
                    {
                        file.writeInt(0x0FFFFFFF);
                    }
                    else
                    {
                        file.writeInt(bones[i].parentIndex);
                    }
                    file.writeInt((int)bones[i].boneId);
                }

                for (int i = 0; i < bones.Count; i++)
                {
                    file.writeFloat(bones[i].position[0]);
                    file.writeFloat(bones[i].position[1]);
                    file.writeFloat(bones[i].position[2]);
                    file.writeFloat(bones[i].rotation[0]);
                    file.writeFloat(bones[i].rotation[1]);
                    file.writeFloat(bones[i].rotation[2]);
                    file.writeFloat(bones[i].scale[0]);
                    file.writeFloat(bones[i].scale[1]);
                    file.writeFloat(bones[i].scale[2]);
                }
            }
            return(file.getBytes());
        }
Beispiel #29
0
        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);
        }