예제 #1
0
        public void LoadBinary(string filename)
        {
            using (var stream = new BinaryStream(filename))
            {
                Debug.WriteLine(">> Reading FCB header...");
                var magic = stream.ReadInt32();

                if (magic != Magic)
                {
                    throw new InvalidOperationException("Bad magic, no FCB data to parse!");
                }

                var type = stream.ReadInt16();

                if (type != Type)
                {
                    throw new InvalidOperationException("FCB library reported the incorrect type?!");
                }

                stream.Position += 2; // ;)

                var objCount  = stream.ReadInt32();
                var attrCount = stream.ReadInt32();

                // read fcb data
                Debug.WriteLine(">> Reading objects...");

                var objRefs = new List <NodeObject>();
                Root = new NodeObject(stream, objRefs);

                Console.WriteLine($"Finished reading {Root.Children.Count} objects. Collected {objRefs.Count} nodes in total.");
            }
        }
예제 #2
0
 public void Deserialize(BinaryStream input)
 {
     LastSortedCRC    = input.ReadInt32();
     CompressedSize   = input.ReadInt32();
     DecompressedSize = input.ReadInt32();
     CompressedBytes  = input.ReadBytes(CompressedSize);
 }
예제 #3
0
        protected NomadObject ReadMapData(BinaryStream stream)
        {
            var check = stream.ReadInt32();

            var result = new NomadObject()
            {
                Id = "FCXMapData"
            };

            if (check != 0x26)
            {
                // non-editor map?
                stream.Position -= 4;

                UID = stream.Read <Guid>();
                ReadPadding(stream, 1);

                Version   = 0;
                IsUserMap = false;
            }
            else
            {
                var magic = stream.ReadInt32();

                if (magic != MGX_MAPDATA)
                {
                    throw new InvalidDataException("Invalid FCX map data -- bad data magic!");
                }

                Version   = check;
                IsUserMap = true;

                ReadPadding(stream, 3);

                MetaData   = ReadFCBChunk(stream, result);
                ConfigData = ReadFCBChunk(stream, result);

                ReadPadding(stream, 5);

                var thumbSize = stream.ReadInt32();

                if (thumbSize > 0)
                {
                    ThumbData = stream.ReadBytes(thumbSize);
                }

                ReadPadding(stream, 1);
            }

            var mapSize = (int)(stream.Length - stream.Position);

            MapData = stream.ReadBytes(mapSize);

            return(result);
        }
예제 #4
0
                public void Deserialize(BinaryStream input, int nameCRC)
                {
                    Id      = input.ReadInt32();
                    Section = input.ReadInt32();

                    if (Section != nameCRC)
                    {
                        throw new FormatException("oasis string section CRC does not match the section's CRC value.");
                    }

                    Enum = input.ReadInt32();
                }
예제 #5
0
        public void Deserialize(BinaryStream stream)
        {
            var baseOffset = stream.Position;

            var magic = stream.ReadInt32();

            if (magic != Signature)
            {
                throw new FormatException();
            }

            Version = stream.ReadInt32();

            if (Version != 1)
            {
                throw new FormatException();
            }

            uint offsetData       = stream.ReadUInt32();
            uint offsetHeader     = stream.ReadUInt32();
            uint offsetDescriptor = stream.ReadUInt32();

            if (offsetData != 20)
            {
                throw new FormatException();
            }

            Data = new FCXCompressedData();
            Data.Deserialize(stream);

            if (baseOffset + offsetHeader != stream.Position)
            {
                throw new FormatException();
            }

            Header = new FCXCompressedData();
            Header.Deserialize(stream);

            if (baseOffset + offsetDescriptor != stream.Position)
            {
                throw new FormatException();
            }

            Descriptor = new FCXCompressedData();
            Descriptor.Deserialize(stream);
        }
