예제 #1
0
        public byte[] Unpack()
        {
            var memory = new BinaryStream(1024);

            using (var bs = new BinaryStream(Data))
            {
                for (int i = 1; i < Blocks.Count; i++)
                {
                    var block = Blocks[i - 1];
                    var next  = Blocks[i];

                    var size = (int)(next.VirtualOffset - block.VirtualOffset);

                    bs.Seek(block.FileOffset - 4, SeekOrigin.Begin);

                    memory.Seek(block.VirtualOffset, SeekOrigin.Begin);

                    if (block.IsCompressed == true)
                    {
                        var zlib = new InflaterInputStream(bs);
                        zlib.CopyTo(memory);
                    }
                    else
                    {
                        var buffer = bs.ReadBytes(size);

                        memory.Write(buffer, 0, size);
                    }
                }
            }

            return(memory.ToArray());
        }
예제 #2
0
        protected bool WriteAttributesList_FmtB(BinaryStream stream, NomadObject obj)
        {
            var ptr = (int)stream.Position;

            byte[] buffer = new byte[0];

            using (var bs = new BinaryStream(1024))
            {
                WriteAttributesData_FmtB(bs, obj.Attributes, ptr);
                buffer = bs.ToArray();
            }

            var length = buffer.Length;

            if (length > 65535)
            {
                throw new InvalidOperationException("Attribute data too large.");
            }

            stream.Write((short)length);
            stream.Write(buffer, 0, length);

            // did we write any data?
            return(length > 0);
        }
예제 #3
0
        public override void Serialize(Stream stream, NomadObject _unused)
        {
            Context.Begin();

            var bs = (stream as BinaryStream)
                     ?? new BinaryStream(stream);

            byte[] buffer = null;

            using (var nb = new BinaryStream(1024))
            {
                base.Serialize(nb, Root);
                buffer = nb.ToArray();
            }

            var count = Prototypes.Count;

            bs.Write(buffer.Length + 8);
            bs.Write(count);

            bs.Write(buffer);

            // todo: prototype entries
            Context.Log("Writing prototypes...");
            foreach (var kv in Prototypes)
            {
                var uid = kv.Key;
                var obj = kv.Value;

                // fail-safe
                var reference = new NomadReference(obj);
                var cached    = reference.Get();

                var ptr = (int)Context.GetPtr(cached);

                if (ptr == -1)
                {
                    throw new InvalidDataException("Couldn't get the pointer to a prototype!");
                }

                var info = new EntityPrototypeInfo(obj, ptr);

                var uidBuffer = (Use64Bit)
                    ? BitConverter.GetBytes(uid)
                    : BitConverter.GetBytes((uint)uid);

                bs.Write(uidBuffer);

                info.Serialize(bs);
            }

            Context.End();
        }
예제 #4
0
        public static FCXCompressedData Pack(BinaryStream stream)
        {
            var compressedData = new FCXCompressedData();

            using (var bs = new BinaryStream(1024))
            {
                uint virtualOffset = 0;
                uint realOffset    = 4;

                while (stream.Position < stream.Length)
                {
                    var length = (int)Math.Min(0x40000, (stream.Length - stream.Position));

                    using (var block = new BinaryStream(16))
                    {
                        var zlib   = new DeflaterOutputStream(block);
                        var buffer = stream.ReadBytes(length);

                        zlib.Write(buffer, 0, length);
                        zlib.Finish();

                        compressedData.Blocks.Add(new Block()
                        {
                            VirtualOffset = virtualOffset,
                            FileOffset    = realOffset,
                            IsCompressed  = true,
                        });

                        block.Position = 0;
                        block.CopyTo(bs);

                        realOffset += (uint)block.Length;
                    }

                    virtualOffset += (uint)length;
                }

                compressedData.Data = bs.ToArray();

                compressedData.Blocks.Add(new Block()
                {
                    VirtualOffset = virtualOffset,
                    FileOffset    = realOffset,
                    IsCompressed  = true,
                });
            }

            return(compressedData);
        }
