public virtual void Save(Stream fs) { var writer = new BinaryWriter(fs, Encoding.UTF8); writer.Write(Signature | (Version << 24)); // Tiles int i, count = Tiles.Count; // Two generic ints we reuse writer.Write(count); for (i = 0; i < count; ++i) { Tiles[i].Write(writer); } // Blocks count = Blocks.Count; writer.Write(count); for (i = 0; i < count; ++i) { Blocks[i].Write(writer); } // Layers uint i2, i3; writer.Write(RowCount); writer.Write(ColumnCount); WriteLayer(background); WriteLayer(foreground); // Sub-Methods void WriteLayer(byte[,] layer) { // We're going to write a byte array called presentRows, with each bit // representing whether the corresponding layer is present in the file. long pos = fs.Position; byte presentRowsBitIndex = 0; i = 0; uint presentRowsLen = Bitwise.GetRequiredBytes(RowCount); var presentRows = new byte[presentRowsLen]; writer.Write(presentRows); for (i2 = 0; i2 < RowCount; ++i2) { // Do a very basic cutoff check to avoid writing tons of nulls uint columnCount = 0; for (i3 = 0; i3 < ColumnCount; ++i3) { if (layer[i2, i3] != 0) { columnCount = i3 + 1; } } if (columnCount != 0) { // Set the appropriate bit stating this row is present presentRows[i] |= (byte)(0x80 >> presentRowsBitIndex); // Write the block indices that make up the column writer.Write(columnCount); for (i3 = 0; i3 < columnCount; ++i3) { writer.Write(layer[i2, i3]); } } if (++presentRowsBitIndex > 7) { presentRowsBitIndex = 0; ++i; } } // Write presentRows long pos2 = fs.Position; fs.Position = pos; writer.Write(presentRows); fs.Position = pos2; } }
public virtual void Load(Stream fs) { var reader = new BinaryReader(fs, Encoding.UTF8); uint sig = reader.ReadUInt32(); byte ver = (byte)((sig & 0xFF000000) >> 24); sig &= 0xFFFFFF; if (sig != Signature) { throw new InvalidDataException( "The given file is not a valid SoniC# stage!"); } if (ver > Version) { throw new NotImplementedException( $"The given SoniC# stage is of an unsupported version (v{ver})!"); } // Tiles int i, count; // Two generic ints we reuse count = reader.ReadInt32(); Tiles.Clear(); for (i = 0; i < count; ++i) { Tiles.Add(new Tile(i, TileMap, reader)); } // Blocks count = reader.ReadInt32(); Blocks.Clear(); for (i = 0; i < count; ++i) { Blocks.Add(new Block(reader)); } // Layers uint i2, i3; uint rowCount = reader.ReadUInt32(); uint columnCount = reader.ReadUInt32(); if (rowCount != RowCount || columnCount != ColumnCount) { background = new byte[rowCount, columnCount]; foreground = new byte[rowCount, columnCount]; } ReadLayer(background); ReadLayer(foreground); // Sub-Methods void ReadLayer(byte[,] layer) { // Read the list of rows present in the file uint presentRowsLen = Bitwise.GetRequiredBytes(rowCount); var presentRows = reader.ReadBytes((int)presentRowsLen); byte presentRowsBitIndex = 0; i = 0; // Read each row for (i2 = 0; i2 < rowCount; ++i2) { // Read each column if the row it belongs to is present in the file if ((presentRows[i] & (0x80 >> presentRowsBitIndex)) != 0) { columnCount = reader.ReadUInt32(); for (i3 = 0; i3 < columnCount; ++i3) { layer[i2, i3] = reader.ReadByte(); } } if (++presentRowsBitIndex > 7) { presentRowsBitIndex = 0; ++i; } } } }