public void Run(Utility utility, string[] args)
        {
            // HACK: The engine code assumes that Game.modData is set.
            Game.ModData = utility.ModData;

            var filename   = args[1];
            var file       = new IniFile(File.Open(args[1], FileMode.Open));
            var basic      = file.GetSection("Basic");
            var mapSection = file.GetSection("Map");
            var tileset    = mapSection.GetValue("Theater", "");
            var iniSize    = mapSection.GetValue("Size", "0, 0, 0, 0").Split(',').Select(int.Parse).ToArray();
            var iniBounds  = mapSection.GetValue("LocalSize", "0, 0, 0, 0").Split(',').Select(int.Parse).ToArray();
            var size       = new Size(iniSize[2], 2 * iniSize[3]);

            var map = new Map(Game.ModData, utility.ModData.DefaultTileSets[tileset], size.Width, size.Height)
            {
                Title       = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)),
                Author      = "Westwood Studios",
                Bounds      = new Rectangle(iniBounds[0], iniBounds[1], iniBounds[2], 2 * iniBounds[3] + 2 * iniBounds[1]),
                RequiresMod = utility.ModData.Manifest.Id
            };

            var fullSize = new int2(iniSize[2], iniSize[3]);

            ReadTiles(map, file, fullSize);
            ReadActors(map, file, "Structures", fullSize);
            ReadActors(map, file, "Units", fullSize);
            ReadActors(map, file, "Infantry", fullSize);
            ReadTerrainActors(map, file, fullSize);
            ReadWaypoints(map, file, fullSize);
            ReadOverlay(map, file, fullSize);
            ReadLighting(map, file);

            var spawnCount = map.ActorDefinitions.Count(n => n.Value.Value == "mpspawn");
            var mapPlayers = new MapPlayers(map.Rules, spawnCount);

            map.PlayerDefinitions = mapPlayers.ToMiniYaml();

            var dest = Path.GetFileNameWithoutExtension(args[1]) + ".oramap";

            map.Save(ZipFileLoader.Create(dest));
            Console.WriteLine(dest + " saved.");
        }
        static void ReadOverlay(Map map, IniFile file, int2 fullSize)
        {
            var overlaySection    = file.GetSection("OverlayPack");
            var overlayCompressed = Convert.FromBase64String(string.Concat(overlaySection.Select(kvp => kvp.Value)));
            var overlayPack       = new byte[1 << 18];
            var temp = new byte[1 << 18];

            UnpackLCW(overlayCompressed, overlayPack, temp);

            var overlayDataSection    = file.GetSection("OverlayDataPack");
            var overlayDataCompressed = Convert.FromBase64String(string.Concat(overlayDataSection.Select(kvp => kvp.Value)));
            var overlayDataPack       = new byte[1 << 18];

            UnpackLCW(overlayDataCompressed, overlayDataPack, temp);

            var overlayIndex = new CellLayer <int>(map);

            overlayIndex.Clear(0xFF);

            for (var y = 0; y < fullSize.Y; y++)
            {
                for (var x = fullSize.X * 2 - 2; x >= 0; x--)
                {
                    var dx = (ushort)x;
                    var dy = (ushort)(y * 2 + x % 2);

                    var uv = new MPos(dx / 2, dy);
                    var rx = (ushort)((dx + dy) / 2 + 1);
                    var ry = (ushort)(dy - rx + fullSize.X + 1);

                    if (!map.Resources.Contains(uv))
                    {
                        continue;
                    }

                    overlayIndex[uv] = rx + 512 * ry;
                }
            }

            foreach (var cell in map.AllCells)
            {
                var overlayType = overlayPack[overlayIndex[cell]];
                if (overlayType == 0xFF)
                {
                    continue;
                }

                string actorType;
                if (OverlayToActor.TryGetValue(overlayType, out actorType))
                {
                    if (string.IsNullOrEmpty(actorType))
                    {
                        continue;
                    }

                    var shape = new Size(1, 1);
                    if (OverlayShapes.TryGetValue(overlayType, out shape))
                    {
                        // Only import the top-left cell of multi-celled overlays
                        var aboveType = overlayPack[overlayIndex[cell - new CVec(1, 0)]];
                        if (shape.Width > 1 && aboveType != 0xFF)
                        {
                            string a;
                            if (OverlayToActor.TryGetValue(aboveType, out a) && a == actorType)
                            {
                                continue;
                            }
                        }

                        var leftType = overlayPack[overlayIndex[cell - new CVec(0, 1)]];
                        if (shape.Height > 1 && leftType != 0xFF)
                        {
                            string a;
                            if (OverlayToActor.TryGetValue(leftType, out a) && a == actorType)
                            {
                                continue;
                            }
                        }
                    }

                    var ar = new ActorReference(actorType)
                    {
                        new LocationInit(cell),
                        new OwnerInit("Neutral")
                    };

                    DamageState damageState;
                    if (OverlayToHealth.TryGetValue(overlayType, out damageState))
                    {
                        var health = 100;
                        if (damageState == DamageState.Critical)
                        {
                            health = 25;
                        }
                        else if (damageState == DamageState.Heavy)
                        {
                            health = 50;
                        }
                        else if (damageState == DamageState.Medium)
                        {
                            health = 75;
                        }

                        if (health != 100)
                        {
                            ar.Add(new HealthInit(health));
                        }
                    }

                    map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, ar.Save()));

                    continue;
                }

                var resourceType = ResourceFromOverlay
                                   .Where(kv => kv.Value.Contains(overlayType))
                                   .Select(kv => kv.Key)
                                   .FirstOrDefault();

                if (resourceType != 0)
                {
                    map.Resources[cell] = new ResourceTile(resourceType, overlayDataPack[overlayIndex[cell]]);
                    continue;
                }

                Console.WriteLine("{0} unknown overlay {1}", cell, overlayType);
            }
        }