예제 #5
0
        protected void WriteRmlData(BinaryStream stream, NomadObject data)
        {
            byte[] rmlBuffer = null;

            using (var bs = new BinaryStream(1024))
            {
                var rmlData = new NomadRmlSerializer();
                rmlData.Serialize(bs, data);

                rmlBuffer = bs.ToArray();
            }

            var size = DescriptorTag.Create(rmlBuffer.Length);
            var next = DescriptorTag.Create(size);

            next.WriteTo(stream);
            size.WriteTo(stream);

            stream.Write(rmlBuffer, 0, rmlBuffer.Length);
        }
예제 #6
0
        public bool Save(string filename)
        {
            if (Type == FileType.Xml)
            {
                var serializer = GetSerializer() as INomadXmlFileSerializer;

                if (serializer != null)
                {
                    serializer.SaveXml(filename);
                    return(true);
                }
            }

            byte[] buffer = null;

            using (var bs = new BinaryStream(1024))
            {
                if (Save(bs))
                {
                    buffer = bs.ToArray();
                }
            }

            if (buffer != null)
            {
                var outDir = Path.GetDirectoryName(filename);

                if (!Directory.Exists(outDir))
                {
                    Directory.CreateDirectory(outDir);
                }

                File.WriteAllBytes(filename, buffer);
                return(true);
            }

            // couldn't serialize data
            return(false);
        }
예제 #7
0
        public override void Serialize(Stream stream, NomadObject _unused)
        {
            var root = new NomadObject("ROOT");

            root.Children.Add(new NomadObject("PMSVALUEDESCLIST"));

            var allFixups = new List <NomadObject>();

            foreach (var param in AllParams)
            {
                if (param.MinVersion > Version)
                {
                    continue;
                }

                var values = new NomadObject(param.ValuesId);
                values.Children.AddRange(param.Values);

                root.Children.Add(values);

                var offsets = new List <int>();
                var hashes  = new List <int>();

                foreach (var fixup in param.Fixups)
                {
                    offsets.Add(fixup.Offset);
                    hashes.Add(fixup.Hash);
                }

                var offsetsAttr = new NomadValue("offsetsArray", DataType.Array);
                var hashesAttr  = new NomadValue("hashesArray", DataType.Array);

                Utils.PackArray(offsetsAttr, offsets, BitConverter.GetBytes, 4);
                Utils.PackArray(hashesAttr, hashes, BitConverter.GetBytes, 4);

                var fixups = new NomadObject(param.FixupsId);

                fixups.Attributes.Add(offsetsAttr);
                fixups.Attributes.Add(hashesAttr);

                allFixups.Add(fixups);
            }

            root.Children.AddRange(allFixups);

            PerMoveResourceInfo.Serialize(root);

            var bs = (stream as BinaryStream)
                     ?? new BinaryStream(stream);

            byte[] fcbData = null;

            using (var nb = new BinaryStream(1024))
            {
                Format = FormatType.Objects;

                base.Serialize(nb, root);
                fcbData = nb.ToArray();
            }

            bs.Write(MoveCount);

            bs.Write(MoveData.Length);
            bs.Write(fcbData.Length);

            bs.Write(MoveData);
            bs.Write(fcbData);
        }