예제 #6
0
        public void Deserialize(BinaryStream stream)
        {
            var offset = stream.ReadInt32();
            var length = offset - 4;

            Data = new byte[length];

            if (stream.Read(Data, 0, length) != length)
            {
                throw new FormatException();
            }

            var blockCount = stream.ReadInt32();

            Blocks = new List <Block>();

            for (int i = 0; i < blockCount; i++)
            {
                var block = new Block()
                {
                    VirtualOffset = stream.ReadUInt32(),
                    FileOffset    = stream.ReadUInt32(),
                };

                block.IsCompressed = (block.FileOffset & 0x80000000) != 0;
                block.FileOffset  &= 0x7FFFFFFF;

                Blocks.Add(block);
            }

            if (Blocks.Count == 0)
            {
                throw new FormatException();
            }

            if (Blocks.First().FileOffset != 4)
            {
                throw new FormatException();
            }

            if (Blocks.Last().FileOffset != (4 + length))
            {
                throw new FormatException();
            }
        }
예제 #7
0
        protected NomadValue ReadAttribute_FmtA(BinaryStream stream, NomadObject parent)
        {
            Context.State = ContextStateType.Member;
            Context.MemberIndex++;

            var hash = stream.ReadInt32();

            return(ReadAttributeData(stream, parent, hash));
        }
예제 #8
0
                public void Deserialize(BinaryStream input)
                {
                    StringCount = input.ReadInt32();

                    SortedEnums   = new List <int>(StringCount);
                    StringOffsets = new List <int>(StringCount);
                    IdValuePairs  = new List <KeyValuePair <int, string> >(StringCount);

                    //
                    // SortedEnums
                    //
                    for (int i = 0; i < StringCount; i++)
                    {
                        var val = input.ReadInt32();

                        SortedEnums.Add(val);
                    }

                    //
                    // StringOffsets
                    //
                    for (int j = 0; j < StringCount; j++)
                    {
                        var val = input.ReadInt32();

                        StringOffsets.Add(val);
                    }

                    //
                    // IdValuePairs
                    //
                    for (int k = 0; k < StringCount; k++)
                    {
                        var id  = input.ReadInt32();
                        var str = input.ReadString(Encoding.Unicode);

                        var kv = new KeyValuePair <int, string>(id, str);

                        IdValuePairs.Add(kv);
                    }
                }
예제 #9
0
        protected void ReadPadding(BinaryStream stream, int count)
        {
            for (int i = 0; i < count; i++)
            {
                var value = stream.ReadInt32();

                if (value != 0)
                {
                    throw new InvalidDataException($"Expected padding but got '{value:X8}' instead!");
                }
            }
        }
예제 #10
0
        public void Deserialize(BinaryStream input)
        {
            var type = input.ReadInt32();

            if (type != 1)
            {
                throw new FormatException("not an oasisstrings_compressed.bin file");
            }

            var count = input.ReadInt32();

            Sections = new List <OasisSection>(count);

            for (int i = 0; i < count; i++)
            {
                var section = new OasisSection();
                section.Deserialize(input);

                Sections.Add(section);
            }
        }
예제 #11
0
            public void Deserialize(BinaryStream input)
            {
                Name        = input.ReadInt32();
                StringCount = input.ReadInt32();

                for (int i = 0; i < StringCount; i++)
                {
                    var locStr = new OasisLocalizedString();
                    locStr.Deserialize(input, Name);

                    LocalizedStrings.Add(locStr);
                }

                CompressedValuesSectionsCount = input.ReadInt32();

                for (int i = 0; i < CompressedValuesSectionsCount; i++)
                {
                    var cpr = new CompressedValues();
                    cpr.Deserialize(input);

                    var lz  = new LZ4Decompressor64();
                    var buf = new byte[cpr.DecompressedSize];

                    lz.DecompressKnownSize(cpr.CompressedBytes, buf, cpr.DecompressedSize);

                    var dCpr = new DecompressedValues();

                    using (var bs = new BinaryStream(buf))
                        dCpr.Deserialize(bs);

                    foreach (var kv in dCpr.IdValuePairs)
                    {
                        var id    = kv.Key;
                        var value = kv.Value;

                        OasisStringLookup.SetString(id, value);
                    }
                }
            }
