private static void WriteScores(ExtendedBinaryWriter writer, byte[] compressedBuffer, int length) { writer.Write(length); writer.Write(compressedBuffer, 0, length); }
public override void PrepareWrite(ExtendedBinaryWriter writer) { writer.WriteNulls(Length); writer.Offset = Length; writer.IsBigEndian = IsBigEndian; }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); var used = new Dictionary <long, long>(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { output.Write(input.ReadBytes(4)); var count = input.ReadInt32(); output.Write(count); output.Write(input.ReadBytes(8)); long outputOffset = input.PeekInt32(); for (var i = 0; i < count; i++) { var offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); var pointer = input.ReadInt32(); output.Write(pointer); var numLines = input.ReadInt32(); output.Write(numLines); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); output.Write(input.ReadBytes(4)); offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); var pos = input.Position; input.Seek(pointer, SeekOrigin.Begin); output.Seek(pointer, SeekOrigin.Begin); for (var j = 0; j < numLines; j++) { offset = input.ReadInt32(); outputOffset = WriteString(output, subtitles, used, offset, outputOffset); } input.Seek(pos, SeekOrigin.Begin); output.Seek(pos, SeekOrigin.Begin); output.Write(input.ReadBytes(36)); } } }
public void Write(object value, ExtendedBinaryWriter writer) { throw new NotImplementedException(); }
public override void Write(ExtendedBinaryWriter writer, object value) => writer.Write(Convert.ToByte(value));
public abstract void PrepareWrite(ExtendedBinaryWriter writer);
public override void Write(long value, ExtendedBinaryWriter writer) { writer.Write(value); }
public override void Write(ExtendedBinaryWriter writer, object value) { var enumIndex = value is string enumStr ? (short)Lookup(enumStr) : Convert.ToInt16(value); writer.Write(enumIndex); }
protected void Rebuild(ExtendedBinaryReader input, ExtendedBinaryWriter output, Dictionary <string, SubtitleWithId> dictionary) { string version = input.ReadStringSerialized(0x04); output.WriteStringSerialized(version, 0x04); string author = input.ReadStringSerialized(0x04); output.WriteStringSerialized(author, 0x04); string description = input.ReadStringSerialized(0x04); output.WriteStringSerialized(description, 0x04); string globalUserScript = input.ReadStringSerialized(0x04); output.WriteStringSerialized(globalUserScript, 0x04); int emphasisSettingCount = input.ReadInt32(); output.Write(emphasisSettingCount); output.Write(input.ReadBytes(emphasisSettingCount * 0x04 * 0x07)); int actorCount = input.ReadInt32(); output.Write(actorCount); for (int i = 0; i < actorCount; i++) { int id = input.ReadInt32(); output.Write(id); int fieldCount = input.ReadInt32(); output.Write(fieldCount); var fields = new Dictionary <string, Field>(fieldCount); for (int j = 0; j < fieldCount; j++) { var field = new Field(); field.Title = input.ReadStringSerialized(0x04); field.Value = input.ReadStringSerialized(0x04); field.Type = input.ReadInt32(); field.TypeString = input.ReadStringSerialized(0x04); fields.Add(field.Title, field); } var translatableFields = new string[] { "Name", "LongDescription", "short_description" }; foreach (KeyValuePair <string, Field> kvp in fields) { output.WriteStringSerialized(kvp.Value.Title, 0x04); if (translatableFields.Contains(kvp.Value.Title) && !string.IsNullOrEmpty(kvp.Value.Value)) { string key = $"Actor_{id}_{kvp.Value.Title}"; SubtitleWithId subtitle = dictionary[key]; output.WriteStringSerialized(subtitle.Translation, 0x04); } else { output.WriteStringSerialized(kvp.Value.Value, 0x04); } output.Write(kvp.Value.Type); output.WriteStringSerialized(kvp.Value.TypeString, 0x04); } output.Write(input.ReadBytes(0x0C)); // portrait output.Write(input.ReadBytes(0x0C)); // spritePortrait output.Write(input.ReadBytes(0x04)); // alternatePortraits output.Write(input.ReadBytes(0x04)); // spritePortraits } int itemCount = input.ReadInt32(); output.Write(itemCount); for (int i = 0; i < itemCount; i++) { int id = input.ReadInt32(); output.Write(id); int fieldCount = input.ReadInt32(); output.Write(fieldCount); var fields = new Dictionary <string, Field>(fieldCount); for (int j = 0; j < fieldCount; j++) { var field = new Field(); field.Title = input.ReadStringSerialized(0x04); field.Value = input.ReadStringSerialized(0x04); field.Type = input.ReadInt32(); field.TypeString = input.ReadStringSerialized(0x04); fields.Add(field.Title, field); } var translatableFields = new string[] { "Description", "displayname", "description", "fixtureBonus", "requirement", "bonus", "fixtureDescription" }; foreach (KeyValuePair <string, Field> kvp in fields) { output.WriteStringSerialized(kvp.Value.Title, 0x04); if (translatableFields.Contains(kvp.Value.Title) && !string.IsNullOrEmpty(kvp.Value.Value)) { string key = $"Item_{id}_{kvp.Value.Title}"; SubtitleWithId subtitle = dictionary[key]; output.WriteStringSerialized(subtitle.Translation, 0x04); } else { output.WriteStringSerialized(kvp.Value.Value, 0x04); } output.Write(kvp.Value.Type); output.WriteStringSerialized(kvp.Value.TypeString, 0x04); } } int locationCount = input.ReadInt32(); output.Write(locationCount); for (int i = 0; i < locationCount; i++) { int id = input.ReadInt32(); output.Write(id); int fieldCount = input.ReadInt32(); output.Write(fieldCount); var fields = new Dictionary <string, Field>(fieldCount); for (int j = 0; j < fieldCount; j++) { var field = new Field(); field.Title = input.ReadStringSerialized(0x04); field.Value = input.ReadStringSerialized(0x04); field.Type = input.ReadInt32(); field.TypeString = input.ReadStringSerialized(0x04); fields.Add(field.Title, field); } var translatableFields = new string[] { "Name" }; foreach (KeyValuePair <string, Field> kvp in fields) { output.WriteStringSerialized(kvp.Value.Title, 0x04); if (translatableFields.Contains(kvp.Value.Title) && !string.IsNullOrEmpty(kvp.Value.Value)) { string key = $"Location_{id}_{kvp.Value.Title}"; SubtitleWithId subtitle = dictionary[key]; output.WriteStringSerialized(subtitle.Translation, 0x04); } else { output.WriteStringSerialized(kvp.Value.Value, 0x04); } output.Write(kvp.Value.Type); output.WriteStringSerialized(kvp.Value.TypeString, 0x04); } } int variableCount = input.ReadInt32(); output.Write(variableCount); for (int i = 0; i < variableCount; i++) { int id = input.ReadInt32(); output.Write(id); int fieldCount = input.ReadInt32(); output.Write(fieldCount); var fields = new Dictionary <string, Field>(fieldCount); for (int j = 0; j < fieldCount; j++) { var field = new Field(); field.Title = input.ReadStringSerialized(0x04); field.Value = input.ReadStringSerialized(0x04); field.Type = input.ReadInt32(); field.TypeString = input.ReadStringSerialized(0x04); fields.Add(field.Title, field); } var translatableFields = new string[] { "Description" }; foreach (KeyValuePair <string, Field> kvp in fields) { output.WriteStringSerialized(kvp.Value.Title, 0x04); if (translatableFields.Contains(kvp.Value.Title) && !string.IsNullOrEmpty(kvp.Value.Value)) { string key = $"Variable_{id}_{kvp.Value.Title}"; SubtitleWithId subtitle = dictionary[key]; output.WriteStringSerialized(subtitle.Translation, 0x04); } else { output.WriteStringSerialized(kvp.Value.Value, 0x04); } output.Write(kvp.Value.Type); output.WriteStringSerialized(kvp.Value.TypeString, 0x04); } } int conversationCount = input.ReadInt32(); output.Write(conversationCount); for (int i = 0; i < conversationCount; i++) { int id = input.ReadInt32(); output.Write(id); int fieldCount = input.ReadInt32(); output.Write(fieldCount); var fields = new Dictionary <string, Field>(fieldCount); for (int j = 0; j < fieldCount; j++) { var field = new Field(); field.Title = input.ReadStringSerialized(0x04); field.Value = input.ReadStringSerialized(0x04); field.Type = input.ReadInt32(); field.TypeString = input.ReadStringSerialized(0x04); fields.Add(field.Title, field); } var translatableFields = new string[] { "Title", "Description", "subtask_title_01", "subtask_title_02", "subtask_title_03", "subtask_title_04", "subtask_title_05", "subtask_title_06", "subtask_title_07", "subtask_title_08", "subtask_title_09", "subtask_title_10", }; foreach (KeyValuePair <string, Field> kvp in fields) { output.WriteStringSerialized(kvp.Value.Title, 0x04); if (translatableFields.Contains(kvp.Value.Title) && !string.IsNullOrEmpty(kvp.Value.Value)) { string key = $"Conversation_{id}_{kvp.Value.Title}"; SubtitleWithId subtitle = dictionary[key]; output.WriteStringSerialized(subtitle.Translation, 0x04); } else { output.WriteStringSerialized(kvp.Value.Value, 0x04); } output.Write(kvp.Value.Type); output.WriteStringSerialized(kvp.Value.TypeString, 0x04); } // ConversationOverrideDisplaySettings output.Write(input.ReadBytes(0x28)); for (int j = 0; j < 3; j++) { output.WriteStringSerialized(input.ReadStringSerialized(0x04), 0x04); } output.Write(input.ReadBytes(0x10)); output.WriteStringSerialized(input.ReadStringSerialized(0x04), 0x04); // nodeColor // DialogueEntry int dialogueEntryCount = input.ReadInt32(); output.Write(dialogueEntryCount); for (int j = 0; j < dialogueEntryCount; j++) { int dialogueEntryId = input.ReadInt32(); output.Write(dialogueEntryId); int fieldCount2 = input.ReadInt32(); output.Write(fieldCount2); var fields2 = new Dictionary <string, Field>(fieldCount2); for (int k = 0; k < fieldCount2; k++) { var field = new Field(); field.Title = input.ReadStringSerialized(0x04); field.Value = input.ReadStringSerialized(0x04); field.Type = input.ReadInt32(); field.TypeString = input.ReadStringSerialized(0x04); fields2.Add($"{field.Title}", field); } var translatableFields2 = new string[] { "Dialogue Text", "Alternate1", "Alternate2", "Alternate3", "Alternate4", "tooltip1", "tooltip2", "tooltip3", "tooltip4", "tooltip5", "tooltip6", "tooltip7", "tooltip8", "tooltip9", "tooltip10" }; foreach (KeyValuePair <string, Field> kvp in fields2) { output.WriteStringSerialized(kvp.Value.Title, 0x04); if (translatableFields2.Contains(kvp.Value.Title) && !string.IsNullOrEmpty(kvp.Value.Value)) { string key = $"Conversation_{id}_Entry_{dialogueEntryId}_{kvp.Value.Title}"; SubtitleWithId subtitle = dictionary[key]; output.WriteStringSerialized(subtitle.Translation, 0x04); } else { output.WriteStringSerialized(kvp.Value.Value, 0x04); } output.Write(kvp.Value.Type); output.WriteStringSerialized(kvp.Value.TypeString, 0x04); } output.Write(input.ReadBytes(0x0C)); output.WriteStringSerialized(input.ReadStringSerialized(0x04), 0x04); // nodeColor output.Write(input.ReadBytes(0x04)); output.WriteStringSerialized(input.ReadStringSerialized(0x04), 0x04); // falseConditionAction output.Write(input.ReadBytes(0x04)); int outgoingLinksCount = input.ReadInt32(); output.Write(outgoingLinksCount); output.Write(input.ReadBytes(outgoingLinksCount * 0x04 * 0x06)); output.WriteStringSerialized(input.ReadStringSerialized(0x04), 0x04); // conditionsString string userScript = input.ReadStringSerialized(0x04); // userScript if (userScript.StartsWith("NewspaperEndgame(")) { var regex = new Regex(@"NewspaperEndgame\(""(?<Id>[^""]+)"",""(?<Headline>[^""]+)"",""(?<Text>[^""\\]*(?:\\.[^""\\]*)*)""\)"); Match match = regex.Match(userScript); while (match.Success) { string endId = match.Groups["Id"].Value; string headlineKey = $"Conversation_{id}_Entry_{dialogueEntryId}_EndHeadline"; string textKey = $"Conversation_{id}_Entry_{dialogueEntryId}_EndText"; if (!dictionary.ContainsKey(headlineKey) || !dictionary.ContainsKey(textKey)) { output.WriteStringSerialized(userScript, 0x04); } else { SubtitleWithId headline = dictionary[headlineKey]; SubtitleWithId text = dictionary[textKey]; string escapedText = text.Translation.Replace("\"", "\\\"").Replace("\\n", "<NewLine>"); output.WriteStringSerialized($@"NewspaperEndgame(""{endId}"",""{headline}"",""{escapedText}"")", 0x04); } match = match.NextMatch(); } } else { output.WriteStringSerialized(userScript, 0x04); } // onExecute output.Write(input.ReadBytes(0x04)); output.Write(input.ReadBytes(0x10)); // Canvas rect } output.Write(input.ReadBytes(0x08)); // canvasScrollPosition output.Write(input.ReadBytes(0x04)); // canvasZoom } int remainderLength = (int)(input.Length - input.Position); byte[] remainder = input.ReadBytes(remainderLength); output.Write(remainder); }
internal void Write(ExtendedBinaryWriter writer) { writer.Write(_info); writer.Write(_contents); }
public override void Write(ExtendedBinaryWriter writer, object value) => throw new NotImplementedException();
public override void Write(Vector2 value, ExtendedBinaryWriter writer) { writer.Write(value.X); writer.Write(value.Y); }
/// <inheritdoc cref="Write(object,MonoSync.Utils.ExtendedBinaryWriter)" /> public abstract void Write(T value, ExtendedBinaryWriter writer);
public virtual void Write(object value, ExtendedBinaryWriter writer) { Write((T)value, writer); }
public override void Save(Stream fileStream) { if (Objects.Count > HeroesObjectLimit) { throw new Exception("Heroes set data is limited to 2048 objects!"); } // Object Entries var writer = new ExtendedBinaryWriter(fileStream, Encoding.ASCII, true); byte objList, objType; // Defined here so we can re-use them. for (ushort i = 0; i < HeroesObjectLimit; ++i) { // If we have less than 2048 objects, write the other null entries. // (Yes the Heroes set data format requires us to do this... awful design, huh?) if (i >= Objects.Count) { writer.WriteNulls((uint) (HeroesObjectLimit - Objects.Count) * MainEntryLength); break; } // Check if object type is valid var obj = Objects[i]; string type1 = obj.ObjectType.Substring(0, 2), type2 = obj.ObjectType.Substring(3, 2); if (obj.ObjectType.Length != 5 || !byte.TryParse(type1, NumberStyles.HexNumber, null, out objList) || !byte.TryParse(type2, NumberStyles.HexNumber, null, out objType)) { Console.WriteLine("WARNING: Object #{0} {1} ({2})!", i, "was skipped, invalid Heroes obj type", obj.ObjectType); writer.WriteNulls(MainEntryLength); continue; } // Write object entries var rot = obj.Transform.Rotation.ToEulerAngles(false); writer.Write(obj.Transform.Position); writer.Write((int)(rot.X * 32768.0 / 180.0)); writer.Write((int)(rot.Y * 32768.0 / 180.0)); writer.Write((int)(rot.Z * 32768.0 / 180.0)); // Yeah in the actual game the same thing is just written twice for some reason byte stageType = obj.GetCustomDataValue <byte>("StageType"); writer.Write((ushort)2); writer.Write(stageType); writer.Write((byte)9); // unknown 2 writer.Write(0u); // unknown 3 writer.Write((ushort)2); writer.Write(stageType); writer.Write((byte)9); // unknown 2 writer.Write(0u); // unknown 3 writer.Write(objList); writer.Write(objType); writer.Write(obj.GetCustomDataValue <byte>("LinkID")); writer.Write((obj.CustomData.ContainsKey("RenderDistance")) ? (byte)obj.CustomData["RenderDistance"].Data : (byte)20); writer.Write((ushort)0); // unknown 5 writer.Write((ushort)(i + 1)); } // Object Parameters writer.WriteNulls(MiscEntryLength); // The first entry has to be null because screw me for (ushort i = 0; i < Objects.Count; ++i) { var obj = Objects[i]; long pos = writer.BaseStream.Position; writer.Write((ushort)0x0100); writer.Write((ushort)(i + 1)); foreach (var param in obj.Parameters) { writer.WriteByType(param.DataType, param.Data); } // Pad-out the entry to make sure it's 0x24 bytes writer.WriteNulls(MiscEntryLength - (uint)(writer.BaseStream.Position - pos)); } }
public override void Serialize(ushort value, ExtendedBinaryWriter writer) { writer.Write(value); }
public override void Serialize(decimal value, ExtendedBinaryWriter writer) { writer.Write(value); }
public static void SaveLight(string filePath) { // Get file path without the .xml at the end var fileInfo = new FileInfo(filePath); string shortName = filePath.Substring(0, filePath.Length - fileInfo.Extension.Length); var xml = XDocument.Load(filePath); var root = xml.Root; var lightTypeElem = root.Element("LightType"); var lightPosElem = root.Element("Position"); var lightColorElem = root.Element("Color"); using (var fileStream = File.Create($"{shortName}")) { var writer = new ExtendedBinaryWriter(fileStream, true); // Write Header writer.Write(0); writer.Write(1); writer.Write(0); writer.Write(24); writer.Write(0); writer.Write(0); // Light Type bool isOmniLight = (lightTypeElem != null && lightTypeElem.Value == "1"); writer.Write((isOmniLight) ? 1 : 0); // Position WriteXMLFloat(writer, lightPosElem?.Element("X")); WriteXMLFloat(writer, lightPosElem?.Element("Y")); WriteXMLFloat(writer, lightPosElem?.Element("Z")); // Color WriteXMLFloat(writer, lightColorElem?.Element("R")); WriteXMLFloat(writer, lightColorElem?.Element("G")); WriteXMLFloat(writer, lightColorElem?.Element("B")); // Omni-Specific Stuff if (isOmniLight) { writer.Write(0); writer.Write(0); writer.Write(0); var omniElem = root.Element("OmniLightRange"); WriteXMLFloat(writer, omniElem?.Element("OmniLightInnerRange")); WriteXMLFloat(writer, omniElem?.Element("OmniLightOuterRange")); } // Fill-In Header writer.Write(0); fileStream.Position = 0; writer.Write((uint)fileStream.Length); fileStream.Position = 8; uint finalTablePosition = (uint)fileStream.Length - 4; writer.Write(finalTablePosition - 0x18); fileStream.Position = 16; writer.Write(finalTablePosition); } }
public abstract void FinishWrite(ExtendedBinaryWriter writer);
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding)) { output.Write(input.ReadBytes(0x20)); // Escribo la cabecera, aunque al final tendré que editarla output.Write(input.ReadInt32()); var stringCount1 = input.ReadInt32(); output.Write(stringCount1); var aux = input.ReadInt32(); output.Write(aux); var stringCount2 = input.ReadInt32(); output.Write(stringCount2); output.Write(input.ReadInt32()); if (aux == 3) { output.Write(input.ReadInt32()); } var language = input.ReadInt32(); output.Write(language); var base1 = input.Position; var base2 = base1 + 4 * stringCount1; var stringsBase = base2 + aux * 4 * stringCount1; var outputOffset = 0; for (var i = 0; i < stringCount1; i++) { input.Seek(base1 + 4 * i, SeekOrigin.Begin); output.Seek(base1 + 4 * i, SeekOrigin.Begin); var index1 = input.ReadInt32(); output.Write(index1); input.Seek(base2 + 4 * index1, SeekOrigin.Begin); output.Seek(base2 + 4 * index1, SeekOrigin.Begin); output.Write(input.ReadInt32()); if (aux == 3) { output.Write(input.ReadInt32()); } var strOffset = input.ReadInt32(); output.Write(outputOffset); input.Seek(stringsBase + strOffset, SeekOrigin.Begin); output.Seek(stringsBase + outputOffset, SeekOrigin.Begin); var originalSize = input.ReadInt32(); var subtitle = ReadSubtitle(input); var outputSubtitle = subtitles.FirstOrDefault(x => x.Offset == subtitle.Offset); if (outputSubtitle != null) { var translationSize = FileEncoding.GetByteCount(outputSubtitle.Translation); output.Write((int)translationSize); WriteSubtitle(output, outputSubtitle, output.Position, false); } else { output.Write(originalSize); WriteSubtitle(output, subtitle, output.Position, false); } output.WritePadding(0x04); outputOffset = (int)(output.Position - stringsBase); } output.WritePadding(0x10); var size = output.Position - 0x20; input.Seek(-0x80, SeekOrigin.End); output.Write(input.ReadBytes(0x80)); output.Seek(0x04, SeekOrigin.Begin); output.Write((int)(size + 0x60)); output.Skip(12); output.Write((int)size); } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { output.Write(input.ReadBytes(6)); var groupCount = input.ReadInt16(); output.Write(groupCount); output.Write(input.ReadBytes(8)); long outputOffset = input.PeekInt32(); var firstStringOffset = outputOffset; for (var i = 0; i < 43; i++) { var offset = input.ReadInt32(); outputOffset = WriteSubtitle(output, subtitles, offset, outputOffset); } output.Write(input.ReadBytes(0x108 - (int)input.Position)); // barkeeper var barKeeperOffset = input.ReadInt32(); outputOffset = WriteSubtitle(output, subtitles, barKeeperOffset, outputOffset); output.Write(input.ReadBytes(0x110 - (int)input.Position)); for (var i = 0; i < groupCount; i++) { var offsets = new int[22]; for (var j = 0; j < 22; j++) { offsets[j] = input.ReadInt32(); } for (var j = 0; j < 8; j++) { output.Write(offsets[j]); } outputOffset = WriteSubtitle(output, subtitles, offsets[8], outputOffset); for (var j = 9; j < 14; j++) { output.Write(offsets[j]); } for (var j = 14; j < 22; j++) { outputOffset = WriteSubtitle(output, subtitles, offsets[j], outputOffset); } } output.Write(input.ReadBytes((int)(firstStringOffset - input.Position))); } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { input.Skip(0x38); var stringsOffset = input.ReadInt32(); input.Seek(0, SeekOrigin.Begin); output.Write(input.ReadBytes(stringsOffset)); Subtitle subtitle; var dict = new Dictionary <long, long>(subtitles.Count); while (input.Position < input.Length) { subtitle = ReadSubtitle(input); var newSubtitle = subtitles.FirstOrDefault(x => x.Offset == subtitle.Offset); if (newSubtitle != null) { dict.Add(subtitle.Offset, output.Position); output.WriteString(newSubtitle.Translation); } } input.Seek(0x10, SeekOrigin.Begin); var count1 = input.ReadInt32(); var offset1 = input.ReadInt32(); input.Skip(8); var count2 = input.ReadInt32(); var offset2 = input.ReadInt32(); input.Seek(offset1, SeekOrigin.Begin); output.Seek(offset1, SeekOrigin.Begin); for (var i = 0; i < count1; i++) { input.Skip(4); output.Skip(4); var stringOffset = input.ReadInt32(); output.Write((int)dict[stringOffset]); input.Skip(16); output.Skip(16); } input.Seek(offset2, SeekOrigin.Begin); output.Seek(offset2, SeekOrigin.Begin); for (var i = 0; i < count2; i++) { var stringOffset = input.ReadInt32(); if (dict.ContainsKey(stringOffset)) { output.Write((int)dict[stringOffset]); } else { output.Skip(4); } } } }
public void Serialize(object value, ExtendedBinaryWriter writer) { int referenceIdentifier = _referenceResolver.ResolveIdentifier(value); writer.Write7BitEncodedInt(referenceIdentifier); }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) using (var tempMemoryStream = new MemoryStream()) using (var tempOutput = new ExtendedBinaryWriter(tempMemoryStream, FileEncoding, Endianness.BigEndian)) { var offsets = new List <long>(); var count1 = input.ReadInt32(); output.Write(count1); output.Write(input.ReadBytes(4)); long outputOffset = 0; for (var i = 0; i < count1; i++) { var count2 = input.ReadInt32(); output.Write(count2); var offset1 = input.ReadInt32(); output.Write(offset1); var returnPos = input.Position; input.Seek(offset1, SeekOrigin.Begin); for (var j = 0; j < count2; j++) { long offset2 = input.ReadInt32(); if (offset2 == 0) { offsets.Add(-1); } else { offsets.Add(outputOffset); outputOffset = WriteSubtitle(tempOutput, subtitles, offset2); } } input.Seek(returnPos, SeekOrigin.Begin); } outputOffset = (int)(output.Position + 4 * offsets.Count); foreach (var offset in offsets) { if (offset == -1) { output.Write(0); } else { output.Write((int)(outputOffset + offset)); } } var data = tempMemoryStream.ToArray(); output.Write(data); } }
public override void Save(Stream fileStream) { // Header var writer = new ExtendedBinaryWriter(fileStream); writer.Write(Signature | (Version << 24)); writer.Write(Meshes.Count); // Meshes uint tri; uint len, i; byte indicesType; foreach (var mesh in Meshes) { // Vertex Data len = (uint)mesh.VertexData.Length; writer.Write(len); for (i = 0; i < len; ++i) { writer.Write(mesh.VertexData[i]); } // Triangle Indices indicesType = 2; // 8-bit len = (uint)mesh.Triangles.Length; for (i = 0; i < len; ++i) { tri = mesh.Triangles[i]; if (tri > ushort.MaxValue) { indicesType = 0; // 32-bit break; } else if (tri > byte.MaxValue) { indicesType = 1; // 16-bit } } writer.Write(len | ((uint)indicesType << 30)); for (i = 0; i < len; ++i) { // 0 = 32-bit, 1 = 16-bit, 2 = 8-bit switch (indicesType) { case 0: default: writer.Write(mesh.Triangles[i]); continue; case 1: writer.Write((ushort)mesh.Triangles[i]); continue; case 2: writer.Write((byte)mesh.Triangles[i]); continue; } } // Material Name if (string.IsNullOrEmpty(mesh.MaterialName)) { writer.Write((byte)0); } else { writer.Write(mesh.MaterialName); } } }
public override void Save(ExtendedBinaryWriter writer) { // Loads all files into memory if not already // This is needed to ensure the reading stream is closed Preload(); // ZLIB Compression Stream mainStream = null; if (Compress) { mainStream = writer.StartDeflateEncapsulation(); } // Filename Section // Address of the Filename section long sectionPosition = writer.BaseStream.Position; writer.WriteDALSignature("Filename", UseSmallSig); writer.AddOffset("SectionSize"); // Allocates space for all the file name pointers foreach (var entry in FileEntries) { writer.AddOffset(entry.FileName); } // Fills in all the file names foreach (var entry in FileEntries) { // Fill in the address and write the file name (including paths) writer.FillInOffset(entry.FileName, (uint)(writer.BaseStream.Position - (UseSmallSig ? 0xC : 0x18))); writer.WriteNullTerminatedString(entry.FileName); } // Fills in the size of the Filename section writer.FillInOffset("SectionSize"); // Realigns the writer writer.FixPadding(UseSmallSig ? 0x04u : 0x08u); // Pack Section // Address to the Pack section sectionPosition = writer.BaseStream.Position; writer.WriteDALSignature("Pack", UseSmallSig); writer.AddOffset("SectionSize"); writer.Write(FileEntries.Count); // Writes file data entries for (int i = 0; i < FileEntries.Count; ++i) { // Allocates 4 bytes for the absolute address of the contents of the file writer.AddOffset($"DataPtr{i}"); // Writes the length of the file writer.Write(FileEntries[i].Data.Length); } // Fills in the size of the Pack section writer.FillInOffset("SectionSize", (uint)(writer.BaseStream.Position - (UseSmallSig ? 0xC : 0x18))); // Realigns the writer writer.FixPadding(UseSmallSig ? 0x04u : 0x08u); // Data for (int i = 0; i < FileEntries.Count; ++i) { writer.FillInOffset($"DataPtr{i}"); writer.Write(FileEntries[i].Data); // Realigns the writer writer.FixPadding(UseSmallSig ? 0x04u : 0x08u); } // Finalise ZLIB Compression if (Compress) { writer.EndDeflateEncapsulation(mainStream); } }
public override void Rebuild(string outputFolder) { var outputPath = System.IO.Path.Combine(outputFolder, RelativePath); Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); var subtitles = GetSubtitles(); using (var fsInput = new FileStream(Path, FileMode.Open)) using (var input = new ExtendedBinaryReader(fsInput, FileEncoding, Endianness.BigEndian)) using (var fsOutput = new FileStream(outputPath, FileMode.Create)) using (var output = new ExtendedBinaryWriter(fsOutput, FileEncoding, Endianness.BigEndian)) { output.Write(input.ReadBytes(3)); var count = input.ReadByte(); output.Write(count); output.Write(input.ReadBytes(4)); var inputPointer1 = input.ReadInt32(); var inputCountPointer1 = input.ReadInt16(); var dataPointer1 = new byte[inputCountPointer1 * 16]; if (inputCountPointer1 > 0) { input.Seek(inputPointer1, SeekOrigin.Begin); dataPointer1 = input.ReadBytes(inputCountPointer1 * 16); input.Seek(14, SeekOrigin.Begin); } output.Write(0); // Si no es 0, ya lo rellenaré luego output.Write(inputCountPointer1); var numTalkers = input.ReadInt16(); output.Write(numTalkers); var inputPointerTalkers = input.ReadInt32(); output.Write(0); // Si no es 0, ya lo rellenaré luego var inputPointerRemainder = input.ReadInt32(); output.Write(0); // Si no es 0, ya lo rellenaré luego using (var unknownMemoryStream = new MemoryStream()) using (var outputUnknown = new ExtendedBinaryWriter(unknownMemoryStream, FileEncoding, Endianness.BigEndian)) using (var propertiesMemoryStream = new MemoryStream()) using (var outputProperties = new ExtendedBinaryWriter(propertiesMemoryStream, FileEncoding, Endianness.BigEndian)) using (var stringsMemoryStream = new MemoryStream()) using (var outputStrings = new ExtendedBinaryWriter(stringsMemoryStream, FileEncoding, Endianness.BigEndian)) { var stringLengths = new List <short>(); var stringOffsets = new List <int>(); var propertiesCount = new List <byte>(); var propertiesOffsets = new List <int>(); var unknownOffsets = new List <int>(); var unknownSectionOffset = 0; var strOffset = 0; var propOffset = 0; var totalStrCount = 0; for (var i = 0; i < count; i++) { input.Seek(0x18 + i * 0x10, SeekOrigin.Begin); var unknownOffset = input.ReadInt32(); output.Write(0); // Si no es 0, ya lo rellenaré luego var groupOffset = input.ReadInt32(); output.Write(groupOffset); var unknownCount = input.ReadByte(); output.Write(unknownCount); var stringCount = input.ReadByte(); output.Write(stringCount); totalStrCount += stringCount; output.Write(input.ReadBytes(6)); if (unknownOffset != 0) { var returnPos = input.Position; input.Seek(unknownOffset, SeekOrigin.Begin); outputUnknown.Write(input.ReadBytes(unknownCount * 12)); unknownOffsets.Add(unknownSectionOffset); unknownSectionOffset = (int)outputUnknown.Position; input.Seek(returnPos, SeekOrigin.Begin); } else { unknownOffsets.Add(-1); } input.Seek(groupOffset, SeekOrigin.Begin); for (var j = 0; j < stringCount; j++) { var inputStringLength = input.ReadInt16(); var inputPropertiesCount = input.ReadByte(); var zero = input.ReadByte(); var inputStringOffset = input.ReadInt32(); var inputPropertiesOffset = input.ReadInt32(); if (inputStringLength == 0) { stringLengths.Add(0); propertiesCount.Add(inputPropertiesCount); stringOffsets.Add(strOffset); propertiesOffsets.Add(propOffset); outputStrings.WriteString(string.Empty); strOffset = (int)outputStrings.Position; var ret = input.Position; input.Seek(inputPropertiesOffset, SeekOrigin.Begin); var prop = input.ReadBytes(inputPropertiesCount * 16); input.Seek(ret, SeekOrigin.Begin); outputProperties.Write(prop); propOffset = (int)outputProperties.Position; } else { var sub = (Subtitle)subtitles.First(x => x.Offset == inputStringOffset); stringLengths.Add((short)FileEncoding.GetByteCount(sub.Translation)); propertiesCount.Add((byte)sub.TranslationProperties.Count); stringOffsets.Add(strOffset); propertiesOffsets.Add(propOffset); outputStrings.WriteString(sub.Translation); strOffset = (int)outputStrings.Position; outputProperties.Write(sub.TranslationProperties.ToByteArray()); propOffset = (int)outputProperties.Position; } } } var unknownBytes = unknownMemoryStream.ToArray(); var propertiesBytes = propertiesMemoryStream.ToArray(); var stringsBytes = stringsMemoryStream.ToArray(); var propBase = (int)output.Position + totalStrCount * 12; var unknownBase = propBase + propertiesBytes.Length; var strBase = unknownBase + unknownBytes.Length; var outputReturnPos = output.Position; for (var i = 0; i < count; i++) { output.Seek(0x18 + i * 0x10, SeekOrigin.Begin); if (unknownOffsets[i] >= 0) { output.Write(unknownOffsets[i] + unknownBase); } } output.Seek(outputReturnPos, SeekOrigin.Begin); for (var i = 0; i < totalStrCount; i++) { output.Write(stringLengths[i]); output.Write(propertiesCount[i]); output.Write((byte)0); output.Write(stringOffsets[i] + strBase); output.Write(propertiesOffsets[i] + propBase); } output.Write(propertiesBytes); if (unknownBytes.Length > 0) { output.Write(unknownBytes); } output.Write(stringsBytes); output.WritePadding(4); } if (inputPointer1 > 0) { var outputPointer1 = (int)output.Position; output.Seek(8, SeekOrigin.Begin); output.Write(outputPointer1); output.Seek(outputPointer1, SeekOrigin.Begin); output.Write(dataPointer1); } if (inputPointerTalkers > 0) { var outputPointerTalkers = (int)output.Position; output.Seek(16, SeekOrigin.Begin); output.Write(outputPointerTalkers); output.Seek(outputPointerTalkers, SeekOrigin.Begin); input.Seek(inputPointerTalkers, SeekOrigin.Begin); using (var stringsMemoryStream = new MemoryStream()) using (var outputStrings = new ExtendedBinaryWriter(stringsMemoryStream, FileEncoding, Endianness.BigEndian)) { var baseOffset = (int)output.Position + numTalkers * 4; var strOffset = baseOffset; for (var i = 0; i < numTalkers; i++) { var offset = input.ReadInt32(); var sub = subtitles.FirstOrDefault(x => x.Offset == offset); output.Write(strOffset); if (sub != null) { outputStrings.WriteString(sub.Translation); } else { outputStrings.WriteString(string.Empty); } strOffset = baseOffset + (int)outputStrings.Position; } output.Write(stringsMemoryStream.ToArray()); } } if (inputPointerRemainder > 0) { var outputPointerRemainder = (int)output.Position; output.Seek(20, SeekOrigin.Begin); output.Write(outputPointerRemainder); output.Seek(outputPointerRemainder, SeekOrigin.Begin); input.Seek(inputPointerRemainder, SeekOrigin.Begin); var data = input.ReadBytes((int)(input.Length - inputPointerRemainder)); output.Write(data); } } }
public void Transcript_EndToEnd() { IChromosome expectedChromosome = new Chromosome("chrBob", "Bob", 1); const int expectedStart = int.MaxValue; const int expectedEnd = int.MinValue; const string expectedId = "ENST00000540021"; const byte expectedVersion = 7; const BioType expectedBioType = BioType.IG_J_pseudogene; const bool expectedCanonical = true; const Source expectedSource = Source.BothRefSeqAndEnsembl; const bool expectedCdsStartNotFound = true; const bool expectedCdsEndNotFound = true; var expectedIdAndVersion = expectedId + "." + expectedVersion; ICodingRegion expectedCodingRegion = new CodingRegion(10001, 10200, 1, 200, 200); ITranscriptRegion[] expectedTranscriptRegions = GetTranscriptRegions(); const byte expectedNumExons = 3; const int expectedTotalExonLength = 300; const byte expectedStartExonPhase = 3; const int expectedSiftIndex = 11; const int expectedPolyPhenIndex = 13; IInterval[] expectedMicroRnas = GetMicroRnas(); ITranslation expectedTranslation = new Translation(expectedCodingRegion, CompactId.Convert("ENSP00000446475", 17), "VEIDSD"); IGene expectedGene = new Gene(expectedChromosome, 100, 200, true, "TP53", 300, CompactId.Convert("7157"), CompactId.Convert("ENSG00000141510")); var genes = new IGene[1]; genes[0] = expectedGene; var peptideSeqs = new string[1]; peptideSeqs[0] = expectedTranslation.PeptideSeq; var geneIndices = CreateIndices(genes); var transcriptRegionIndices = CreateIndices(expectedTranscriptRegions); var microRnaIndices = CreateIndices(expectedMicroRnas); var peptideIndices = CreateIndices(peptideSeqs); var indexToChromosome = new Dictionary <ushort, IChromosome> { [expectedChromosome.Index] = expectedChromosome }; // ReSharper disable ConditionIsAlwaysTrueOrFalse var transcript = new Transcript(expectedChromosome, expectedStart, expectedEnd, CompactId.Convert(expectedId, expectedVersion), expectedTranslation, expectedBioType, expectedGene, expectedTotalExonLength, expectedStartExonPhase, expectedCanonical, expectedTranscriptRegions, expectedNumExons, expectedMicroRnas, expectedSiftIndex, expectedPolyPhenIndex, expectedSource, expectedCdsStartNotFound, expectedCdsEndNotFound, null, null); // ReSharper restore ConditionIsAlwaysTrueOrFalse ITranscript observedTranscript; using (var ms = new MemoryStream()) { using (var writer = new ExtendedBinaryWriter(ms, Encoding.UTF8, true)) { transcript.Write(writer, geneIndices, transcriptRegionIndices, microRnaIndices, peptideIndices); } ms.Position = 0; using (var reader = new BufferedBinaryReader(ms)) { observedTranscript = Transcript.Read(reader, indexToChromosome, genes, expectedTranscriptRegions, expectedMicroRnas, peptideSeqs); } } Assert.NotNull(observedTranscript); Assert.Equal(expectedStart, observedTranscript.Start); Assert.Equal(expectedEnd, observedTranscript.End); Assert.Equal(expectedIdAndVersion, observedTranscript.Id.WithVersion); Assert.Equal(expectedBioType, observedTranscript.BioType); Assert.Equal(expectedCanonical, observedTranscript.IsCanonical); Assert.Equal(expectedSource, observedTranscript.Source); Assert.Equal(expectedTotalExonLength, observedTranscript.TotalExonLength); Assert.Equal(expectedStartExonPhase, observedTranscript.StartExonPhase); Assert.Equal(expectedSiftIndex, observedTranscript.SiftIndex); Assert.Equal(expectedPolyPhenIndex, observedTranscript.PolyPhenIndex); Assert.Equal(expectedChromosome.Index, observedTranscript.Chromosome.Index); Assert.Equal(expectedGene.Symbol, observedTranscript.Gene.Symbol); Assert.Equal(expectedTranslation.PeptideSeq, observedTranscript.Translation.PeptideSeq); Assert.Equal(expectedTranscriptRegions.Length, observedTranscript.TranscriptRegions.Length); Assert.Equal(expectedMicroRnas.Length, observedTranscript.MicroRnas.Length); }
public virtual void FinishWrite(ExtendedBinaryWriter writer) { throw new NotImplementedException(); }
/* Functions and utilities */ #region Writing /// <summary> /// Saves the SEModel to a stream, following the current specification version, using the provided data /// </summary> /// <param name="Stream">The file stream to write to</param> public void Write(Stream Stream) { // Open up a binary writer using (ExtendedBinaryWriter writeFile = new ExtendedBinaryWriter(Stream)) { // Write magic writeFile.Write(new char[] { 'S', 'E', 'M', 'o', 'd', 'e', 'l' }); // Write version writeFile.Write((short)0x1); // Write header size writeFile.Write((short)0x14); // Build data present flags { // Buffer byte DataPresentFlags = 0x0; // Check for bones if (Bones.Count > 0) { DataPresentFlags |= (byte)SEModel_DataPresenceFlags.SEMODEL_PRESENCE_BONE; } // Check for meshes if (Meshes.Count > 0) { DataPresentFlags |= (byte)SEModel_DataPresenceFlags.SEMODEL_PRESENCE_MESH; } // Check for materials if (Materials.Count > 0) { DataPresentFlags |= (byte)SEModel_DataPresenceFlags.SEMODEL_PRESENCE_MATERIALS; } // Write it writeFile.Write((byte)DataPresentFlags); } // Dynamic properties bool HasScales = false, HasLocals = true, HasGlobals = false; // Build bone data present flags { // Buffer byte DataPresentFlags = 0x0; // Check for non-default bone data foreach (var Bone in Bones) { if (Bone.Scale != Vector3.One) { HasScales = true; } if (Bone.LocalPosition != Vector3.Zero || Bone.LocalRotation != Quaternion.Identity) { HasLocals = true; } if (Bone.GlobalPosition != Vector3.Zero || Bone.GlobalRotation != Quaternion.Identity) { HasGlobals = true; } // Check to end if (HasScales && HasLocals && HasGlobals) { break; } } // Check for bone types if (HasScales) { DataPresentFlags |= (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_SCALES; } if (HasLocals) { DataPresentFlags |= (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_LOCAL_MATRIX; } if (HasGlobals) { DataPresentFlags |= (byte)SEModel_BoneDataPresenceFlags.SEMODEL_PRESENCE_GLOBAL_MATRIX; } // Write it writeFile.Write((byte)DataPresentFlags); } // Dynamic properties bool HasNormals = false, HasColors = false; // Build mesh data present flags { // Buffer byte DataPresentFlags = 0x0; // Implied properties bool HasUVSet = false, HasWeights = false; // Check for non-default properties foreach (var Mesh in Meshes) { foreach (var Vertex in Mesh.Verticies) { if (Vertex.UVSets.Count > 0) { HasUVSet = true; } if (Vertex.Weights.Count > 0) { HasWeights = true; } if (Vertex.VertexColor != Color.White) { HasColors = true; } if (Vertex.VertexNormal != Vector3.Zero) { HasNormals = true; } // Check to end if (HasUVSet && HasWeights && HasNormals && HasColors) { break; } } // Check to end if (HasUVSet && HasWeights && HasNormals && HasColors) { break; } } // Check for UVSets if (HasUVSet) { DataPresentFlags |= (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_UVSET; } // Check for normals if (HasNormals) { DataPresentFlags |= (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_NORMALS; } // Check for colors if (HasColors) { DataPresentFlags |= (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_COLOR; } // Check for weights if (HasWeights) { DataPresentFlags |= (byte)SEModel_MeshDataPresenceFlags.SEMODEL_PRESENCE_WEIGHTS; } // Write it writeFile.Write((byte)DataPresentFlags); } // The bonecount buffer uint BoneCountBuffer = BoneCount; // The meshcount buffer uint MeshCountBuffer = MeshCount; // The matcount buffer uint MatCountBuffer = MaterialCount; // Write count of bones writeFile.Write((uint)BoneCountBuffer); // Write count of meshes writeFile.Write((uint)MeshCountBuffer); // Write count of mats writeFile.Write((uint)MatCountBuffer); // Write 3 reserved bytes writeFile.Write(new byte[3] { 0x0, 0x0, 0x0 }); // Write bone tagnames foreach (var Bone in Bones) { writeFile.WriteNullTermString(Bone.BoneName); } // Write bone data foreach (var Bone in Bones) { // Write bone flags writeFile.Write((byte)0x0); // Write parent index writeFile.Write((int)Bone.BoneParent); // Write global matrix if (HasGlobals) { writeFile.Write((float)Bone.GlobalPosition.X); writeFile.Write((float)Bone.GlobalPosition.Y); writeFile.Write((float)Bone.GlobalPosition.Z); writeFile.Write((float)Bone.GlobalRotation.X); writeFile.Write((float)Bone.GlobalRotation.Y); writeFile.Write((float)Bone.GlobalRotation.Z); writeFile.Write((float)Bone.GlobalRotation.W); } // Write local matrix if (HasLocals) { writeFile.Write((float)Bone.LocalPosition.X); writeFile.Write((float)Bone.LocalPosition.Y); writeFile.Write((float)Bone.LocalPosition.Z); writeFile.Write((float)Bone.LocalRotation.X); writeFile.Write((float)Bone.LocalRotation.Y); writeFile.Write((float)Bone.LocalRotation.Z); writeFile.Write((float)Bone.LocalRotation.W); } // Write scales if (HasScales) { writeFile.Write((float)Bone.Scale.X); writeFile.Write((float)Bone.Scale.Y); writeFile.Write((float)Bone.Scale.Z); } } // Write mesh data foreach (var Mesh in Meshes) { // Write mesh flags writeFile.Write((byte)0x0); // Buffers for counts byte MatIndiciesCount = 0, MaxSkinInfluence = 0; int VertexCount = Mesh.Verticies.Count, FaceCount = Mesh.Faces.Count; // Iterate and calculate indicies foreach (var Vertex in Mesh.Verticies) { if (Vertex.UVSets.Count > MatIndiciesCount) { MatIndiciesCount = (byte)Vertex.UVSets.Count; } if (Vertex.Weights.Count > MaxSkinInfluence) { MaxSkinInfluence = (byte)Vertex.Weights.Count; } } // Write material indicies writeFile.Write((byte)MatIndiciesCount); // Write max skin influence writeFile.Write((byte)MaxSkinInfluence); // Write vertex count writeFile.Write((int)VertexCount); // Write face count writeFile.Write((int)FaceCount); // Write positions foreach (var Vertex in Mesh.Verticies) { writeFile.Write((float)Vertex.Position.X); writeFile.Write((float)Vertex.Position.Y); writeFile.Write((float)Vertex.Position.Z); } // Write uvlayers foreach (var Vertex in Mesh.Verticies) { for (int i = 0; i < MatIndiciesCount; i++) { var Layer = (i < Vertex.UVSets.Count) ? Vertex.UVSets[i] : Vector2.Zero; // Write it writeFile.Write((float)Layer.X); writeFile.Write((float)Layer.Y); } } // Write normals if (HasNormals) { foreach (var Vertex in Mesh.Verticies) { writeFile.Write((float)Vertex.VertexNormal.X); writeFile.Write((float)Vertex.VertexNormal.Y); writeFile.Write((float)Vertex.VertexNormal.Z); } } // Write colors if (HasColors) { foreach (var Vertex in Mesh.Verticies) { writeFile.Write((byte)Vertex.VertexColor.R); writeFile.Write((byte)Vertex.VertexColor.G); writeFile.Write((byte)Vertex.VertexColor.B); writeFile.Write((byte)Vertex.VertexColor.A); } } // Write weights foreach (var Vertex in Mesh.Verticies) { for (int i = 0; i < MaxSkinInfluence; i++) { var WeightID = (i < Vertex.Weights.Count) ? Vertex.Weights[i].BoneIndex : 0; var WeightValue = (i < Vertex.Weights.Count) ? Vertex.Weights[i].BoneWeight : 0.0f; // Write ID based on count if (BoneCountBuffer <= 0xFF) { writeFile.Write((byte)WeightID); } else if (BoneCountBuffer <= 0xFFFF) { writeFile.Write((ushort)WeightID); } else { writeFile.Write((uint)WeightID); } // Write value writeFile.Write((float)WeightValue); } } // Write faces foreach (var Face in Mesh.Faces) { // Write face indicies based on total vertex count if (VertexCount <= 0xFF) { writeFile.Write((byte)Face.FaceIndex1); writeFile.Write((byte)Face.FaceIndex2); writeFile.Write((byte)Face.FaceIndex3); } else if (VertexCount <= 0xFFFF) { writeFile.Write((ushort)Face.FaceIndex1); writeFile.Write((ushort)Face.FaceIndex2); writeFile.Write((ushort)Face.FaceIndex3); } else { writeFile.Write((uint)Face.FaceIndex1); writeFile.Write((uint)Face.FaceIndex2); writeFile.Write((uint)Face.FaceIndex3); } } // Write material indicies for (int i = 0; i < MatIndiciesCount; i++) { var Index = (i < Mesh.MaterialReferenceIndicies.Count) ? Mesh.MaterialReferenceIndicies[i] : -1; // Write the index, or null for no reference writeFile.Write((int)Index); } } // Write material data foreach (var Mat in Materials) { // Write name writeFile.WriteNullTermString(Mat.Name); // Check type if (Mat.MaterialData is SEModelSimpleMaterial) { // Simple material writeFile.Write((bool)true); // Write the image references writeFile.WriteNullTermString(((SEModelSimpleMaterial)Mat.MaterialData).DiffuseMap); writeFile.WriteNullTermString(((SEModelSimpleMaterial)Mat.MaterialData).NormalMap); writeFile.WriteNullTermString(((SEModelSimpleMaterial)Mat.MaterialData).SpecularMap); } } } }