2019-01-26 00:39:37 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
2019-02-01 17:19:20 +00:00
|
|
|
|
using RobloxFiles.BinaryFormat.Chunks;
|
|
|
|
|
|
|
|
|
|
namespace RobloxFiles.BinaryFormat
|
2019-01-26 00:39:37 +00:00
|
|
|
|
{
|
2019-05-19 04:44:51 +00:00
|
|
|
|
public class BinaryRobloxFile : RobloxFile
|
2019-01-26 00:39:37 +00:00
|
|
|
|
{
|
2019-01-29 09:50:55 +00:00
|
|
|
|
// Header Specific
|
|
|
|
|
public const string MagicHeader = "<roblox!\x89\xff\x0d\x0a\x1a\x0a";
|
|
|
|
|
|
|
|
|
|
public ushort Version;
|
|
|
|
|
public uint NumTypes;
|
|
|
|
|
public uint NumInstances;
|
|
|
|
|
public byte[] Reserved;
|
|
|
|
|
|
|
|
|
|
// Runtime Specific
|
2019-05-19 04:44:51 +00:00
|
|
|
|
public List<BinaryRobloxFileChunk> Chunks = new List<BinaryRobloxFileChunk>();
|
2019-01-29 09:50:55 +00:00
|
|
|
|
public override string ToString() => GetType().Name;
|
|
|
|
|
|
|
|
|
|
public Instance[] Instances;
|
|
|
|
|
public INST[] Types;
|
2019-05-17 06:14:04 +00:00
|
|
|
|
|
|
|
|
|
public Dictionary<string, string> Metadata;
|
|
|
|
|
public Dictionary<uint, string> SharedStrings;
|
2019-05-19 04:44:51 +00:00
|
|
|
|
|
|
|
|
|
internal BinaryRobloxFile()
|
|
|
|
|
{
|
|
|
|
|
Name = "BinaryRobloxFile";
|
|
|
|
|
ParentLocked = true;
|
|
|
|
|
}
|
2019-01-29 09:50:55 +00:00
|
|
|
|
|
2019-05-19 04:44:51 +00:00
|
|
|
|
protected override void ReadFile(byte[] contents)
|
2019-01-26 00:39:37 +00:00
|
|
|
|
{
|
|
|
|
|
using (MemoryStream file = new MemoryStream(contents))
|
2019-05-19 04:44:51 +00:00
|
|
|
|
using (BinaryRobloxFileReader reader = new BinaryRobloxFileReader(file))
|
2019-01-26 00:39:37 +00:00
|
|
|
|
{
|
2019-01-29 09:50:55 +00:00
|
|
|
|
// Verify the signature of the file.
|
2019-01-26 00:39:37 +00:00
|
|
|
|
byte[] binSignature = reader.ReadBytes(14);
|
|
|
|
|
string signature = Encoding.UTF7.GetString(binSignature);
|
|
|
|
|
|
2019-01-29 09:50:55 +00:00
|
|
|
|
if (signature != MagicHeader)
|
2019-01-30 06:36:56 +00:00
|
|
|
|
throw new InvalidDataException("Provided file's signature does not match BinaryRobloxFile.MagicHeader!");
|
2019-01-26 00:39:37 +00:00
|
|
|
|
|
2019-01-29 09:50:55 +00:00
|
|
|
|
// Read header data.
|
2019-01-26 00:39:37 +00:00
|
|
|
|
Version = reader.ReadUInt16();
|
|
|
|
|
NumTypes = reader.ReadUInt32();
|
|
|
|
|
NumInstances = reader.ReadUInt32();
|
2019-01-29 09:50:55 +00:00
|
|
|
|
Reserved = reader.ReadBytes(8);
|
2019-01-26 00:39:37 +00:00
|
|
|
|
|
|
|
|
|
// Begin reading the file chunks.
|
|
|
|
|
bool reading = true;
|
|
|
|
|
|
2019-01-29 09:50:55 +00:00
|
|
|
|
Types = new INST[NumTypes];
|
|
|
|
|
Instances = new Instance[NumInstances];
|
|
|
|
|
|
2019-01-26 00:39:37 +00:00
|
|
|
|
while (reading)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2019-05-19 04:44:51 +00:00
|
|
|
|
BinaryRobloxFileChunk chunk = new BinaryRobloxFileChunk(reader);
|
2019-01-29 09:50:55 +00:00
|
|
|
|
Chunks.Add(chunk);
|
2019-01-26 00:39:37 +00:00
|
|
|
|
|
|
|
|
|
switch (chunk.ChunkType)
|
|
|
|
|
{
|
|
|
|
|
case "INST":
|
2019-01-29 09:50:55 +00:00
|
|
|
|
INST type = new INST(chunk);
|
|
|
|
|
type.Allocate(this);
|
2019-01-26 00:39:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case "PROP":
|
2019-02-04 19:30:33 +00:00
|
|
|
|
PROP prop = new PROP(chunk);
|
|
|
|
|
prop.ReadProperties(this);
|
2019-01-26 00:39:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case "PRNT":
|
2019-01-30 06:36:56 +00:00
|
|
|
|
PRNT hierarchy = new PRNT(chunk);
|
|
|
|
|
hierarchy.Assemble(this);
|
2019-01-26 00:39:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case "META":
|
2019-05-17 06:14:04 +00:00
|
|
|
|
META meta = new META(chunk);
|
|
|
|
|
Metadata = meta.Data;
|
|
|
|
|
break;
|
|
|
|
|
case "SSTR":
|
|
|
|
|
SSTR shared = new SSTR(chunk);
|
|
|
|
|
SharedStrings = shared.Strings;
|
2019-01-26 00:39:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case "END\0":
|
|
|
|
|
reading = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2019-05-19 04:44:51 +00:00
|
|
|
|
Console.WriteLine("BinaryRobloxFile: Unhandled chunk type: {0}!", chunk.ChunkType);
|
2019-01-29 09:50:55 +00:00
|
|
|
|
Chunks.Remove(chunk);
|
2019-01-26 00:39:37 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (EndOfStreamException)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Unexpected end of file!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-17 12:08:06 +00:00
|
|
|
|
|
2019-05-19 04:44:51 +00:00
|
|
|
|
public override void Save(Stream stream)
|
2019-05-17 12:08:06 +00:00
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException("Not implemented yet!");
|
|
|
|
|
}
|
2019-01-26 00:39:37 +00:00
|
|
|
|
}
|
2019-01-30 06:36:56 +00:00
|
|
|
|
}
|