Brought spec up to date, improvements to stability

This commit is contained in:
CloneTrooper1019
2020-07-12 20:19:30 -05:00
parent 7359b6efb7
commit 57fd3f8a25
29 changed files with 551 additions and 245 deletions

View File

@ -16,7 +16,7 @@ namespace RobloxFiles.BinaryFormat.Chunks
public override string ToString() => ClassName;
public void LoadFromReader(BinaryRobloxFileReader reader)
public void Load(BinaryRobloxFileReader reader)
{
BinaryRobloxFile file = reader.File;
@ -59,10 +59,8 @@ namespace RobloxFiles.BinaryFormat.Chunks
file.Classes[ClassIndex] = this;
}
public BinaryRobloxFileChunk SaveAsChunk(BinaryRobloxFileWriter writer)
public void Save(BinaryRobloxFileWriter writer)
{
writer.StartWritingChunk(this);
writer.Write(ClassIndex);
writer.WriteString(ClassName);
@ -72,7 +70,7 @@ namespace RobloxFiles.BinaryFormat.Chunks
if (IsService)
{
BinaryRobloxFile file = writer.File;
var file = writer.File;
foreach (int instId in InstanceIds)
{
@ -80,8 +78,6 @@ namespace RobloxFiles.BinaryFormat.Chunks
writer.Write(service.Parent == file);
}
}
return writer.FinishWritingChunk();
}
}
}

View File

@ -6,7 +6,7 @@ namespace RobloxFiles.BinaryFormat.Chunks
{
public Dictionary<string, string> Data = new Dictionary<string, string>();
public void LoadFromReader(BinaryRobloxFileReader reader)
public void Load(BinaryRobloxFileReader reader)
{
BinaryRobloxFile file = reader.File;
int numEntries = reader.ReadInt32();
@ -21,18 +21,15 @@ namespace RobloxFiles.BinaryFormat.Chunks
file.META = this;
}
public BinaryRobloxFileChunk SaveAsChunk(BinaryRobloxFileWriter writer)
public void Save(BinaryRobloxFileWriter writer)
{
writer.StartWritingChunk(this);
writer.Write(Data.Count);
foreach (var kvPair in Data)
foreach (var pair in Data)
{
writer.WriteString(kvPair.Key);
writer.WriteString(kvPair.Value);
writer.WriteString(pair.Key);
writer.WriteString(pair.Value);
}
return writer.FinishWritingChunk();
}
}
}

View File

@ -1,29 +1,29 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace RobloxFiles.BinaryFormat.Chunks
{
public class PRNT : IBinaryFileChunk
{
public byte Format { get; private set; }
public int NumRelations { get; private set; }
private const byte FORMAT = 0;
public List<int> ChildrenIds { get; private set; }
public List<int> ParentIds { get; private set; }
public void LoadFromReader(BinaryRobloxFileReader reader)
public void Load(BinaryRobloxFileReader reader)
{
BinaryRobloxFile file = reader.File;
Format = reader.ReadByte();
NumRelations = reader.ReadInt32();
byte format = reader.ReadByte();
int idCount = reader.ReadInt32();
ChildrenIds = reader.ReadInstanceIds(NumRelations);
ParentIds = reader.ReadInstanceIds(NumRelations);
if (format != FORMAT)
throw new Exception($"Unexpected PRNT format: {format} (expected {FORMAT}!)");
var childIds = reader.ReadInstanceIds(idCount);
var parentIds = reader.ReadInstanceIds(idCount);
for (int i = 0; i < NumRelations; i++)
for (int i = 0; i < idCount; i++)
{
int childId = ChildrenIds[i];
int parentId = ParentIds[i];
int childId = childIds[i];
int parentId = parentIds[i];
Instance child = file.Instances[childId];
child.Parent = (parentId >= 0 ? file.Instances[parentId] : file);
@ -31,15 +31,13 @@ namespace RobloxFiles.BinaryFormat.Chunks
}
}
public BinaryRobloxFileChunk SaveAsChunk(BinaryRobloxFileWriter writer)
public void Save(BinaryRobloxFileWriter writer)
{
writer.StartWritingChunk(this);
var postInstances = writer.PostInstances;
var idCount = postInstances.Count;
Format = 0;
NumRelations = 0;
ChildrenIds = new List<int>();
ParentIds = new List<int>();
var childIds = new List<int>();
var parentIds = new List<int>();
foreach (Instance inst in writer.PostInstances)
{
@ -51,19 +49,15 @@ namespace RobloxFiles.BinaryFormat.Chunks
if (parent != null)
parentId = int.Parse(parent.Referent);
ChildrenIds.Add(childId);
ParentIds.Add(parentId);
NumRelations++;
childIds.Add(childId);
parentIds.Add(parentId);
}
writer.Write(Format);
writer.Write(NumRelations);
writer.Write(FORMAT);
writer.Write(idCount);
writer.WriteInstanceIds(ChildrenIds);
writer.WriteInstanceIds(ParentIds);
return writer.FinishWritingChunk();
writer.WriteInstanceIds(childIds);
writer.WriteInstanceIds(parentIds);
}
}
}

View File

