public FontList(ref BinaryStream s) { SectionHeader section = new SectionHeader(ref s); int startpos = (int)s.BaseStream.Position - 8; fontCount = s.ReadUInt16(); s.Align(4); // Padding int basepos = (int)s.BaseStream.Position; fileNameOffsets = new uint[fontCount]; fileNames = new string[fontCount]; for (int o = 0; o < fontCount; o++) { fileNameOffsets[o] = s.ReadUInt32(); int offsetpos = (int)s.BaseStream.Position; s.BaseStream.Position = basepos + fileNameOffsets[o]; fileNames[o] = s.ReadString(StringCoding.ZeroTerminated); s.Align(4); s.BaseStream.Position = offsetpos; } s.BaseStream.Position = startpos + section.size; }
public void Write(ref BinaryStream s) { s.WriteByte((byte)originType); s.Align(4); // Padding s.WriteSingle(screenWidth); s.WriteSingle(screenHeight); s.WriteSingle(maxPartsWidth); s.WriteSingle(maxPartsHeight); s.WriteString(name, StringCoding.ZeroTerminated); s.Align(4); }
public void Write(ref BinaryStream s) { s.WriteByte((byte)combineRBG); s.WriteByte((byte)combineAlpha); s.Align(4); // Padding }
public MaterialList(ref BinaryStream s) { SectionHeader section = new SectionHeader(ref s); int startpos = (int)s.BaseStream.Position - 8; materialCount = s.ReadUInt16(); s.Align(4); // Padding infoOffsets = new uint[materialCount]; materials = new Material[materialCount]; for (int o = 0; o < materialCount; o++) { infoOffsets[o] = s.ReadUInt32(); int offsetpos = (int)s.BaseStream.Position; s.BaseStream.Position = startpos + infoOffsets[o]; materials[o] = new Material(ref s); s.BaseStream.Position = offsetpos; } s.BaseStream.Position = startpos + section.size; }
public void Write(ref BinaryStream s) { s.WriteByte((byte)compareFunc); s.Align(4); // Padding s.WriteSingle(alphaRef); }
public TextBox(ref BinaryStream s) : base(ref s) { int startPos = (int)s.BaseStream.Position - 84; bufByteCount = s.ReadUInt16(); stringByteCount = s.ReadUInt16(); materialIndex = s.ReadUInt16(); fontIndex = s.ReadUInt16(); textPosition = s.Read1Byte(); textAlignment = s.Read1Byte(); flags = s.ReadUInt16(); italicsRatio = s.ReadSingle(); textOffset = s.ReadUInt32(); textColors = new Color[2]; textColors[0] = ColorHelper.BytesToColor(s.ReadBytes(4)); // Color 1 textColors[1] = ColorHelper.BytesToColor(s.ReadBytes(4)); // Color 2 fontSize = new Vec2(s.ReadSingle(), s.ReadSingle()); charSpace = s.ReadSingle(); lineSpace = s.ReadSingle(); textIDOffset = s.ReadUInt32(); shadowOffset = new Vec2(s.ReadSingle(), s.ReadSingle()); shadowScale = new Vec2(s.ReadSingle(), s.ReadSingle()); shadowColors = new Color[2]; shadowColors[0] = ColorHelper.BytesToColor(s.ReadBytes(4)); // Color 1 shadowColors[1] = ColorHelper.BytesToColor(s.ReadBytes(4)); // Color 2 shadowItalicsRatio = s.ReadSingle(); lineWidthOffsetOffset = s.ReadUInt32(); perCharacterTransformOffset = s.ReadUInt32(); text = Encoding.ASCII.GetString(s.ReadBytes(stringByteCount)).Replace("\0", ""); if (textIDOffset != 0) { s.BaseStream.Position = startPos + textIDOffset; textID = (int)s.ReadUInt32(); } s.Align(4); // Align everything // Do character transforms later }
public ProjectionTexGenParameters(ref BinaryStream s) { transX = s.ReadSingle(); transY = s.ReadSingle(); scaleX = s.ReadSingle(); scaleY = s.ReadSingle(); flag = s.Read1Byte(); s.Align(4); // Padding }
public static void AlignWithValue(this BinaryStream bs, int alignment, byte value, bool grow = false) { long basePos = bs.Position; long newPos = bs.Align(alignment); bs.Position = basePos; for (long i = basePos; i < newPos; i++) { bs.WriteByte(value); } }
public void Write(ref BinaryStream s) { s.WriteByte((byte)genType); s.WriteByte((byte)genSource); s.Align(4); // Padding s.WriteSingle(translate); s.WriteSingle(scale); s.WriteByte(flag); s.Write(new byte[] { 0x00, 0x00, 0x00 }); // Reserved }
public static void AlignWithValue(this BinaryStream bs, int alignment, byte val) { long pos = bs.Position; bs.Align(alignment, true); long endPos = bs.Position; bs.Position = pos; for (int i = 0; i < endPos - pos; i++) { bs.WriteByte(val); } }
public LayoutSettings(ref BinaryStream s) { SectionHeader section = new SectionHeader(ref s); s.Read1Byte(); s.ReadBytes(3); // Padding screenWidth = s.ReadSingle(); screenHeight = s.ReadSingle(); maxPartsWidth = s.ReadSingle(); maxPartsHeight = s.ReadSingle(); name = s.ReadString(StringCoding.ZeroTerminated); s.Align(4); // Padding }
private List <dynamic> ReadArrayNode(BinaryStream _binaryStream, int length) { List <dynamic> array = new List <dynamic>(length); if (_fastLoad) { _alreadyReadNodes.Add((uint)_binaryStream.Position - 4, array); } // Read the element types of the array. byte[] nodeTypes = _binaryStream.ReadBytes(length); // Read the elements, which begin after a padding to the next 4 bytes. _binaryStream.Align(4); for (int i = 0; i < length; i++) { array.Add(ReadNode(_binaryStream, (ByamlNodeType)nodeTypes[i])); } return(array); }
public static Tuple <int, byte[]> PackN(SarcData data, int _align = -1) { int align = _align >= 0 ? _align : (int)GuessAlignment(data.Files); MemoryStream o = new MemoryStream(); BinaryStream bs = new BinaryStream(o, ByteConverter.GetConverter(data.endianness), leaveOpen: false); bs.Write("SARC", StringCoding.Raw); bs.Write((UInt16)0x14); // Chunk length bs.Write((UInt16)0xFEFF); // BOM bs.Write((UInt32)0x00); //filesize update later bs.Write((UInt32)0x00); //Beginning of data bs.Write((UInt16)0x100); bs.Write((UInt16)0x00); bs.Write("SFAT", StringCoding.Raw); bs.Write((UInt16)0xc); bs.Write((UInt16)data.Files.Keys.Count); bs.Write((UInt32)0x00000065); List <uint> offsetToUpdate = new List <uint>(); //Sort files by hash string[] Keys = data.Files.Keys.OrderBy(x => data.HashOnly ? StringHashToUint(x) : NameHash(x)).ToArray(); foreach (string k in Keys) { if (data.HashOnly) { bs.Write(StringHashToUint(k)); } else { bs.Write(NameHash(k)); } offsetToUpdate.Add((uint)bs.BaseStream.Position); bs.Write((UInt32)0); bs.Write((UInt32)0); bs.Write((UInt32)0); } bs.Write("SFNT", StringCoding.Raw); bs.Write((UInt16)0x8); bs.Write((UInt16)0); List <uint> StringOffsets = new List <uint>(); foreach (string k in Keys) { StringOffsets.Add((uint)bs.BaseStream.Position); bs.Write(k, StringCoding.ZeroTerminated); bs.Align(4); } bs.Align(0x1000); //TODO: check if works in odyssey List <uint> FileOffsets = new List <uint>(); foreach (string k in Keys) { bs.Align((int)GuessFileAlignment(data.Files[k])); FileOffsets.Add((uint)bs.BaseStream.Position); bs.Write(data.Files[k]); } for (int i = 0; i < offsetToUpdate.Count; i++) { bs.BaseStream.Position = offsetToUpdate[i]; if (!data.HashOnly) { bs.Write(0x01000000 | ((StringOffsets[i] - StringOffsets[0]) / 4)); } else { bs.Write((UInt32)0); } bs.Write((UInt32)(FileOffsets[i] - FileOffsets[0])); bs.Write((UInt32)(FileOffsets[i] + data.Files[Keys[i]].Length - FileOffsets[0])); } bs.BaseStream.Position = 0x08; bs.Write((uint)bs.BaseStream.Length); bs.Write((uint)FileOffsets[0]); return(new Tuple <int, byte[]>(align, o.ToArray())); }
public void Save(string path) { using (var fs = new FileStream(path, FileMode.Create)) using (var bs = new BinaryStream(fs, ByteConverter.Big)) { bs.WriteString(MAGIC, StringCoding.Raw); bs.Position += 4; bs.Position += 4; // Skip prefixes offset for now bs.WriteInt32(NameTrees.Count); bs.Position += NameTrees.Count * sizeof(uint); bs.AlignWithValue(0x10, 0x5E); long lastPos = bs.Position; for (int i = 0; i < NameTrees.Count; i++) { var currentTree = NameTrees[i]; bs.Position = lastPos; int baseTreePos = (int)bs.Position; // For now skip everything and go to the string tables bs.Position += 0x10; bs.Position += 0x10 * currentTree.Entries.Count; OptimizedStringTable opt = NameTrees[i].GetStringTable(); opt.SaveStream(bs); bs.AlignWithValue(0x10, 0x5E); lastPos = bs.Position; // Write where the tree is located bs.Position = 0x10 + (i * sizeof(uint)); bs.WriteInt32(baseTreePos); // Write its data bs.Position = baseTreePos; bs.WriteInt32(100); bs.WriteInt32(currentTree.Entries.Count); bs.AlignWithValue(0x10, 0x5E); for (int j = 0; j < currentTree.Entries.Count; j++) { var entry = currentTree.Entries[j]; bs.WriteUInt32(entry.SpecDBID); bs.WriteUInt32(entry.AlphabeticalID); bs.WriteInt32(opt.GetStringOffset(entry.FullName)); bs.WriteBytes(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }); } } // Write the prefix tree bs.Position = lastPos; bs.WriteInt32(Prefixes.Count); // 4 byte header // Skip entries bs.Position += Prefixes.Count * sizeof(uint); OptimizedStringTable prefixST = GetPrefixStringTable(); prefixST.SaveStream(bs); bs.Align(0x10, true); // String table bs.Position = lastPos + 4; foreach (var prefix in Prefixes) { bs.WriteInt32(prefixST.GetStringOffset(prefix.Name)); } // Write prefix tree offset bs.Position = 0x08; bs.WriteInt32((int)lastPos); } }
protected void WriteContent(object rootReferenceKey) { using (_binaryStream) { // Write the header, specifying magic bytes, version and main node offsets. _binaryStream.Write(BYAML_MAGIC); _binaryStream.Write(_version); Offset nameArrayOffset = _binaryStream.ReserveOffset(); Offset stringArrayOffset = _binaryStream.ReserveOffset(); Offset pathArrayOffset = _supportPaths ? _binaryStream.ReserveOffset() : null; Offset rootOffset = _binaryStream.ReserveOffset(); // Write the main nodes. _binaryStream.Align(4); nameArrayOffset.Satisfy(); WriteStringArrayNode(_binaryStream, _nameArray); if (_stringArray.Length == 0) { stringArrayOffset.Satisfy(0); } else { _binaryStream.Align(4); stringArrayOffset.Satisfy(); WriteStringArrayNode(_binaryStream, _stringArray); } // Include a path array offset if requested. if (_supportPaths) { if (_pathArray.Count == 0) { pathArrayOffset.Satisfy(0); } else { _binaryStream.Align(4); pathArrayOffset.Satisfy(); WritePathArrayNode(_binaryStream, _pathArray); } } _binaryStream.Align(4); //write value stack (Dictionary, Array, long, uint, double) uint valStackPos = (uint)_binaryStream.Position; //write all dictionaries foreach (KeyValuePair <object, ByamlDict> keyValuePair in _dictionaries) { _binaryStream.Seek(valStackPos + keyValuePair.Value.offset, SeekOrigin.Begin); if (keyValuePair.Key == rootReferenceKey) { rootOffset.Satisfy(); } if (_byteOrder == Endian.Big) { _binaryStream.Write((uint)ByamlNodeType.Dictionary << 24 | (uint)keyValuePair.Value.entries.Length); } else { _binaryStream.Write((uint)ByamlNodeType.Dictionary | (uint)keyValuePair.Value.entries.Length << 8); } foreach ((string key, Entry entry) in keyValuePair.Value.entries) { if (_byteOrder == Endian.Big) { _binaryStream.Write(Array.IndexOf(_nameArray, key) << 8 | (byte)entry.type); } else { _binaryStream.Write(Array.IndexOf(_nameArray, key) | (byte)entry.type << 24); } WriteValue(entry); } } //write all arrays foreach (KeyValuePair <object, ByamlArr> keyValuePair in _arrays) { _binaryStream.Seek(valStackPos + keyValuePair.Value.offset, SeekOrigin.Begin); if (keyValuePair.Key == rootReferenceKey) { rootOffset.Satisfy(); } if (_byteOrder == Endian.Big) { _binaryStream.Write((uint)ByamlNodeType.Array << 24 | (uint)keyValuePair.Value.entries.Length); } else { _binaryStream.Write((uint)ByamlNodeType.Array | (uint)keyValuePair.Value.entries.Length << 8); } foreach (Entry entry in keyValuePair.Value.entries) { _binaryStream.Write((byte)entry.type); } _binaryStream.Align(4); foreach (Entry entry in keyValuePair.Value.entries) { WriteValue(entry); } } //write all 8 byte values foreach (var keyValuePair in _eightByteValues) { _binaryStream.Seek(valStackPos + keyValuePair.Value, SeekOrigin.Begin); _binaryStream.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: _binaryStream.Write((uint)Array.IndexOf(_stringArray, entry.value)); break; case ByamlNodeType.PathIndex: _binaryStream.Write(_pathArray.IndexOf(entry.value)); break; case ByamlNodeType.Dictionary: _binaryStream.Write(valStackPos + _dictionaries[(object)entry.value].offset); break; case ByamlNodeType.Array: _binaryStream.Write(valStackPos + _arrays[(object)entry.value].offset); break; case ByamlNodeType.Boolean: _binaryStream.Write(entry.value ? 1 : 0); break; case ByamlNodeType.Integer: case ByamlNodeType.Float: case ByamlNodeType.UInteger: _binaryStream.Write(entry.value); break; case ByamlNodeType.Double: case ByamlNodeType.ULong: case ByamlNodeType.Long: _binaryStream.Write(valStackPos + _eightByteValues[entry.value]); return; case ByamlNodeType.Null: _binaryStream.Write(0); break; } } } }
public Window(ref BinaryStream s) : base(ref s) { int startPos = (int)s.BaseStream.Position - 84; inflation = new WindowInflation(); inflation.left = s.ReadUInt16(); inflation.right = s.ReadUInt16(); inflation.top = s.ReadUInt16(); inflation.bottom = s.ReadUInt16(); frameSize = new WindowFrameSize(); frameSize.left = s.ReadUInt16(); frameSize.right = s.ReadUInt16(); frameSize.top = s.ReadUInt16(); frameSize.bottom = s.ReadUInt16(); frameCount = s.Read1Byte(); windowFlags = s.Read1Byte(); s.Align(4); // Padding contentOffset = s.ReadUInt32(); frameOffsetTableOffset = s.ReadUInt32(); s.BaseStream.Position = startPos + contentOffset; content = new WindowContent(); content.vertexColors = new Color[4]; content.vertexColors[0] = ColorHelper.BytesToColor(s.ReadBytes(4)); // TL content.vertexColors[1] = ColorHelper.BytesToColor(s.ReadBytes(4)); // TR content.vertexColors[2] = ColorHelper.BytesToColor(s.ReadBytes(4)); // BL content.vertexColors[3] = ColorHelper.BytesToColor(s.ReadBytes(4)); // BR content.materialIndex = s.ReadUInt16(); content.texCoordCount = s.Read1Byte(); s.Align(4); // Padding content.texCoords = new TexCoord[content.texCoordCount]; for (int i = 0; i < content.texCoordCount; i++) { content.texCoords[i] = new TexCoord( new Vec2(s.ReadSingle(), s.ReadSingle()), // TL new Vec2(s.ReadSingle(), s.ReadSingle()), // TR new Vec2(s.ReadSingle(), s.ReadSingle()), // BL new Vec2(s.ReadSingle(), s.ReadSingle()) // BR ); } s.BaseStream.Position = startPos + frameOffsetTableOffset; frameOffsetTable = new uint[frameCount]; for (int i = 0; i < frameCount; i++) { frameOffsetTable[i] = s.ReadUInt32(); } frames = new WindowFrame[frameCount]; for (int i = 0; i < frameCount; i++) { s.BaseStream.Position = startPos + frameOffsetTable[i]; WindowFrame frame = new WindowFrame(); frame.materialIndex = s.ReadUInt16(); frame.textureFlip = s.Read1Byte(); s.Align(4); // Padding frames[i] = frame; } }
public void Save(string path) { using (var fs = new FileStream(path, FileMode.Create)) using (var br = new BinaryStream(fs)) { br.WriteString(BGML.MAGIC, StringCoding.Raw); br.Position += 4; br.Position += 4; // Write File Size Later br.Position += 4; br.WriteInt32(Tracks.Count); br.WriteInt32(0x30); // We know its always at 0x30.. so just write anyway br.WriteInt32(Playlists.Count); br.Position += 4; // Offset write later br.Position = 0x30; // Step 1: Skip all way to the string table location so we can have proper string offsets // - Move to the Playlist Tree for now br.Position += 0x30 * Tracks.Count; // - Go to the end of the Playlist Tree br.Position += Playlists.Count * sizeof(uint); // - Playlist Tree is aligned br.Align(0x10, true); int[] playlistDataOffsets = new int[Playlists.Count]; // Will be used later on to write the tree // - Write Playlist Data along the way for (int i = 0; i < Playlists.Count; i++) { playlistDataOffsets[i] = (int)br.Position; br.Position += 0x10; // We're skipping the first int which is the string offset br.WriteInt32(Playlists[i].TrackIndexes.Count); foreach (var index in Playlists[i].TrackIndexes) { br.WriteInt32(index); } br.Align(0x10, true); } // Step 2: We reached the string table location, write the string tables OptimizedStringTable trackStringTable = SerializeTrackStringTable(); trackStringTable.SaveStream(br); OptimizedStringTable playlistStringTable = SerializePlaylistStringTable(); playlistStringTable.SaveStream(br); // Step 3: Populate the trees that reference the string tables for (int i = 0; i < Tracks.Count; i++) { br.Position = 0x30 + (i * 0x30); br.WriteInt32(trackStringTable.GetStringOffset(Tracks[i].Label)); br.WriteInt32((int)Tracks[i].Format); br.WriteInt32(trackStringTable.GetStringOffset(Tracks[i].FileName)); br.Position += 8; br.WriteInt32(trackStringTable.GetStringOffset(Tracks[i].TrackName)); br.WriteInt32(trackStringTable.GetStringOffset(Tracks[i].Artist)); br.WriteInt32(trackStringTable.GetStringOffset(Tracks[i].Genre)); br.Position += 0x10; } // Write the playlist data pointers int playlistTreeOffset = (int)br.Position; for (int i = 0; i < playlistDataOffsets.Length; i++) { br.WriteInt32(playlistDataOffsets[i]); } br.Align(0x10, true); // Write Playlist Label offsets for (int i = 0; i < Playlists.Count; i++) { br.Position = playlistDataOffsets[i]; // Using shortcut by using the precalculated offsets from earlier br.WriteInt32(playlistStringTable.GetStringOffset(Playlists[i].Name)); } // Finish up the header br.Position = 0x08; br.WriteInt32((int)br.Length); // File Size br.Position = 0x1C; br.WriteInt32(playlistTreeOffset); } }