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); }
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(); }
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()); }
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); } }
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); }
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); }
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); } } } } }
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); }
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()); }
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()); }
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); }
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()); }
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); }
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); }
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); }
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); }
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()); }
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()); }
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()); }
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); }
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); }
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()); }
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()); }
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()); } }
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()); }
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()); }
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()); }
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()); }
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); }