예제 #12
0
        public void Deserialize(BinaryStream stream)
        {
            Debug.WriteLine(">> Reading FCB header...");
            var magic = stream.ReadInt32();

            if (magic != Magic)
            {
                throw new InvalidOperationException("Bad magic, no FCB data to parse!");
            }

            Type = (ContainerType)stream.ReadInt16();

            stream.Position += 2; // ;)

            var totalCount = stream.ReadInt32();
            var nodesCount = stream.ReadInt32();

            // read fcb data
            switch (Type)
            {
            case ContainerType.Objects:
            {
                Debug.WriteLine(">> Reading objects...");

                var objRefs = new List <NodeObject>();
                Root = new NodeObject(stream, objRefs);
            }
            break;

            case ContainerType.Classes:
            {
                Debug.WriteLine(">> Reading classes...");
                Root = new NodeClass(stream);
            }
            break;
            }
        }
예제 #13
0
        public void Deserialize(BinaryStream stream)
        {
            if (Use32Bit)
            {
                UID = stream.ReadUInt32();
            }
            else
            {
                UID = stream.ReadInt64();
            }

            Offset     = stream.ReadInt32() + 8;
            TotalCount = stream.ReadUInt16();
            NodesCount = stream.ReadUInt16();
        }
예제 #14
0
        public XElement CreateXmlElement(NomadObject obj, XElement parent = null)
        {
            Context.State = ContextStateType.Object;
            Context.ObjectIndex++;

            var name = XName.Get(obj.Id);
            var elem = new XElement(name);

            if (parent != null)
            {
                parent.Add(elem);
            }

            foreach (var attr in obj.Attributes)
            {
                if (attr.Id == "RML_DATA")
                {
                    using (var bs = new BinaryStream(attr.Data.Buffer))
                    {
                        var rmlSize   = bs.ReadInt32();
                        var rmlBuffer = bs.ReadBytes(rmlSize);

                        using (var rs = new BinaryStream(rmlBuffer))
                        {
                            var rmlData = new NomadRmlSerializer();
                            var rml     = rmlData.Deserialize(rs);

                            var rmlRoot = new XElement("RML_DATA");
                            var rmlElem = CreateXmlElement(rml, rmlRoot);

                            elem.Add(rmlRoot);
                        }
                    }
                }
                else
                {
                    CreateXmlAttribute(attr, elem);
                }
            }

            foreach (var child in obj.Children)
            {
                CreateXmlElement(child, elem);
            }

            return(elem);
        }
예제 #15
0
        protected NomadObject ReadFCBChunk(BinaryStream stream, NomadObject parent)
        {
            var fcbSize = stream.ReadInt32();
            var fcbData = stream.ReadBytes(fcbSize);

            using (var bs = new BinaryStream(fcbData))
            {
                var serializer = new NomadResourceSerializer();
                var root       = serializer.Deserialize(bs);

                if (parent != null)
                {
                    parent.Children.Add(root);
                }

                return(root);
            }
        }
예제 #16
0
        public void Deserialize(BinaryStream stream, bool readHash)
        {
            if (readHash)
            {
                var hash = stream.ReadInt32();

                var name = StringHasher.ResolveHash(hash);
                var type = AttributeTypes.GetType(hash);

                // cannot be null or contain spaces
                var nameResolved = ((name != null) && !name.Contains(" "));

                if (nameResolved)
                {
                    Name = name;
                }
                else
                {
                    Hash = hash;
                }

                // try resolving the full name, e.g. 'Class.bProperty'
                var fullHash = StringHasher.GetHash(FullName);

                if (fullHash != hash)
                {
                    if (AttributeTypes.IsTypeKnown(fullHash))
                    {
                        type = AttributeTypes.GetType(fullHash);
                    }
                }

                Data = new AttributeData(type);
            }
            else
            {
                Deserialize(stream);
            }
        }
예제 #17
0
        public static DescriptorTag Read(BinaryStream stream, ReferenceType refType = ReferenceType.None)
        {
            var ptr = (int)stream.Position;

            var value = stream.ReadByte();
            var type  = GetDescriptorType(value);

            if ((type == DescriptorType.Reference) && (refType == ReferenceType.None))
            {
                throw new InvalidOperationException("ID:10T error while reading a descriptor -- consumed a reference with no type defined!");
            }

            var isOffset = (type == DescriptorType.Reference) &&
                           (refType == ReferenceType.Offset);

            if (type != DescriptorType.None)
            {
                if (GlobalFlags.HasFlag(DescriptorFlags.Use24Bit))
                {
                    // move back
                    stream.Position -= 1;

                    // read in value without control code
                    value = (int)(stream.ReadUInt32() >> 8);
                }
                else
                {
                    value = stream.ReadInt32();
                }

                if (isOffset)
                {
                    // make offset absolute
                    value = (ptr - value);
                }
            }

            return(new DescriptorTag(value, type, refType));
        }
