public static byte[] pack(Dictionary <string, byte[]> files) { MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o, false); bw.ByteOrder = ByteOrder.BigEndian; bw.Write("SARC", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0x14); // Chunk length bw.Write((UInt16)0xFEFF); // BOM bw.Write((UInt32)0x00); //filesize update later bw.Write((UInt32)0x00); //Beginning of data bw.Write((UInt32)0x01000000); bw.Write("SFAT", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0xc); bw.Write((UInt16)files.Keys.Count); bw.Write((UInt32)0x00000065); List <uint> offsetToUpdate = new List <uint>(); foreach (string k in files.Keys) { bw.Write(NameHash(k)); bw.Write((byte)0x1); bw.Write((byte)0); //this should be part of the name index, but u16 will work too offsetToUpdate.Add((uint)bw.BaseStream.Position); bw.Write((UInt16)0); bw.Write((UInt32)0); bw.Write((UInt32)0); } bw.Write("SFNT", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0x8); bw.Write((UInt16)0); List <uint> StringOffsets = new List <uint>(); foreach (string k in files.Keys) { StringOffsets.Add((uint)bw.BaseStream.Position); bw.Write(k, BinaryStringFormat.ZeroTerminated); bw.Align(4); } List <uint> FileOffsets = new List <uint>(); foreach (string k in files.Keys) { FileOffsets.Add((uint)bw.BaseStream.Position); bw.Write(files[k]); bw.Align(4); } for (int i = 0; i < offsetToUpdate.Count; i++) { bw.BaseStream.Position = offsetToUpdate[i]; bw.Write((UInt16)((StringOffsets[i] - StringOffsets[0]) / 4)); bw.Write((UInt32)(FileOffsets[i] - FileOffsets[0])); bw.Write((UInt32)(FileOffsets[i] + files.Values.ToArray()[i].Length - FileOffsets[0])); } bw.BaseStream.Position = 0x08; bw.Write((uint)bw.BaseStream.Length); bw.Write((uint)FileOffsets[0]); return(o.ToArray()); }
private void WriteValueContents(BinaryDataWriter writer, Offset offset, ByamlNodeType type, dynamic value) { if (alreadyWrittenNodes.ContainsKey(value)) { offset.Satisfy((int)alreadyWrittenNodes[value]); return; } // Satisfy the offset to the complex node value which must be 4-byte aligned. writer.Align(4); offset.Satisfy(); // Write the value contents. switch (type) { case ByamlNodeType.Dictionary: alreadyWrittenNodes.Add(value, (uint)writer.Position); WriteDictionaryNode(writer, value); break; case ByamlNodeType.StringArray: WriteStringArrayNode(writer, value); break; case ByamlNodeType.PathArray: alreadyWrittenNodes.Add(value, (uint)writer.Position); WritePathArrayNode(writer, value); break; case ByamlNodeType.Array: alreadyWrittenNodes.Add(value, (uint)writer.Position); WriteArrayNode(writer, value); break; default: throw new ByamlException($"{type} not supported as complex node."); } }
private void WritePathArray(BinaryDataWriter writer, Offset offset, IList <List <ByamlPathPoint> > pathArray) { // Satisfy the offset to the value in the BYAML file which must be 4-byte aligned. writer.Align(4); offset.Satisfy(); WriteTypeAndElementCount(writer, ByamlNodeType.PathArray, pathArray.Count); // Write the offsets to the paths. int pathOffset = 4 + 4 * (pathArray.Count + 1); // Relative to node start + all uint32 offsets. foreach (List <ByamlPathPoint> path in pathArray) { writer.Write(pathOffset); pathOffset += path.Count * ByamlPathPoint.SizeInBytes; } writer.Write(pathOffset); // The last one points to the end of the last path. // Write the paths. foreach (List <ByamlPathPoint> path in pathArray) { foreach (ByamlPathPoint point in path) { writer.Write(point.Position); writer.Write(point.Normal); writer.Write(point.Unknown); } } }
private void WriteValueContents(BinaryDataWriter writer, Offset offset, ByamlNodeType type, dynamic value) { // Satisfy the offset to the complex node value which must be 4-byte aligned. writer.Align(4); offset.Satisfy(); // Write the value contents. switch (type) { case ByamlNodeType.Dictionary: WriteDictionaryNode(writer, value); break; case ByamlNodeType.StringArray: WriteStringArrayNode(writer, value); break; case ByamlNodeType.PathArray: WritePathArrayNode(writer, value); break; case ByamlNodeType.Array: WriteArrayNode(writer, value); break; default: throw new ByamlException($"{type} not supported as complex node."); } }
private void WriteStringArrayNode(BinaryDataWriter writer, IEnumerable <string> node) { uint NodeStartPos = (uint)writer.BaseStream.Position; WriteTypeAndLength(writer, ByamlNodeType.StringArray, node); for (int i = 0; i <= node.Count(); i++) { writer.Write(new byte[4]); //Space for offsets } List <uint> offsets = new List <uint>(); foreach (string str in node) { offsets.Add((uint)writer.BaseStream.Position - NodeStartPos); writer.Write(str, BinaryStringFormat.ZeroTerminated); } offsets.Add((uint)writer.BaseStream.Position - NodeStartPos); writer.Align(4); uint backHere = (uint)writer.BaseStream.Position; writer.BaseStream.Position = NodeStartPos + 4; foreach (uint off in offsets) { writer.Write(off); } writer.BaseStream.Position = backHere; }
private void WriteArrayNode(BinaryDataWriter writer, IEnumerable node) { WriteTypeAndLength(writer, ByamlNodeType.Array, node); // Write the element types. foreach (dynamic element in node) { writer.Write((byte)GetNodeType(element)); } // Write the elements, which begin after a padding to the next 4 bytes. writer.Align(4); Dictionary <Offset, dynamic> offsets = new Dictionary <Offset, dynamic>(); foreach (dynamic element in node) { var off = WriteValue(writer, element); if (off != null) { offsets.Add(off, element); } } // Write the contents of complex nodes and satisfy the offsets. foreach (var element in offsets) { WriteValueContents(writer, element.Key, GetNodeType(element.Value), element.Value); } }
private void WriteArrayOrDictionary(BinaryDataWriter writer, Offset offset, object obj) { // Satisfy the offset to the value in the BYAML file which must be 4-byte aligned. writer.Align(4); offset.Satisfy(); // Serialize the value as an array. IList objArray = obj as IList; if (objArray != null) { WriteArray(writer, objArray); return; } // Serialize the value as a custom type. Type objType = obj.GetType(); if (IsTypeByamlObject(objType)) { WriteDictionary(writer, obj); return; } throw new ByamlException($"Type {objType.Name} is not supported as BYAML array or dictionary data."); }
private void WriteArrayNode(BinaryDataWriter writer, IEnumerable node) { WriteTypeAndLength(writer, ByamlNodeType.Array, node); // Write the element types. foreach (dynamic element in node) { writer.Write((byte)GetNodeType(element)); } // Write the elements, which begin after a padding to the next 4 bytes. writer.Align(4); List <Offset> offsets = new List <Offset>(); foreach (dynamic element in node) { offsets.Add(WriteValue(writer, element)); } // Write the contents of complex nodes and satisfy the offsets. int index = 0; foreach (dynamic element in node) { Offset offset = offsets[index]; if (offset != null) { WriteValueContents(writer, offset, GetNodeType(element), element); } index++; } }
public byte[] Write() { var mem = new MemoryStream(); BinaryDataWriter bin = new BinaryDataWriter(mem); bin.ByteOrder = ByteOrder.LittleEndian; bin.Write(Head); List <long> TexPositions = new List <long>(); foreach (var t in Textures) { TexPositions.Add(bin.BaseStream.Position); bin.Write(t.Write()); } var DataStart = bin.BaseStream.Position; List <long> TexDataPositions = new List <long>(); bin.Align(0x10); bin.Write("BRTD", BinaryStringFormat.NoPrefixOrTermination); bin.Write((int)0); bin.Write((int)0); bin.Write((int)0); foreach (var t in Textures) { TexDataPositions.Add(bin.BaseStream.Position); bin.Write(t.Data); bin.Align(0x10); } bin.Align(0x1000); UInt32 rltPos = (UInt32)bin.BaseStream.Position; bin.Write(Rlt); //Update offsets bin.BaseStream.Position = 0x18; bin.Write((UInt32)rltPos); bin.Write((UInt32)bin.BaseStream.Length); bin.BaseStream.Position = TexDataPositions[0] - 8; bin.Write(rltPos - (TexDataPositions[0] - 0x10)); for (int i = 0; i < TexPositions.Count; i++) { bin.BaseStream.Position = TexPositions[i] + 0x2A0; bin.Write(TexDataPositions[i]); } bin.BaseStream.Position = rltPos + 4; bin.Write(rltPos); return(mem.ToArray()); }
void ApplyChanges() { MemoryStream mem = new MemoryStream(); BinaryDataWriter bin = new BinaryDataWriter(mem); bin.Write((ushort)(Properties.Count + AddedProperties.Count)); bin.Write((ushort)0); bin.Write(new byte[0xC * AddedProperties.Count]); bin.Write(data, 4, data.Length - 4); //write rest of entries, adding new elements first doesn't break relative offets in the struct foreach (var m in Properties) { if ((byte)m.type != 1 && (byte)m.type != 2) { continue; } bin.Position = m.ValueOffset + 0xC * AddedProperties.Count; for (int i = 0; i < m.ValueCount; i++) { if (m.type == EditableProperty.ValueType.int32) { bin.Write(int.Parse(m.value[i])); } else { bin.Write(float.Parse(m.value[i])); } } } for (int i = 0; i < AddedProperties.Count; i++) { bin.Position = bin.BaseStream.Length; uint DataOffset = (uint)bin.BaseStream.Position; for (int j = 0; j < AddedProperties[i].ValueCount; j++) { if (AddedProperties[i].type == EditableProperty.ValueType.int32) { bin.Write(int.Parse(AddedProperties[i].value[j])); } else { bin.Write(float.Parse(AddedProperties[i].value[j])); } } uint NameOffest = (uint)bin.BaseStream.Position; bin.Write(AddedProperties[i].Name, BinaryStringFormat.ZeroTerminated); bin.Align(4); uint entryStart = (uint)(4 + i * 0xC); bin.BaseStream.Position = entryStart; bin.Write(NameOffest - entryStart); bin.Write(DataOffset - entryStart); bin.Write(AddedProperties[i].ValueCount); bin.Write((byte)AddedProperties[i].type); bin.Write((byte)0); } data = mem.ToArray(); }
static void WriteModel(BinaryDataWriter er, KCLModel mod) { long HeaderPos = er.BaseStream.Position; mod.Header.Write(er); long curpos = er.BaseStream.Position; //Write vertices array position er.BaseStream.Position = HeaderPos; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; foreach (Vector3D v in mod.Vertices) { er.Write(v); } er.Align(4); curpos = er.BaseStream.Position; //Write normal array position er.BaseStream.Position = HeaderPos + 4; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; foreach (Vector3D v in mod.Normals) { er.Write(v); } er.Align(4); curpos = er.BaseStream.Position; //Write Triangles offset er.BaseStream.Position = HeaderPos + 8; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; foreach (KCLModel.KCLPlane p in mod.Planes) { p.Write(er); } curpos = er.BaseStream.Position; //Write Spatial index offset er.BaseStream.Position = HeaderPos + 12; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; mod.Octree.Write(er); }
private void WriteValueContents(BinaryDataWriter writer, Offset offset, ByamlNodeType type, dynamic value) { if (alreadyWrittenNodes.ContainsKey(value)) { offset.Satisfy((int)alreadyWrittenNodes[value]); return; } else if (value is IEnumerable) { foreach (var d in alreadyWrittenNodes.Keys.Where(x => x is IEnumerable && x.Count == value.Count)) { if (IEnumerableCompare.IsEqual(d, value)) { offset.Satisfy((int)alreadyWrittenNodes[d]); return; } } } // Satisfy the offset to the complex node value which must be 4-byte aligned. writer.Align(4); offset.Satisfy(); // Write the value contents. switch (type) { case ByamlNodeType.Dictionary: alreadyWrittenNodes.Add(value, (uint)writer.Position); WriteDictionaryNode(writer, value); break; case ByamlNodeType.StringArray: WriteStringArrayNode(writer, value); break; case ByamlNodeType.PathArray: alreadyWrittenNodes.Add(value, (uint)writer.Position); WritePathArrayNode(writer, value); break; case ByamlNodeType.Array: alreadyWrittenNodes.Add(value, (uint)writer.Position); WriteArrayNode(writer, value); break; case ByamlNodeType.Double: case ByamlNodeType.ULong: case ByamlNodeType.Long: writer.Write(value); break; default: throw new ByamlException($"{type} not supported as complex node."); } }
public static void WriteArray(ByamlContext ctx, ByamlEntry entry, BinaryDataWriter bw) { var list = (List <ByamlEntry>)entry.Value; bw.Write((byte)entry.NodeType); bw.WriteInt24(list.Count); List <long> tempOffs = new List <long>(); //node types foreach (var item in list) { bw.Write((byte)item.NodeType); } bw.Align(4); //values foreach (var item in list) { if (NodeIsValue(item.NodeType)) { WriteValue(ctx, item, bw); } else { tempOffs.Add(bw.Position); bw.Write(0); //temp } } //array/dictionary int index = 0; foreach (var item in list) { if (!NodeIsValue(item.NodeType)) { long curPos = bw.Position; using (bw.TemporarySeek(tempOffs[index++], SeekOrigin.Begin)) bw.Write((int)curPos); if (item.NodeType == ByamlNodeType.Array) { WriteArray(ctx, item, bw); } else if (item.NodeType == ByamlNodeType.Dictionary) { WriteDictionary(ctx, item, bw); } } } }
private void WritePathArrayNode(BinaryDataWriter writer, IEnumerable<List<ByamlPathPoint>> node) { writer.Align(4); WriteTypeAndLength(writer, ByamlNodeType.PathArray, node); // Write the offsets to the paths, where the last one points to the end of the last path. long offset = 4 + 4 * (node.Count() + 1); // Relative to node start + all uint32 offsets. foreach (List<ByamlPathPoint> path in node) { writer.Write((uint)offset); offset += path.Count * 28; // 28 bytes are required for a single point. } writer.Write((uint)offset); // Write the paths. foreach (List<ByamlPathPoint> path in node) { WritePathNode(writer, path); } }
/// <summary> /// Saves the data into the given <paramref name="stream"/>. /// </summary> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param> public void Save(Stream stream) { using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII, true)) { writer.ByteOrder = ByteOrder; // Write the file header. writer.Write(Identifier, BinaryStringFormat.NoPrefixOrTermination); Offset fileSizeOffset = writer.ReserveOffset(); writer.Write((short)Count); writer.Write(Unknown); writer.Write(Version); Offset[] sectionOffsets = writer.ReserveOffset(Count); int headerLength = (int)writer.Position; // Write all the sections. int sectionIndex = 0; foreach (SectionBase section in this) { // Fill in the offset to this section. sectionOffsets[sectionIndex].Satisfy((int)writer.Position - headerLength); // Write the section header. writer.Write(section.Name, BinaryStringFormat.NoPrefixOrTermination); writer.Write(section.ElementCount); writer.Write((short)section.Count); writer.Write(section.SectionType, false); // Write the section groups, each of them is 4-byte aligned. foreach (GroupBase group in section) { group.Save(writer); writer.Align(4); } sectionIndex++; } fileSizeOffset.Satisfy(); } }
private void WriteV2(BinaryDataWriter writer) { writer.ByteOrder = ByteOrder.BigEndian; writer.Write((uint)Version); writer.ByteOrder = this.ByteOrder; Offset octreeOffset = writer.ReserveOffset(); Offset modelOffsetArrayOffset = writer.ReserveOffset(); writer.Write(Models.Count); writer.Write(MinCoordinate); writer.Write(MaxCoordinate); writer.Write(CoordinateShift); writer.Write(PrismCount); // Write the model octree. octreeOffset.Satisfy(); foreach (ModelOctreeNode rootChild in ModelOctreeRoot) { rootChild.Write(writer); } int branchKey = 8; foreach (ModelOctreeNode rootChild in ModelOctreeRoot) { rootChild.WriteChildren(writer, ref branchKey); } // Write the model offsets. modelOffsetArrayOffset.Satisfy(); Offset[] modelOffsets = writer.ReserveOffset(Models.Count); // Write the models. for (int i = 0; i < Models.Count; i++) { modelOffsets[i].Satisfy(); Models[i].Write(writer, Version); writer.Align(4); } }
private void WriteStringArrayNode(BinaryDataWriter writer, IEnumerable <string> node) { writer.Align(4); WriteTypeAndLength(writer, ByamlNodeType.StringArray, node); // Write the offsets to the strings, where the last one points to the end of the last string. long offset = 4 + 4 * (node.Count() + 1); // Relative to node start + all uint32 offsets. foreach (string str in node) { writer.Write((uint)offset); offset += str.Length + 1; } writer.Write((uint)offset); // Write the 0-terminated strings. foreach (string str in node) { writer.Write(str, BinaryStringFormat.ZeroTerminated); } }
/// <summary> /// Saves the data into the given <paramref name="stream"/>. /// </summary> /// <param name="stream">The <see cref="Stream"/> to save the data to.</param> public void Save(Stream stream) { using (BinaryDataWriter writer = new BinaryDataWriter(stream, true) { ByteOrder = ByteOrder.BigEndian }) { // Write the header. writer.Write(_signature); Offset octreeOffset = writer.ReserveOffset(); Offset modelOffsetArrayOffset = writer.ReserveOffset(); writer.Write(Models.Count); writer.Write(MinCoordinate); writer.Write(MaxCoordinate); writer.Write(CoordinateShift); writer.Write(Unknown); // Write the model octree. octreeOffset.Satisfy(); foreach (CourseOctreeNode rootChild in CourseOctreeRoot) { rootChild.Save(writer); } // Write the model offsets. modelOffsetArrayOffset.Satisfy(); Offset[] modelOffsets = writer.ReserveOffset(Models.Count); // Write the models. int i = 0; foreach (KclModel model in Models) { modelOffsets[i++].Satisfy(); model.Save(stream); writer.Align(4); } } }
private void WriteArray(BinaryDataWriter writer, IList array) { WriteTypeAndElementCount(writer, ByamlNodeType.Array, array.Count); // Write the element types (which must be the same for each to be supported for serialization). ByamlNodeType nodeType = GetNodeType(array.GetType().GetTypeInfo().GetElementType()); for (int i = 0; i < array.Count; i++) { writer.Write((byte)nodeType); } // Write the elements, which begin after a padding to the next 4 bytes. writer.Align(4); if (nodeType == ByamlNodeType.Array || nodeType == ByamlNodeType.Dictionary) { // Arrays or dictionaries are referenced by offsets pointing behind the array. Offset[] offsets = new Offset[array.Count]; for (int i = 0; i < array.Count; i++) { offsets[i] = writer.ReserveOffset(); } // Behind the offsets, write the array or dictionary contents and satisfy the 4-byte aligned offsets. for (int i = 0; i < array.Count; i++) { WriteArrayOrDictionary(writer, offsets[i], array[i]); } } else { // Primitive values are stored directly rather than being referenced by offsets. foreach (object element in array) { WritePrimitiveType(writer, nodeType, element); } } }
//write byaml public static void WriteStringList(List <string> list, BinaryDataWriter bw) { long startPos = bw.Position; bw.Write((byte)ByamlNodeType.StringTable); bw.WriteInt24(list.Count); bw.Write(new byte[4 * (list.Count + 1)]); //temp long tempPos; for (int i = 0; i < list.Count; i++) { tempPos = bw.Position; using (bw.TemporarySeek(startPos + 4 + i * 4, SeekOrigin.Begin)) bw.Write((int)(tempPos - startPos)); bw.Write(Encoding.UTF8.GetBytes(list[i] + "\0")); } tempPos = bw.Position; using (bw.TemporarySeek(startPos + 4 + list.Count * 4, SeekOrigin.Begin)) bw.Write((int)(tempPos - startPos)); bw.Align(4); }
private void WriteStringArray(BinaryDataWriter writer, Offset offset, IList <string> stringArray) { // Satisfy the offset to the value in the BYAML file which must be 4-byte aligned. writer.Align(4); offset.Satisfy(); WriteTypeAndElementCount(writer, ByamlNodeType.StringArray, stringArray.Count); // Write the offsets to the strings. int stringOffset = 4 + 4 * (stringArray.Count + 1); // Relative to node start + all uint32 offsets. foreach (string str in stringArray) { writer.Write(stringOffset); stringOffset += str.Length + 1; } writer.Write(stringOffset); // The last one points to the end of the last string. // Write the 0-terminated strings. foreach (string str in stringArray) { writer.Write(str, BinaryStringFormat.ZeroTerminated); } }
protected void WriteContent(object rootReferenceKey) { using (_writer) { // Write the header, specifying magic bytes, version and main node offsets. _writer.Write(BYAML_MAGIC); _writer.Write(_version); Offset nameArrayOffset = _writer.ReserveOffset(); Offset stringArrayOffset = _writer.ReserveOffset(); Offset pathArrayOffset = _supportPaths ? _writer.ReserveOffset() : null; Offset rootOffset = _writer.ReserveOffset(); // Write the main nodes. _writer.Align(4); nameArrayOffset.Satisfy(); WriteStringArrayNode(_writer, _nameArray); if (_stringArray.Length == 0) { stringArrayOffset.Satisfy(0); } else { _writer.Align(4); stringArrayOffset.Satisfy(); WriteStringArrayNode(_writer, _stringArray); } // Include a path array offset if requested. if (_supportPaths) { if (_pathArray.Count == 0) { pathArrayOffset.Satisfy(0); } else { _writer.Align(4); pathArrayOffset.Satisfy(); WritePathArrayNode(_writer, _pathArray); } } _writer.Align(4); //write value stack (Dictionary, Array, long, uint, double) int valStackPos = (int)_writer.BaseStream.Position; //write all dictionaries foreach (KeyValuePair <object, ByamlDict> keyValuePair in _dictionaries) { _writer.Seek(valStackPos + keyValuePair.Value.offset, SeekOrigin.Begin); if (keyValuePair.Key == rootReferenceKey) { rootOffset.Satisfy(); } if (_byteOrder == ByteOrder.BigEndian) { _writer.Write((uint)ByamlNodeType.Dictionary << 24 | (uint)keyValuePair.Value.entries.Length); } else { _writer.Write((uint)ByamlNodeType.Dictionary | (uint)keyValuePair.Value.entries.Length << 8); } foreach ((string key, Entry entry) in keyValuePair.Value.entries) { if (_byteOrder == ByteOrder.BigEndian) { _writer.Write(Array.IndexOf(_nameArray, key) << 8 | (byte)entry.type); } else { _writer.Write(Array.IndexOf(_nameArray, key) | (byte)entry.type << 24); } WriteValue(entry); } } //write all arrays foreach (KeyValuePair <object, ByamlArr> keyValuePair in _arrays) { _writer.Seek(valStackPos + keyValuePair.Value.offset, SeekOrigin.Begin); if (keyValuePair.Key == rootReferenceKey) { rootOffset.Satisfy(); } if (_byteOrder == ByteOrder.BigEndian) { _writer.Write((uint)ByamlNodeType.Array << 24 | (uint)keyValuePair.Value.entries.Length); } else { _writer.Write((uint)ByamlNodeType.Array | (uint)keyValuePair.Value.entries.Length << 8); } foreach (Entry entry in keyValuePair.Value.entries) { _writer.Write((byte)entry.type); } _writer.Align(4); foreach (Entry entry in keyValuePair.Value.entries) { WriteValue(entry); } } //write all 8 byte values foreach (var keyValuePair in _eightByteValues) { _writer.Seek(valStackPos + keyValuePair.Value, SeekOrigin.Begin); _writer.Write(keyValuePair.Key); } void WriteValue(Entry entry) { // Only write the offset for the complex value contents, write simple values directly. switch (entry.type) { case ByamlNodeType.StringIndex: _writer.Write((uint)Array.IndexOf(_stringArray, entry.value)); break; case ByamlNodeType.PathIndex: _writer.Write(_pathArray.IndexOf(entry.value)); break; case ByamlNodeType.Dictionary: _writer.Write(valStackPos + _dictionaries[(object)entry.value].offset); break; case ByamlNodeType.Array: _writer.Write(valStackPos + _arrays[(object)entry.value].offset); break; case ByamlNodeType.Boolean: _writer.Write(entry.value ? 1 : 0); break; case ByamlNodeType.Integer: case ByamlNodeType.Float: case ByamlNodeType.UInteger: _writer.Write(entry.value); break; case ByamlNodeType.Double: case ByamlNodeType.ULong: case ByamlNodeType.Long: _writer.Write(valStackPos + _eightByteValues[entry.value]); return; case ByamlNodeType.Null: _writer.Write(0); break; } } } }
public static Tuple <int, byte[]> PackN(SarcData data, int _align = -1) { int align = _align >= 0 ? _align : (int)GuessAlignment(data.Files); MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o, false); bw.ByteOrder = data.endianness; bw.Write("SARC", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0x14); // Chunk length bw.Write((UInt16)0xFEFF); // BOM bw.Write((UInt32)0x00); //filesize update later bw.Write((UInt32)0x00); //Beginning of data bw.Write((UInt16)0x100); bw.Write((UInt16)0x00); bw.Write("SFAT", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0xc); bw.Write((UInt16)data.Files.Keys.Count); bw.Write((UInt32)0x00000065); List <uint> offsetToUpdate = new List <uint>(); //Names must be sorted by hash string[] SortedNames = null; if (data.HashOnly) { SortedNames = data.Files.Keys.OrderBy(x => StringHashToUint(x)).ToArray(); } else { SortedNames = data.Files.Keys.OrderBy(x => NameHash(x)).ToArray(); } foreach (string k in SortedNames) { if (data.HashOnly) { bw.Write(StringHashToUint(k)); } else { bw.Write(NameHash(k)); } offsetToUpdate.Add((uint)bw.BaseStream.Position); bw.Write((UInt32)0); bw.Write((UInt32)0); bw.Write((UInt32)0); } bw.Write("SFNT", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0x8); bw.Write((UInt16)0); List <uint> StringOffsets = new List <uint>(); foreach (string k in SortedNames) { StringOffsets.Add((uint)bw.BaseStream.Position); bw.Write(k, BinaryStringFormat.ZeroTerminated); bw.Align(4); } bw.Align(0x1000); //TODO: check if works in odyssey List <uint> FileOffsets = new List <uint>(); foreach (string k in SortedNames) { bw.Align((int)GuessFileAlignment(data.Files[k])); FileOffsets.Add((uint)bw.BaseStream.Position); bw.Write(data.Files[k]); } for (int i = 0; i < offsetToUpdate.Count; i++) { bw.BaseStream.Position = offsetToUpdate[i]; if (!data.HashOnly) { bw.Write(0x01000000 | ((StringOffsets[i] - StringOffsets[0]) / 4)); } else { bw.Write((UInt32)0); } bw.Write((UInt32)(FileOffsets[i] - FileOffsets[0])); bw.Write((UInt32)(FileOffsets[i] + data.Files[SortedNames[i]].Length - FileOffsets[0])); } bw.BaseStream.Position = 0x08; bw.Write((uint)bw.BaseStream.Length); bw.Write((uint)FileOffsets[0]); return(new Tuple <int, byte[]>(align, o.ToArray())); }
public static byte[] pack(Dictionary <string, byte[]> files, int align = -1, ByteOrder endianness = ByteOrder.LittleEndian) { if (align < 0) { align = (int)GuessAlignment(files); } MemoryStream o = new MemoryStream(); BinaryDataWriter bw = new BinaryDataWriter(o, false); bw.ByteOrder = endianness; bw.Write("SARC", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0x14); // Chunk length bw.Write((UInt16)0xFEFF); // BOM bw.Write((UInt32)0x00); //filesize update later bw.Write((UInt32)0x00); //Beginning of data bw.Write((UInt32)0x00000100); bw.Write("SFAT", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0xc); bw.Write((UInt16)files.Keys.Count); bw.Write((UInt32)0x00000065); List <uint> offsetToUpdate = new List <uint>(); foreach (string k in files.Keys) { bw.Write(NameHash(k)); offsetToUpdate.Add((uint)bw.BaseStream.Position); bw.Write((UInt32)0); bw.Write((UInt32)0); bw.Write((UInt32)0); } bw.Write("SFNT", BinaryStringFormat.NoPrefixOrTermination); bw.Write((UInt16)0x8); bw.Write((UInt16)0); List <uint> StringOffsets = new List <uint>(); foreach (string k in files.Keys) { StringOffsets.Add((uint)bw.BaseStream.Position); bw.Write(k, BinaryStringFormat.ZeroTerminated); bw.Align(4); } bw.Align(align); List <uint> FileOffsets = new List <uint>(); foreach (string k in files.Keys) { FileOffsets.Add((uint)bw.BaseStream.Position); bw.Write(files[k]); bw.Align(align); } for (int i = 0; i < offsetToUpdate.Count; i++) { bw.BaseStream.Position = offsetToUpdate[i]; bw.Write((UInt16)((StringOffsets[i] - StringOffsets[0]) / 4)); bw.Write((UInt16)0x0100); bw.Write((UInt32)(FileOffsets[i] - FileOffsets[0])); bw.Write((UInt32)(FileOffsets[i] + files.Values.ToArray()[i].Length - FileOffsets[0])); } bw.BaseStream.Position = 0x08; bw.Write((uint)bw.BaseStream.Length); bw.Write((uint)FileOffsets[0]); return(o.ToArray()); }
protected override void ApplyChanges(BinaryDataWriter bin) { AddNewProperties(); bin.ByteOrder = order; bin.Write((ushort)(Properties.Count + AddedProperties.Count + UnknownPropertiesCount)); bin.Write((ushort)0); bin.Write(new byte[0xC * AddedProperties.Count]); bin.Write(data, 4, data.Length - 4); //write rest of entries, adding new elements first doesn't break relative offets in the struct foreach (var m in Properties) { if ((byte)m.type != 1 && (byte)m.type != 2) { continue; } m.ValueOffset += +0xC * AddedProperties.Count; bin.Position = m.ValueOffset; if (m.value.Length != m.ValueCount) { throw new Exception("Can't change the number of values of an usd1 property"); } for (int i = 0; i < m.ValueCount; i++) { if (m.type == EditableProperty.ValueType.int32) { bin.Write(int.Parse(m.value[i])); } else { bin.Write(float.Parse(m.value[i])); } } } for (int i = 0; i < AddedProperties.Count; i++) { bin.Position = bin.BaseStream.Length; uint DataOffset = (uint)bin.BaseStream.Position; AddedProperties[i].ValueOffset = DataOffset; AddedProperties[i].ValueCount = (ushort)AddedProperties[i].value.Length; for (int j = 0; j < AddedProperties[i].value.Length; j++) { if (AddedProperties[i].type == EditableProperty.ValueType.int32) { bin.Write(int.Parse(AddedProperties[i].value[j])); } else { bin.Write(float.Parse(AddedProperties[i].value[j])); } } uint NameOffest = (uint)bin.BaseStream.Position; bin.Write(AddedProperties[i].Name, BinaryStringFormat.ZeroTerminated); bin.Align(4); uint entryStart = (uint)(4 + i * 0xC); bin.BaseStream.Position = entryStart; bin.Write(NameOffest - entryStart); bin.Write(DataOffset - entryStart); bin.Write((ushort)AddedProperties[i].ValueCount); bin.Write((byte)AddedProperties[i].type); bin.Write((byte)0); OriginalProperties.Add(AddedProperties[i].Name); } Properties.AddRange(AddedProperties); AddedProperties.Clear(); }
public byte[] Write(ByteOrder byteOrder) { if (Models.Count != 8) { throw new Exception("The root octree is not complete"); } var size = GlobalHeader.OctreeMax - GlobalHeader.OctreeOrigin; using (MemoryStream m = new MemoryStream()) { BinaryDataWriter er = new BinaryDataWriter(m); //Write KCL Header er.ByteOrder = ByteOrder.BigEndian; //The signature is always big endian er.Write(0x02020000); er.ByteOrder = byteOrder; er.Write((UInt32)0x38); er.Write((UInt32)0x58); er.Write((UInt32)Models.Count); er.Write(GlobalHeader.OctreeOrigin); er.Write(GlobalHeader.OctreeMax); er.Write((UInt32)GlobalHeader.CoordShift); er.Write((UInt32)GlobalHeader.YShift); er.Write((UInt32)GlobalHeader.ZShift); er.Write((UInt32)GlobalHeader.Unknown1); List <KCLModel> WriteModels = new List <KCLModel>(); uint modelCount = 0; for (int i = 0; i < 8; i++) { if (Models[i] != null) { er.Write((UInt32)(0x80000000 | modelCount)); modelCount++; WriteModels.Add(Models[i]); } else { er.Write((UInt32)(0xC0000000)); } } if (modelCount == 0) { throw new Exception("No models in the global octree"); } uint ModelListOff = (uint)er.BaseStream.Position; er.BaseStream.Position = 0xC; er.Write((UInt32)modelCount); er.BaseStream.Position = ModelListOff; for (int i = 0; i < modelCount; i++) //Update offsets later { er.Write((UInt32)0); } for (int i = 0; i < modelCount; i++) { er.Align(4); uint pos = (uint)er.BaseStream.Position; er.BaseStream.Position = ModelListOff + i * 4; er.Write((UInt32)pos); er.BaseStream.Position = pos; WriteModel(er, WriteModels[i]); } return(m.ToArray()); } }