Starting code for writing SerializedFiles

This commit is contained in:
Jeremy Pritts 2023-08-30 23:52:31 -04:00
parent 896131f828
commit 6ddb8cc2dd
2 changed files with 111 additions and 23 deletions

View File

@ -69,27 +69,6 @@ namespace AssetRipper.IO.Files.SerializedFiles.Parser
}
}
public void Write(Stream stream, SerializedFileHeader header)
{
bool swapEndianess = WriteSwapEndianess(stream, header);
EndianType endianess = swapEndianess ? EndianType.BigEndian : EndianType.LittleEndian;
using SerializedWriter writer = new SerializedWriter(stream, endianess, header.Version, UnityVersion);
Write(writer);
}
private bool WriteSwapEndianess(Stream stream, SerializedFileHeader header)
{
if (HasEndian(header.Version))
{
stream.WriteByte(SwapEndianess ? (byte)1 : (byte)0);
return SwapEndianess;
}
else
{
return header.Endianess;
}
}
private void Read(SerializedReader reader)
{
if (HasSignature(reader.Generation))
@ -144,8 +123,12 @@ namespace AssetRipper.IO.Files.SerializedFiles.Parser
}
}
private void Write(SerializedWriter writer)
public void Write(SerializedWriter writer)
{
if (HasEndian(writer.Generation))
{
writer.Write(writer.EndianType == EndianType.BigEndian ? (byte)1 : (byte)0);
}
if (HasSignature(writer.Generation))
{
writer.WriteStringZeroTerm(UnityVersion.ToString());

View File

@ -1,5 +1,6 @@
using AssetRipper.IO.Endian;
using AssetRipper.IO.Files.Converters;
using AssetRipper.IO.Files.SerializedFiles.IO;
using AssetRipper.IO.Files.SerializedFiles.Parser;
using AssetRipper.IO.Files.Streams.Smart;
using AssetRipper.IO.Files.Utils;
@ -118,7 +119,111 @@ namespace AssetRipper.IO.Files.SerializedFiles
public override void Write(Stream stream)
{
throw new NotImplementedException();
long initialPosition = stream.Position;
using SerializedWriter writer = new(stream, EndianType, Generation, Version);
SerializedFileHeader header = new()
{
Version = Generation,
Endianess = EndianType == EndianType.BigEndian,
};
header.Write(writer);
SerializedFileMetadata metadata = new()
{
UnityVersion = Version,
TargetPlatform = Platform,
Externals = m_dependencies ?? Array.Empty<FileIdentifier>(),
Object = GetNewObjectInfoArray(m_objects),
Types = m_types ?? Array.Empty<SerializedType>(),
RefTypes = m_refTypes ?? Array.Empty<SerializedTypeReference>(),
EnableTypeTree = HasTypeTree,
};
long metadataPosition;
long metadataSize;
long objectDataPosition;
if (SerializedFileMetadata.IsMetadataAtTheEnd(Generation))
{
metadataPosition = stream.Position;
metadata.Write(writer);
metadataSize = stream.Position - metadataPosition;
AlignStream(writer);//Object data must always be aligned.
objectDataPosition = stream.Position;
WriteObjectData(writer, metadata.Object);
}
else
{
AlignStream(writer);//Object data must always be aligned.
objectDataPosition = stream.Position;
WriteObjectData(writer, metadata.Object);
metadataPosition = stream.Position;
metadata.Write(writer);
metadataSize = stream.Position - metadataPosition;
}
long finalPosition = stream.Position;
stream.Position = initialPosition;
header.FileSize = finalPosition - initialPosition;
header.MetadataSize = metadataSize;
header.DataOffset = objectDataPosition - initialPosition;
header.Write(writer);
stream.Position = finalPosition;
static void WriteObjectData(SerializedWriter writer, ObjectInfo[] objects)
{
foreach (ObjectInfo objectInfo in objects)
{
writer.Write(objectInfo.ObjectData);
AlignStream(writer);
}
}
static ObjectInfo[] GetNewObjectInfoArray(ObjectInfo[]? objects)
{
if (objects is null)
{
return Array.Empty<ObjectInfo>();
}
ObjectInfo[] newObjects = new ObjectInfo[objects.Length];
//This doesn't work correctly because ObjectInfo is not a struct, but that can be fixed later.
Array.Copy(objects, newObjects, objects.Length);
long byteStart = 0;
for (int i = 0; i < newObjects.Length; i++)
{
ObjectInfo objectInfo = newObjects[i];
objectInfo.ByteStart = byteStart;
objectInfo.ByteSize = objectInfo.ObjectData.Length;
newObjects[i] = objectInfo;
byteStart += objectInfo.ByteSize;
byteStart += 3 - (byteStart % 4);//Object data must always be aligned.
}
return newObjects;
}
static void AlignStream(SerializedWriter writer)
{
switch (writer.BaseStream.Position % 4)
{
case 1:
writer.Write((byte)0);
writer.Write((byte)0);
writer.Write((byte)0);
break;
case 2:
writer.Write((byte)0);
writer.Write((byte)0);
break;
case 3:
writer.Write((byte)0);
break;
}
}
}
public static SerializedFile FromFile(string filePath)