예제 #18
0
        public override void Deserialize(BinaryStream stream)
        {
            var ptr = (int)stream.Position;

            var nD = DescriptorTag.Read(stream, ReferenceType.Offset);

            if (nD.IsOffset)
            {
                stream.Position = nD.Value;
                Deserialize(stream);

                stream.Position = (ptr + nD.Size);
            }
            else
            {
                Offset = ptr;

                var nChildren = nD.Value;

                Children = new List <NodeClass>(nChildren);

                var hash = stream.ReadInt32();
                var size = stream.ReadInt16();

                var name = StringHasher.ResolveHash(hash);

                if (name != null)
                {
                    Name = name;
                }
                else
                {
                    Hash = hash;
                }

                var attrsPtr = (int)stream.Position;
                var next     = (attrsPtr + size);

                if (size != 0)
                {
                    var nhD = DescriptorTag.Read(stream, ReferenceType.Offset);

                    var adjustPtr = false;

                    if (nhD.IsOffset)
                    {
                        stream.Position = nhD.Value;

                        // read again
                        nhD = DescriptorTag.Read(stream, ReferenceType.Offset);

                        if (nhD.IsOffset)
                        {
                            throw new InvalidOperationException("Cannot have nested offsets!");
                        }

                        // adjust ptr to attributes
                        attrsPtr += nhD.Size;
                        adjustPtr = true;
                    }

                    var nAttrs = nhD.Value;

                    Attributes = new List <NodeAttribute>(nAttrs);

                    for (int i = 0; i < nAttrs; i++)
                    {
                        var attr = new NodeAttribute(stream, Name);
                        Attributes.Add(attr);
                    }

                    // move to the attributes if needed
                    if (adjustPtr)
                    {
                        stream.Position = attrsPtr;
                    }

                    // deserialize attribute data
                    foreach (var attr in Attributes)
                    {
                        attr.Deserialize(stream);
                    }
                }
                else
                {
                    throw new NotImplementedException("Zero-length nodes are not covered under TrumpCare™.");
                }

                if (stream.Position != next)
                {
                    throw new InvalidOperationException("You dun f****d up, son!");
                }

                // read children
                for (int n = 0; n < nChildren; n++)
                {
                    var child = new NodeClass(stream);
                    Children.Add(child);
                }
            }
        }
예제 #19
0
        protected NomadObject ReadObject_FmtA(BinaryStream stream, NomadObject parent = null)
        {
            Context.State = ContextStateType.Object;
            Context.ObjectIndex++;

            var ptr       = (int)stream.Position;
            var nChildren = DescriptorTag.Read(stream, ReferenceType.Index);

            if (nChildren.Type == DescriptorType.Reference)
            {
                throw new InvalidOperationException("Cannot deserialize an object reference directly!");
            }

            var hash = stream.ReadInt32();
            var id   = StringId.Parse(hash);

            var result = new NomadObject(id);

            Context.AddRef(result, ptr);

            if (result.IsRml)
            {
                var next = DescriptorTag.Read(stream, ReferenceType.Index);

                var rmlBase = (int)stream.Position;

                var rmlSize   = stream.ReadInt32();
                var rmlBuffer = stream.ReadBytes(rmlSize);

                using (var bs = new BinaryStream(rmlBuffer))
                {
                    var rmlData = new NomadRmlSerializer();
                    var rml     = rmlData.Deserialize(bs);

                    result.Children.Add(rml);
                }

                stream.Position = (rmlBase + next);
            }
            else
            {
                var nAttrs = DescriptorTag.Read(stream, ReferenceType.Index);

                for (int i = 0; i < nAttrs; i++)
                {
                    ReadAttribute_FmtA(stream, result);
                }

                for (int i = 0; i < nChildren; i++)
                {
                    var cP = (int)stream.Position;
                    var cD = DescriptorTag.Read(stream, ReferenceType.Index);

                    // rip
                    if (cD.IsIndex)
                    {
                        var idx      = cD.Value;
                        var childRef = Context.GetRefByIdx(idx) as NomadObject;

                        result.Children.Add(childRef);
                    }
                    else
                    {
                        // move back
                        stream.Position = cP;

                        ReadObject_FmtA(stream, result);
                    }
                }
            }

            if (parent != null)
            {
                parent.Children.Add(result);
            }

            return(result);
        }
