Exemple #1
0
        public Resource Read()
        {
            using (this.reader = new BinaryReader(stream))
            {
                LSBHeader header;
                header.signature = reader.ReadUInt32();
                if (header.signature != LSBHeader.Signature)
                    throw new InvalidFormatException(String.Format("Illegal signature in header; expected {0}, got {1}", LSBHeader.Signature, header.signature));

                header.totalSize = reader.ReadUInt32();
                if (stream.Length != header.totalSize)
                    throw new InvalidFormatException(String.Format("Invalid LSB file size; expected {0}, got {1}", header.totalSize, stream.Length));

                header.bigEndian = reader.ReadUInt32();
                // The game only uses little-endian files on all platforms currently and big-endian support isn't worth the hassle
                if (header.bigEndian != 0)
                    throw new InvalidFormatException("Big-endian LSB files are not supported");

                header.unknown = reader.ReadUInt32();
                header.metadata.timestamp = reader.ReadUInt64();
                header.metadata.majorVersion = reader.ReadUInt32();
                header.metadata.minorVersion = reader.ReadUInt32();
                header.metadata.revision = reader.ReadUInt32();
                header.metadata.buildNumber = reader.ReadUInt32();

                ReadStaticStrings();

                Resource rsrc = new Resource();
                rsrc.Metadata = header.metadata;
                ReadRegions(rsrc);
                return rsrc;
            }
        }
Exemple #2
0
        public void Write(Resource rsrc)
        {
            using (this.writer = new BinaryWriter(stream))
            {
                writer.Write(LSBHeader.Signature);
                var sizeOffset = stream.Position;
                writer.Write((UInt32)0); // Total size of file, will be updater after we finished serializing
                writer.Write((UInt32)0); // Little-endian format
                writer.Write((UInt32)0); // Unknown
                writer.Write(rsrc.Metadata.timestamp);
                writer.Write(rsrc.Metadata.majorVersion);
                writer.Write(rsrc.Metadata.minorVersion);
                writer.Write(rsrc.Metadata.revision);
                writer.Write(rsrc.Metadata.buildNumber);

                CollectStaticStrings(rsrc);
                WriteStaticStrings();

                WriteRegions(rsrc);

                UInt32 fileSize = (UInt32)stream.Position;
                stream.Seek(sizeOffset, SeekOrigin.Begin);
                writer.Write(fileSize);
            }
        }
Exemple #3
0
        private void WriteRegions(Resource rsrc)
        {
            writer.Write((UInt32)rsrc.Regions.Count);
            var regionMapOffset = stream.Position;
            foreach (var rgn in rsrc.Regions)
            {
                writer.Write(staticStrings[rgn.Key]);
                writer.Write((UInt32)0); // Offset of region, will be updater after we finished serializing
            }

            List<UInt32> regionPositions = new List<UInt32>();
            foreach (var rgn in rsrc.Regions)
            {
                regionPositions.Add((UInt32)stream.Position);
                WriteNode(rgn.Value);
            }

            var endOffset = stream.Position;
            stream.Seek(regionMapOffset, SeekOrigin.Begin);
            foreach (var position in regionPositions)
            {
                stream.Seek(4, SeekOrigin.Current);
                writer.Write(position);
            }

            stream.Seek(endOffset, SeekOrigin.Begin);
        }
Exemple #4
0
        public void Write(Resource rsrc)
        {
            var settings = new XmlWriterSettings();
            settings.Indent = PrettyPrint;
            settings.IndentChars = "\t";

            using (this.writer = XmlWriter.Create(stream, settings))
            {
                writer.WriteStartElement("save");

                writer.WriteStartElement("header");
                writer.WriteAttributeString("version", LSXReader.CurrentVersion);
                writer.WriteAttributeString("time", rsrc.Metadata.timestamp.ToString());
                writer.WriteEndElement();

                writer.WriteStartElement("version");
                writer.WriteAttributeString("major", rsrc.Metadata.majorVersion.ToString());
                writer.WriteAttributeString("minor", rsrc.Metadata.minorVersion.ToString());
                writer.WriteAttributeString("revision", rsrc.Metadata.revision.ToString());
                writer.WriteAttributeString("build", rsrc.Metadata.buildNumber.ToString());
                writer.WriteEndElement();

                WriteRegions(rsrc);

                writer.WriteEndElement();
                writer.Flush();
            }
        }