예제 #8
0
        public NomadObject ReadXmlObject(XElement xml, NomadObject parent = null)
        {
            Context.State = ContextStateType.Object;
            Context.ObjectIndex++;

            var name = xml.Name.LocalName;

            var id    = StringId.Parse(name);
            var isRml = false;

            if (parent != null)
            {
                isRml = parent.IsRml;
            }
            if (!isRml && (id == "RML_DATA"))
            {
                isRml = true;
            }

            if (isRml)
            {
                XElement rmlElem = null;

                foreach (var elem in xml.Elements())
                {
                    if (rmlElem != null)
                    {
                        throw new XmlException("Too many elements in RML_DATA node!");
                    }

                    rmlElem = elem;
                }

                if (rmlElem == null)
                {
                    throw new XmlException("Empty RML_DATA nodes are cancerous to your health!");
                }

                var rmlRoot = new NomadObject(true)
                {
                    Id = "RML_DATA"
                };

                ReadRmlObject(rmlElem, rmlRoot);

                byte[] rmlBuffer = null;

                using (var bs = new BinaryStream(1024))
                {
                    // don't write size yet
                    bs.Position += 4;

                    var rmlData = new NomadRmlSerializer();
                    rmlData.Serialize(bs, rmlRoot);

                    // write size
                    var rmlSize = (int)(bs.Position - 4);
                    bs.Position = 0;

                    bs.Write(rmlSize);

                    rmlBuffer = bs.ToArray();
                }

                if (parent != null)
                {
                    var rml = new NomadValue()
                    {
                        Id   = id,
                        Data = new AttributeData(DataType.RML, rmlBuffer),
                    };

                    parent.Attributes.Add(rml);
                }

                return(rmlRoot);
            }

            var result = new NomadObject(isRml)
            {
                Id = id
            };

            foreach (var attr in xml.Attributes())
            {
                ReadXmlAttribute(attr, result);
            }

            foreach (var node in xml.Elements())
            {
                ReadXmlObject(node, result);
            }

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

            return(result);
        }
예제 #9
0
        public override void Serialize(Stream stream, NomadObject data)
        {
            if (Context.State == ContextStateType.End)
            {
                Context.Reset();
            }

            if (data.Id != "RML_DATA")
            {
                throw new InvalidOperationException("RML data wasn't prepared before initializing.");
            }

            if ((data.Children.Count != 1) || (data.Attributes.Count != 0))
            {
                throw new InvalidOperationException("RML data is malformed and cannot be serialized properly.");
            }

            var _stream = (stream as BinaryStream)
                          ?? new BinaryStream(stream);

            var rmlRoot = data.Children[0];

            if (!rmlRoot.IsRml)
            {
                throw new InvalidOperationException("You can't serialize non-RML data as RML data, dumbass!");
            }

            _strings.Clear();

            var strLookup = new Dictionary <string, int>();
            var strPtr    = 0;

            var getStrIdx = new Func <string, int>((str) => {
                var ptr = 0;

                if (str == null)
                {
                    str = String.Empty;
                }

                if (strLookup.ContainsKey(str))
                {
                    ptr = strLookup[str];
                }
                else
                {
                    // add to lookup
                    ptr = strPtr;
                    strLookup.Add(str, strPtr);

                    // add to string table
                    _strings.Add(strPtr, str);

                    // must have null-terminator!
                    var strLen = 1;

                    if (str != null)
                    {
                        strLen += str.Length;
                    }

                    strPtr += strLen;
                }

                return(ptr);
            });

            var entries = new List <NomadData>();

            var elemsCount = 1;
            var attrsCount = 0;

            entries.Add(rmlRoot);

            // iterates through attributes then children (and children's children, etc.)
            foreach (var nd in rmlRoot)
            {
                if (!nd.IsRml)
                {
                    throw new InvalidOperationException("Can't serialize non-RML data!");
                }

                if (nd.IsAttribute)
                {
                    ++attrsCount;
                }
                else if (nd.IsObject)
                {
                    ++elemsCount;
                }

                entries.Add(nd);
            }

            // rough size estimate
            var rmlSize = ((elemsCount * 4) + (attrsCount * 2));

            var strTableLen = -1;

            byte[] rmlBuffer = null;

            using (var ms = new BinaryStream(rmlSize))
            {
                var writeInt = new Action <int>((ptr) => {
                    var nD = DescriptorTag.Create(ptr);
                    nD.WriteTo(ms);
                });

                var writeRml = new Action <NomadData>((nd) => {
                    var nameIdx = getStrIdx(nd.Id);
                    var valIdx  = -1;

                    if (nd.IsObject)
                    {
                        Context.State = ContextStateType.Object;
                        Context.ObjectIndex++;

                        var obj = (NomadObject)nd;

                        valIdx = getStrIdx(obj.Tag);

                        writeInt(nameIdx);
                        writeInt(valIdx);
                        writeInt(obj.Attributes.Count);
                        writeInt(obj.Children.Count);
                    }
                    else if (nd.IsAttribute)
                    {
                        Context.State = ContextStateType.Member;
                        Context.MemberIndex++;

                        var attr = (NomadValue)nd;

                        valIdx = getStrIdx(attr.Data);

                        // required for attributes
                        ms.WriteByte(0);

                        writeInt(nameIdx);
                        writeInt(valIdx);
                    }
                });

                writeRml(rmlRoot);

                // enumerates attributes, then children (+ nested children)
                foreach (var rml in rmlRoot)
                {
                    writeRml(rml);
                }

                // setup string table size
                strTableLen = strPtr;

                // write out string table
                foreach (var kv in _strings)
                {
                    var str = kv.Value;

                    var strLen = (str != null) ? str.Length : 0;
                    var strBuf = new byte[strLen + 1];

                    if (strLen > 0)
                    {
                        Encoding.UTF8.GetBytes(str, 0, strLen, strBuf, 0);
                    }

                    ms.Write(strBuf);
                }

                // commit buffer
                rmlBuffer = ms.ToArray();
                rmlSize   = rmlBuffer.Length;
            }

            var bufSize = 5; // header + 3 small ints

            // expand size as needed
            if (strTableLen >= 254)
            {
                bufSize += 4;
            }
            if (elemsCount >= 254)
            {
                bufSize += 4;
            }
            if (attrsCount >= 254)
            {
                bufSize += 4;
            }

            // calculate the final size (hopefully)
            bufSize += rmlSize;

            byte[] result = null;

            using (var ms = new BinaryStream(bufSize))
            {
                ms.WriteByte(0);
                ms.WriteByte(Reserved);

                DescriptorTag[] descriptors =
                {
                    DescriptorTag.Create(strTableLen),
                    DescriptorTag.Create(elemsCount),
                    DescriptorTag.Create(attrsCount),
                };

                foreach (var desc in descriptors)
                {
                    desc.WriteTo(ms);
                }

                // write RML data (+ string table)
                ms.Write(rmlBuffer);

                // profit!!!
                result = ms.ToArray();
            }

            _stream.Write(result, 0, result.Length);

            Context.State = ContextStateType.End;
        }