예제 #20
0
        protected NomadObject ReadObject_FmtB(BinaryStream stream, NomadObject parent = null)
        {
            Context.State = ContextStateType.Object;
            Context.ObjectIndex++;

            var ptr = (int)stream.Position;

            var nD = DescriptorTag.Read(stream, ReferenceType.Offset);

            NomadObject result = null;

            if (nD.IsOffset)
            {
                result = Context.GetRefByPtr(nD.Value) as NomadObject;

                // this should never happen
                if (result == null)
                {
                    throw new InvalidDataException("Malformed data!");
                }
            }
            else
            {
                var nChildren = nD.Value;

                var hash = stream.ReadInt32();
                var size = stream.ReadInt16();

                if (size == 0)
                {
                    throw new NotImplementedException("Zero-length nodes are not covered under TrumpCare(tm).");
                }

                var id = StringId.Parse(hash);

                result = new NomadObject(id);

                Context.AddRef(result, ptr);

                var attrsPtr = (int)stream.Position;
                var next     = (attrsPtr + size);

                var nhD = DescriptorTag.Read(stream, ReferenceType.Offset);

                var adjustPtr = false;

                if (nhD.IsOffset)
                {
                    stream.Position = nhD.Value;

                    // adjust ptr to attributes
                    attrsPtr += nhD.Size;
                    adjustPtr = true;

                    // read again
                    nhD = DescriptorTag.Read(stream, ReferenceType.Offset);

                    if (nhD.IsOffset)
                    {
                        throw new InvalidOperationException("Cannot have nested offsets!");
                    }
                }

                var nAttrs = nhD.Value;
                var hashes = new int[nAttrs];

                // read attribute hash list
                for (int i = 0; i < nAttrs; i++)
                {
                    hashes[i] = stream.ReadInt32();
                }

                // move to the attributes if needed
                if (adjustPtr)
                {
                    stream.Position = attrsPtr;
                }

                // deserialize attributes
                if (nAttrs > 0)
                {
                    ReadAttributes_FmtB(stream, result, hashes);
                }

                if (stream.Position != next)
                {
                    Context.LogDebug($"Something went wrong when reading attributes for '{result.Id}':");
                    Context.LogDebug($" - Expected to read {size} bytes but only read {stream.Position - attrsPtr}");

                    foreach (var attr in result.Attributes)
                    {
                        Context.LogDebug($" - '{attr.Id}' : {attr.Data.Type} ({attr.Data.Size} bytes)");
                    }

                    stream.Position = next;
                }

                // read children
                for (int n = 0; n < nChildren; n++)
                {
                    ReadObject_FmtB(stream, result);
                }
            }

            if (parent != null)
            {
                parent.Children.Add(result);
            }

            return(result);
        }
예제 #21
0
 public void Deserialize(BinaryStream stream)
 {
     Offset     = stream.ReadInt32();
     TotalCount = stream.ReadUInt16();
     ChildCount = stream.ReadUInt16();
 }