Exemple #5
0
 private void WriteRegions(Resource rsrc)
 {
     foreach (var region in rsrc.Regions)
     {
         writer.WriteStartElement("region");
         writer.WriteAttributeString("id", region.Key);
         WriteNode(region.Value);
         writer.WriteEndElement();
     }
 }
Exemple #6
0
        private void ReadRegions(Resource rsrc)
        {
            UInt32 regions = reader.ReadUInt32();
            for (UInt32 i = 0; i < regions; i++)
            {
                UInt32 regionNameId = reader.ReadUInt32();
                UInt32 regionOffset = reader.ReadUInt32();

                Region rgn = new Region();
                rgn.RegionName = staticStrings[regionNameId];
                var lastRegionPos = stream.Position;

                stream.Seek(regionOffset, SeekOrigin.Begin);
                ReadNode(rgn);
                rsrc.Regions[rgn.RegionName] = rgn;
                stream.Seek(lastRegionPos, SeekOrigin.Begin);
            }
        }
        public Resource Read()
        {
            using (this.reader = XmlReader.Create(stream))
            {
                Resource    rsrc          = new Resource();
                Region      currentRegion = null;
                List <Node> stack         = new List <Node>();

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.Name)
                        {
                        case "save":
                            // Root element
                            if (stack.Count() > 0)
                            {
                                throw new InvalidFormatException("Node <save> was unexpected.");
                            }
                            break;

                        case "header":
                            // LSX metadata part 1
                            string version = reader["version"];
                            if (version != InitialVersion && version != CurrentVersion)
                            {
                                throw new InvalidFormatException(String.Format("Unsupported LSX version; expected {0}, found {1}", CurrentVersion, version));
                            }

                            rsrc.Metadata.timestamp = Convert.ToUInt64(reader["time"]);
                            break;

                        case "version":
                            // LSX metadata part 2
                            rsrc.Metadata.majorVersion = Convert.ToUInt32(reader["major"]);
                            rsrc.Metadata.minorVersion = Convert.ToUInt32(reader["minor"]);
                            rsrc.Metadata.revision     = Convert.ToUInt32(reader["revision"]);
                            rsrc.Metadata.buildNumber  = Convert.ToUInt32(reader["build"]);
                            break;

                        case "region":
                            if (currentRegion != null)
                            {
                                throw new InvalidFormatException("A <region> can only start at the root level of a resource.");
                            }

                            Debug.Assert(!reader.IsEmptyElement);
                            var region = new Region();
                            region.RegionName = reader["id"];
                            Debug.Assert(region.RegionName != null);
                            rsrc.Regions.Add(region.RegionName, region);
                            currentRegion = region;
                            break;

                        case "node":
                            if (currentRegion == null)
                            {
                                throw new InvalidFormatException("A <node> must be located inside a region.");
                            }

                            Node node;
                            if (stack.Count() == 0)
                            {
                                // The node is the root node of the region
                                node = currentRegion;
                            }
                            else
                            {
                                // New node under the current parent
                                node        = new Node();
                                node.Parent = stack.Last();
                            }

                            node.Name = reader["id"];
                            Debug.Assert(node.Name != null);
                            if (node.Parent != null)
                            {
                                node.Parent.AppendChild(node);
                            }

                            if (!reader.IsEmptyElement)
                            {
                                stack.Add(node);
                            }
                            break;

                        case "attribute":
                            var attrTypeId = Convert.ToUInt32(reader["type"]);
                            var attrName   = reader["id"];
                            var attrValue  = reader["value"];
                            if (attrTypeId > (int)NodeAttribute.DataType.DT_Max)
                            {
                                throw new InvalidFormatException(String.Format("Unsupported attribute data type: {0}", attrTypeId));
                            }

                            Debug.Assert(attrName != null);
                            Debug.Assert(attrValue != null);
                            var attr = new NodeAttribute((NodeAttribute.DataType)attrTypeId);
                            attr.FromString(attrValue);
                            if (attr.Type == NodeAttribute.DataType.DT_TranslatedString)
                            {
                                var ts = ((TranslatedString)attr.Value);
                                ts.Handle = reader["handle"];
                                Debug.Assert(ts.Handle != null);
                            }
                            else if (attr.Type == NodeAttribute.DataType.DT_TranslatedFSString)
                            {
                                var fs = ((TranslatedFSString)attr.Value);
                                ReadTranslatedFSString(fs);
                            }

                            stack.Last().Attributes.Add(attrName, attr);
                            break;

                        case "children":
                            // Child nodes are handled in the "node" case
                            break;

                        default:
                            throw new InvalidFormatException(String.Format("Unknown element encountered: {0}", reader.Name));
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        switch (reader.Name)
                        {
                        case "save":
                        case "header":
                        case "version":
                        case "attribute":
                        case "children":
                            // These elements don't change the stack, just discard them
                            break;

                        case "region":
                            Debug.Assert(stack.Count == 0);
                            Debug.Assert(currentRegion != null);
                            Debug.Assert(currentRegion.Name != null);
                            currentRegion = null;
                            break;

                        case "node":
                            stack.RemoveAt(stack.Count - 1);
                            break;

                        default:
                            throw new InvalidFormatException(String.Format("Unknown element encountered: {0}", reader.Name));
                        }
                    }
                }

                return(rsrc);
            }
        }
        public Resource Read()
        {
            using (var reader = new BinaryReader(Stream))
            {
                var hdr = BinUtils.ReadStruct <Header>(reader);
                if (hdr.Magic != BitConverter.ToUInt32(Header.Signature, 0))
                {
                    var msg = String.Format(
                        "Invalid LSF signature; expected {0,8:X}, got {1,8:X}",
                        BitConverter.ToUInt32(Header.Signature, 0), hdr.Magic
                        );
                    throw new InvalidDataException(msg);
                }

                if (hdr.Version < (ulong)FileVersion.VerInitial || hdr.Version > (ulong)FileVersion.CurrentVersion)
                {
                    var msg = String.Format("LSF version {0} is not supported", hdr.Version);
                    throw new InvalidDataException(msg);
                }

                Names = new List <List <String> >();
                bool isCompressed = BinUtils.CompressionFlagsToMethod(hdr.CompressionFlags) != CompressionMethod.None;
                if (hdr.StringsSizeOnDisk > 0 || hdr.StringsUncompressedSize > 0)
                {
                    uint   onDiskSize = isCompressed ? hdr.StringsSizeOnDisk : hdr.StringsUncompressedSize;
                    byte[] compressed = reader.ReadBytes((int)onDiskSize);
                    byte[] uncompressed;
                    if (isCompressed)
                    {
                        uncompressed = BinUtils.Decompress(compressed, (int)hdr.StringsUncompressedSize, hdr.CompressionFlags);
                    }
                    else
                    {
                        uncompressed = compressed;
                    }

#if DUMP_LSF_SERIALIZATION
                    using (var nodesFile = new FileStream("names.bin", FileMode.Create, FileAccess.Write))
                    {
                        nodesFile.Write(uncompressed, 0, uncompressed.Length);
                    }
#endif

                    using (var namesStream = new MemoryStream(uncompressed))
                    {
                        ReadNames(namesStream);
                    }
                }

                Nodes = new List <NodeInfo>();
                if (hdr.NodesSizeOnDisk > 0 || hdr.NodesUncompressedSize > 0)
                {
                    uint onDiskSize   = isCompressed ? hdr.NodesSizeOnDisk : hdr.NodesUncompressedSize;
                    var  uncompressed = Decompress(reader, onDiskSize, hdr.NodesUncompressedSize, hdr);

#if DUMP_LSF_SERIALIZATION
                    using (var nodesFile = new FileStream("nodes.bin", FileMode.Create, FileAccess.Write))
                    {
                        nodesFile.Write(uncompressed, 0, uncompressed.Length);
                    }
#endif

                    using (var nodesStream = new MemoryStream(uncompressed))
                    {
                        var longNodes = hdr.Version >= (ulong)FileVersion.VerExtendedNodes &&
                                        hdr.Extended == 1;
                        ReadNodes(nodesStream, longNodes);
                    }
                }

                Attributes = new List <AttributeInfo>();
                if (hdr.AttributesSizeOnDisk > 0 || hdr.AttributesUncompressedSize > 0)
                {
                    uint onDiskSize   = isCompressed ? hdr.AttributesSizeOnDisk : hdr.AttributesUncompressedSize;
                    var  uncompressed = Decompress(reader, onDiskSize, hdr.AttributesUncompressedSize, hdr);

#if DUMP_LSF_SERIALIZATION
                    using (var attributesFile = new FileStream("attributes.bin", FileMode.Create, FileAccess.Write))
                    {
                        attributesFile.Write(uncompressed, 0, uncompressed.Length);
                    }
#endif

                    using (var attributesStream = new MemoryStream(uncompressed))
                    {
                        var longAttributes = hdr.Version >= (ulong)FileVersion.VerExtendedNodes &&
                                             hdr.Extended == 1;
                        if (longAttributes)
                        {
                            ReadAttributesV3(attributesStream);
                        }
                        else
                        {
                            ReadAttributesV2(attributesStream);
                        }
                    }
                }

                if (hdr.ValuesSizeOnDisk > 0 || hdr.ValuesUncompressedSize > 0)
                {
                    uint onDiskSize   = isCompressed ? hdr.ValuesSizeOnDisk : hdr.ValuesUncompressedSize;
                    var  uncompressed = Decompress(reader, onDiskSize, hdr.ValuesUncompressedSize, hdr);
                    var  valueStream  = new MemoryStream(uncompressed);
                    this.Values = valueStream;

#if DUMP_LSF_SERIALIZATION
                    using (var valuesFile = new FileStream("values.bin", FileMode.Create, FileAccess.Write))
                    {
                        valuesFile.Write(uncompressed, 0, uncompressed.Length);
                    }
#endif
                }
                else
                {
                    this.Values = new MemoryStream();
                }

                Resource resource = new Resource();
                ReadRegions(resource);

                resource.Metadata.majorVersion = (hdr.EngineVersion & 0xff000000) >> 24;
                resource.Metadata.minorVersion = (hdr.EngineVersion & 0xff0000) >> 16;
                resource.Metadata.revision     = (hdr.EngineVersion & 0xff00) >> 8;
                resource.Metadata.buildNumber  = (hdr.EngineVersion & 0xff);

                return(resource);
            }
        }