예제 #10
0
            public void Serialize(BinaryStream output)
            {
                output.Write(Name.Hash);
                output.Write(StringCount);

                foreach (var locStr in LocalizedStrings)
                {
                    locStr.Serialize(output);
                }

                var vals    = new List <DecompressedValues>();
                var locStrs = new List <OasisLocalizedString>();

                var len = 0;
                var crc = 0;

                foreach (var locStr in LocalizedStrings)
                {
                    locStrs.Add(locStr);

                    len += (locStr.Value.Length * 2);

                    if ((len >= MAX_LENGTH) &&
                        (locStr.Enum != crc))
                    {
                        var val = new DecompressedValues(locStrs);
                        vals.Add(val);

                        locStrs = new List <OasisLocalizedString>();
                        len     = 0;
                        crc     = 0;
                    }
                    else
                    {
                        crc = locStr.Enum;
                    }
                }

                if (locStrs.Count != 0)
                {
                    var val = new DecompressedValues(locStrs);
                    vals.Add(val);

                    locStrs = new List <OasisLocalizedString>();
                }

                output.Write(vals.Count);

                foreach (var val in vals)
                {
                    var cpr = new CompressedValues();

                    using (var bs = new BinaryStream(1024))
                    {
                        val.Serialize(bs);

                        var buffer = bs.ToArray();
                        var size   = buffer.Length;

                        byte[] cprBuffer = null;
                        var    lz        = new LZ4Compressor64();

                        var cprSize = lz.Compress(buffer, cprBuffer);

                        cpr.CompressedBytes = cprBuffer;
                        cpr.CompressedSize  = cprSize;

                        cpr.DecompressedSize = size;

                        cpr.LastSortedCRC = val.SortedEnums.Last();
                    }

                    cpr.Serialize(output);
                }
            }