예제 #22
0
        public void LoadBinary(string filename)
        {
            using (var stream = new BinaryStream(filename))
            {
                Debug.WriteLine(">> Reading infos header...");
                var infosOffset = stream.ReadInt32();
                var infosCount  = stream.ReadInt32();

                Use32Bit = ((stream.Length - (infosCount * 0xC)) == infosOffset);

                Debug.WriteLine(">> Reading FCB header...");
                var magic = stream.ReadInt32();

                if (magic != Magic)
                {
                    throw new InvalidOperationException("Bad magic, no FCB data to parse!");
                }

                var type = stream.ReadInt16();

                if (type != Type)
                {
                    throw new InvalidOperationException("FCB library reported the incorrect type?!");
                }

                stream.Position += 2;                // ;)

                var totalCount = stream.ReadInt32(); // * 3
                var nodesCount = stream.ReadInt32(); // * 4

                var dataOffset = (int)stream.Position;

                var memSize      = ((totalCount * 3) + nodesCount) * 4;
                var memSizeAlign = Memory.Align(memSize, 16);

#if DEBUG
                Console.WriteLine("[Library.Header]");
                Console.WriteLine($"  Total: {totalCount}");
                Console.WriteLine($"  Nodes: {nodesCount}");
                Console.WriteLine($"  MemSize: {memSize:X8}");
#endif

                // read the infos first!
                Debug.WriteLine(">> Reading infos...");
                stream.Position = infosOffset;

                var nInfosTotal = 0;
                var nInfosNodes = 0;

                var refDatas = new Dictionary <int, EntityReferenceData>(infosCount);

                for (int i = 0; i < infosCount; i++)
                {
                    var refData = new EntityReferenceData(stream, Use32Bit);

                    nInfosTotal += refData.TotalCount;
                    nInfosNodes += refData.NodesCount;

                    refDatas.Add(refData.Offset, refData);
                }

                var count1Diff = (totalCount - nInfosTotal);
                var count2Diff = (nodesCount - nInfosNodes);

#if DEBUG
                Console.WriteLine("[Library.Infos]");
                Console.WriteLine($"  Total: {nInfosTotal}");
                Console.WriteLine($"  Nodes: {nInfosNodes}");
                Console.WriteLine("[Library.Logging]");
                Console.WriteLine($"  TotalDiff: {count1Diff}");
                Console.WriteLine($"  NodesDiff: {count2Diff}");
#endif

                // read fcb data
                Debug.WriteLine(">> Reading libraries...");
                stream.Position = dataOffset;

                var root = new NodeClass(stream);

                Libraries = new List <EntityLibrary>(root.Children.Count);

                foreach (var library in root.Children)
                {
                    // deserialize from the class
                    var lib = new EntityLibrary()
                    {
                        Use32Bit = Use32Bit,
                    };

                    lib.Deserialize(library);

                    // update UIDs
                    foreach (var entry in lib.Entries)
                    {
                        var node   = entry.GroupNode;
                        var offset = node.Offset;

                        if (refDatas.ContainsKey(offset))
                        {
                            var entRef = refDatas[offset];
                            entry.UID = entRef.UID;
                        }
                    }

                    Libraries.Add(lib);
                }

                Console.WriteLine($"Finished reading {Libraries.Count} libraries. Collected {Utils.GetTotalNumberOfNodes(root)} nodes in total.");
            }
        }
예제 #23
0
        public void Deserialize(BinaryStream stream, List <NodeObject> objRefs)
        {
            Offset = (int)stream.Position;

            // define reference type just in case we f**k up somehow
            var nD = DescriptorTag.Read(stream, ReferenceType.Index);

            if (nD.Type == DescriptorType.Reference)
            {
                throw new InvalidOperationException("Cannot deserialize an object reference directly!");
            }

            var nChildren = nD.Value;

            Children = new List <NodeObject>(nChildren);

            var hash = stream.ReadInt32();
            var name = StringHasher.ResolveHash(hash);

            if (name != null)
            {
                Name = name;
            }
            else
            {
                Hash = hash;
            }

            // add a reference to this object
            objRefs.Add(this);

            var aD     = DescriptorTag.Read(stream, ReferenceType.Index);
            var nAttrs = aD.Value;

            Attributes = new List <NodeAttribute>(nAttrs);

            if (nAttrs > 0)
            {
                for (int i = 0; i < nAttrs; i++)
                {
                    // hash and data inline
                    var attr = new NodeAttribute(stream, Name);
                    attr.Deserialize(stream);

                    Attributes.Add(attr);
                }
            }

            if (nChildren > 0)
            {
                // read children
                for (int n = 0; n < nChildren; n++)
                {
                    var cP = (int)stream.Position;
                    var cD = DescriptorTag.Read(stream, ReferenceType.Index);

                    // rip
                    if (cD.IsIndex)
                    {
                        var idx      = cD.Value;
                        var childRef = objRefs[idx];

                        Children.Add(childRef);
                    }
                    else
                    {
                        // move back
                        stream.Position = cP;

                        var child = new NodeObject(stream, objRefs);
                        Children.Add(child);
                    }
                }
            }
        }