@ -29,7 +29,7 @@ namespace RobloxFiles.BinaryFormat.Chunks
return $"{Type} {ClassName}.{Name}";
}
public void LoadFromReader(BinaryRobloxFileReader reader)
public void Load(BinaryRobloxFileReader reader)
{
BinaryRobloxFile file = reader.File;
@ -71,7 +71,6 @@ namespace RobloxFiles.BinaryFormat.Chunks
}
});
// Read the property data based on the property type.
switch (Type)
{
case PropertyType.String:
@ -500,13 +499,22 @@ namespace RobloxFiles.BinaryFormat.Chunks
readProperties(i =>
{
uint key = SharedKeys[i];
return file.SharedStrings[key];
});
break;
case PropertyType.ProtectedString:
readProperties(i =>
{
int length = reader.ReadInt32();
byte[] buffer = reader.ReadBytes(length);
return new ProtectedString(buffer);
});
break;
default:
Console.WriteLine("Unhandled property type: {0}!", Type);
Console.Error.WriteLine("Unhandled property type: {0}!", Type);
break;
//
}
@ -546,7 +554,7 @@ namespace RobloxFiles.BinaryFormat.Chunks
return propMap;
}
public BinaryRobloxFileChunk SaveAsChunk(BinaryRobloxFileWriter writer)
public void Save(BinaryRobloxFileWriter writer)
{
BinaryRobloxFile file = writer.File;
@ -567,9 +575,7 @@ namespace RobloxFiles.BinaryFormat.Chunks
props.Add(prop);
}
writer.StartWritingChunk(this);
writer.Write(ClassIndex);
writer.WriteString(Name);
writer.Write(TypeId);
@ -996,12 +1002,12 @@ namespace RobloxFiles.BinaryFormat.Chunks
props.ForEach(prop =>
{
SharedString shared = prop.CastValue<SharedString>();
string key = shared.MD5_Key;
var shared = prop.CastValue<SharedString>();
string key = shared.Key;
if (!sstr.Lookup.ContainsKey(key))
{
uint id = (uint)(sstr.NumHashes++);
uint id = (uint)(sstr.Lookup.Count);
sstr.Strings.Add(id, shared);
sstr.Lookup.Add(key, id);
}
@ -1012,10 +1018,19 @@ namespace RobloxFiles.BinaryFormat.Chunks
writer.WriteInterleaved(sharedKeys);
break;
//
case PropertyType.ProtectedString:
props.ForEach(prop =>
{
var protect = prop.CastValue<ProtectedString>();
byte[] buffer = protect.RawBuffer;
writer.Write(buffer.Length);
writer.Write(buffer);
});
break;
default: break;
}
return writer.FinishWritingChunk();
}
}
}

View File

@ -0,0 +1,56 @@
namespace RobloxFiles.BinaryFormat.Chunks
{
public struct Signature
{
public int Version;
public long Id;
public int Length;
public byte[] Data;
}
public class SIGN : IBinaryFileChunk
{
public Signature[] Signatures;
public void Load(BinaryRobloxFileReader reader)
{
int numSignatures = reader.ReadInt32();
Signatures = new Signature[numSignatures];
for (int i = 0; i < numSignatures; i++)
{
var signature = new Signature
{
Version = reader.ReadInt32(),
Id = reader.ReadInt64(),
Length = reader.ReadInt32(),
};
signature.Data = reader.ReadBytes(signature.Length);
Signatures[i] = signature;
}
var file = reader.File;
file.SIGN = this;
}
public void Save(BinaryRobloxFileWriter writer)
{
writer.Write(Signatures.Length);
for (int i = 0; i < Signatures.Length; i++)
{
var signature = Signatures[i];
signature.Length = signature.Data.Length;
writer.Write(signature.Version);
writer.Write(signature.Id);
writer.Write(signature.Length);
writer.Write(signature.Data);
}
}
}
}

View File

@ -6,56 +6,54 @@ namespace RobloxFiles.BinaryFormat.Chunks
{
public class SSTR : IBinaryFileChunk
{
public int Version;
public int NumHashes;
private const int FORMAT = 0;
public Dictionary<string, uint> Lookup = new Dictionary<string, uint>();
public Dictionary<uint, SharedString> Strings = new Dictionary<uint, SharedString>();
internal Dictionary<string, uint> Lookup = new Dictionary<string, uint>();
internal Dictionary<uint, SharedString> Strings = new Dictionary<uint, SharedString>();
public void LoadFromReader(BinaryRobloxFileReader reader)
public void Load(BinaryRobloxFileReader reader)
{
BinaryRobloxFile file = reader.File;
Version = reader.ReadInt32();
NumHashes = reader.ReadInt32();
int format = reader.ReadInt32();
int numHashes = reader.ReadInt32();
for (uint id = 0; id < NumHashes; id++)
if (format != FORMAT)
throw new Exception($"Unexpected SSTR format: {format} (expected {FORMAT}!)");
for (uint id = 0; id < numHashes; id++)
{
byte[] md5 = reader.ReadBytes(16);
int length = reader.ReadInt32();
byte[] data = reader.ReadBytes(length);
byte[] hash = reader.ReadBytes(16);
string key = Convert.ToBase64String(hash);
byte[] data = reader.ReadBuffer();
SharedString value = SharedString.FromBuffer(data);
Lookup.Add(value.MD5_Key, id);
Lookup.Add(key, id);
Strings.Add(id, value);
}
file.SSTR = this;
}
public BinaryRobloxFileChunk SaveAsChunk(BinaryRobloxFileWriter writer)
public void Save(BinaryRobloxFileWriter writer)
{
writer.StartWritingChunk(this);
writer.Write(Version);
writer.Write(NumHashes);
writer.Write(FORMAT);
writer.Write(Lookup.Count);
foreach (var pair in Lookup)
{
string key = pair.Key;
byte[] md5 = Convert.FromBase64String(key);
writer.Write(md5);
byte[] hash = Convert.FromBase64String(key);
writer.Write(hash);
SharedString value = Strings[pair.Value];
byte[] buffer = SharedString.FindRecord(value.MD5_Key);
byte[] buffer = SharedString.Find(value.Key);
writer.Write(buffer.Length);
writer.Write(buffer);
}
return writer.FinishWritingChunk();
}
}
}