Exemple #9
0
 private void CollectStaticStrings(Resource rsrc)
 {
     staticStrings.Clear();
     foreach (var rgn in rsrc.Regions)
     {
         AddStaticString(rgn.Key);
         CollectStaticStrings(rgn.Value);
     }
 }
Exemple #10
0
 private void resourceConvertBtn_Click(object sender, EventArgs e)
 {
     try
     {
         Resource = ResourceUtils.LoadResource(resourceInputPath.Text);
         var format = ResourceUtils.ExtensionToResourceFormat(resourceOutputPath.Text);
         int outputVersion = -1;
         if (GetGame() == DivGame.DOS2)
         {
             outputVersion = (int)FileVersion.VerExtendedNodes;
         }
         else
         {
             outputVersion = (int)FileVersion.VerChunkedCompress;
         }
         ResourceUtils.SaveResource(Resource, resourceOutputPath.Text, format, outputVersion);
         MessageBox.Show("Resource saved successfully.");
     }
     catch (Exception exc)
     {
         MessageBox.Show("Internal error!\r\n\r\n" + exc.ToString(), "Conversion Failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
 }
Exemple #11
0
        public Resource Read()
        {
            using (this.reader = XmlReader.Create(stream))
            {
                Resource rsrc = new Resource();
                Region currentRegion = null;
                List<Node> stack = new List<Node>();

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        switch (reader.Name)
                        {
                            case "save":
                                // Root element
                                if (stack.Count() > 0)
                                    throw new InvalidFormatException("Node <save> was unexpected.");
                                break;

                            case "header":
                                // LSX metadata part 1
                                string version = reader["version"];
                                if (version != InitialVersion && version != CurrentVersion)
                                    throw new InvalidFormatException(String.Format("Unsupported LSX version; expected {0}, found {1}", CurrentVersion, version));

                                rsrc.Metadata.timestamp = Convert.ToUInt64(reader["timestamp"]);
                                break;

                            case "version":
                                // LSX metadata part 2
                                rsrc.Metadata.majorVersion = Convert.ToUInt32(reader["major"]);
                                rsrc.Metadata.minorVersion = Convert.ToUInt32(reader["minor"]);
                                rsrc.Metadata.revision = Convert.ToUInt32(reader["revision"]);
                                rsrc.Metadata.buildNumber = Convert.ToUInt32(reader["build"]);
                                break;

                            case "region":
                                if (currentRegion != null)
                                    throw new InvalidFormatException("A <region> can only start at the root level of a resource.");

                                Debug.Assert(!reader.IsEmptyElement);
                                var region = new Region();
                                region.RegionName = reader["id"];
                                Debug.Assert(region.RegionName != null);
                                rsrc.Regions.Add(region.RegionName, region);
                                currentRegion = region;
                                break;

                            case "node":
                                if (currentRegion == null)
                                    throw new InvalidFormatException("A <node> must be located inside a region.");

                                Node node;
                                if (stack.Count() == 0)
                                {
                                    // The node is the root node of the region
                                    node = currentRegion;
                                }
                                else
                                {
                                    // New node under the current parent
                                    node = new Node();
                                    node.Parent = stack.Last();
                                }

                                node.Name = reader["id"];
                                Debug.Assert(node.Name != null);
                                if (node.Parent != null)
                                    node.Parent.AppendChild(node);

                                if (!reader.IsEmptyElement)
                                    stack.Add(node);
                                break;

                            case "attribute":
                                var attrTypeId = Convert.ToUInt32(reader["type"]);
                                var attrName = reader["id"];
                                var attrValue = reader["value"];
                                if (attrTypeId > (int)NodeAttribute.DataType.DT_Max)
                                    throw new InvalidFormatException(String.Format("Unsupported attribute data type: {0}", attrTypeId));
                                
                                Debug.Assert(attrName != null);
                                Debug.Assert(attrValue != null);
                                var attr = new NodeAttribute((NodeAttribute.DataType)attrTypeId);
                                attr.FromString(attrValue);
                                if (attr.Type == NodeAttribute.DataType.DT_TranslatedString)
                                {
                                    ((TranslatedString)attr.Value).Handle = reader["handle"];
                                    Debug.Assert(((TranslatedString)attr.Value).Handle != null);
                                }

                                stack.Last().Attributes.Add(attrName, attr);
                                break;

                            case "children":
                                // Child nodes are handled in the "node" case
                                break;

                            default:
                                throw new InvalidFormatException(String.Format("Unknown element encountered: {0}", reader.Name));
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        switch (reader.Name)
                        {
                            case "save":
                            case "header":
                            case "version":
                            case "attribute":
                            case "children":
                                // These elements don't change the stack, just discard them
                                break;

                            case "region":
                                Debug.Assert(stack.Count == 0);
                                Debug.Assert(currentRegion != null);
                                Debug.Assert(currentRegion.Name != null);
                                currentRegion = null;
                                break;

                            case "node":
                                stack.RemoveAt(stack.Count - 1);
                                break;

                            default:
                                throw new InvalidFormatException(String.Format("Unknown element encountered: {0}", reader.Name));
                        }
                    }
                }

                return rsrc;
            }
        }