Example #1
0
        public static unsafe Bitmap ExtractThumb(IniFile map)
        {
            var prevSection = map.GetSection("Preview");
            var size        = prevSection.ReadString("Size").Split(',');
            var previewSize = new Rectangle(int.Parse(size[0]), int.Parse(size[1]), int.Parse(size[2]), int.Parse(size[3]));
            var preview     = new Bitmap(previewSize.Width, previewSize.Height, PixelFormat.Format24bppRgb);

            byte[] image            = new byte[preview.Width * preview.Height * 3];
            var    prevDataSection  = map.GetSection("PreviewPack");
            var    image_compressed = Convert.FromBase64String(prevDataSection.ConcatenatedValues());

            Format5.DecodeInto(image_compressed, image, 5);

            // invert rgb->bgr
            BitmapData bmd = preview.LockBits(new Rectangle(0, 0, preview.Width, preview.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
            int        idx = 0;

            for (int y = 0; y < bmd.Height; y++)
            {
                byte *row = (byte *)bmd.Scan0 + bmd.Stride * y;
                byte *p   = row;
                for (int x = 0; x < bmd.Width; x++)
                {
                    byte b   = image[idx++];
                    byte g   = image[idx++];
                    byte r   = image[idx++];
                    *    p++ = r;
                    *    p++ = g;
                    *    p++ = b;
                }
            }

            preview.UnlockBits(bmd);
            return(preview);
        }
Example #2
0
        public void SerializeIsoMapPack5(IniFile.IniSection isoMapPack5)
        {
            int cells       = (Width * 2 - 1) * Height;
            int lzoPackSize = cells * 11 + 4;             // last 4 bytes contains a lzo pack header saying no more data is left

            var  isoMapPack  = new byte[lzoPackSize];
            var  isoMapPack2 = new byte[lzoPackSize];
            long di          = 0;

            foreach (var tile in this.isoTiles)
            {
                var bs = tile.ToMapPack5Entry().ToArray();
                Array.Copy(bs, 0, isoMapPack, di, 11);
                di += 11;
            }

            var    compressed   = Format5.Encode(isoMapPack, 5);
            string compressed64 = Convert.ToBase64String(compressed);

            int i   = 1;
            int idx = 0;

            isoMapPack5.Clear();
            while (idx < compressed64.Length)
            {
                int adv = Math.Min(74, compressed64.Length - idx);
                isoMapPack5.SetValue(i++.ToString(), compressed64.Substring(idx, adv));
                idx += adv;
            }
        }
Example #3
0
        /// <summary>Reads the tiles. </summary>
        private void ReadTiles()
        {
            var mapSection = GetSection("IsoMapPack5");

            byte[] lzoData     = Convert.FromBase64String(mapSection.ConcatenatedValues());
            int    cells       = (FullSize.Width * 2 - 1) * FullSize.Height;
            int    lzoPackSize = cells * 11 + 4;          // last 4 bytes contains a lzo pack header saying no more data is left

            var  isoMapPack          = new byte[lzoPackSize];
            uint totalDecompressSize = Format5.DecodeInto(lzoData, isoMapPack);

            var mf       = new MemoryFile(isoMapPack);
            int numtiles = 0;

            for (int i = 0; i < cells; i++)
            {
                ushort rx      = mf.ReadUInt16();
                ushort ry      = mf.ReadUInt16();
                short  tilenum = mf.ReadInt16();
                short  zero1   = mf.ReadInt16();
                ushort subtile = mf.ReadByte();
                short  z       = mf.ReadByte();
                byte   zero2   = mf.ReadByte();

                int dx = rx - ry + FullSize.Width - 1;
                int dy = rx + ry - FullSize.Width - 1;
                numtiles++;
                if (dx >= 0 && dx < 2 * Tiles.Width &&
                    dy >= 0 && dy < 2 * Tiles.Height)
                {
                    var tile = new IsoTile((ushort)dx, (ushort)dy, rx, ry, z, tilenum, subtile);
                    Tiles[(ushort)dx, (ushort)dy / 2] = tile;
                }
            }

            // fix missing tiles

            // import tiles
            for (ushort y = 0; y < FullSize.Height; y++)
            {
                for (ushort x = 0; x <= FullSize.Width * 2 - 2; x++)
                {
                    var isoTile = Tiles[x, y];
                    if (isoTile == null)
                    {
                        // fix null tiles to blank
                        ushort dx = (ushort)(x);
                        ushort dy = (ushort)(y * 2 + x % 2);
                        ushort rx = (ushort)((dx + dy) / 2 + 1);
                        ushort ry = (ushort)(dy - rx + FullSize.Width + 1);
                        Tiles[x, y] = new IsoTile(dx, dy, rx, ry, 0, 0, 0);
                    }
                }
            }


            Logger.Debug("Read {0} tiles", numtiles);
        }
Example #4
0
        /// <summary>Reads the overlay.</summary>
        private void ReadOverlay()
        {
            IniSection overlaySection = GetSection("OverlayPack");

            if (overlaySection == null)
            {
                Logger.Info("OverlayPack section unavailable in {0}, overlay will be unavailable", Path.GetFileName(FileName));
                return;
            }

            byte[] format80Data = Convert.FromBase64String(overlaySection.ConcatenatedValues());
            var    overlayPack  = new byte[1 << 18];

            Format5.DecodeInto(format80Data, overlayPack, 80);

            IniSection overlayDataSection = GetSection("OverlayDataPack");

            if (overlayDataSection == null)
            {
                Logger.Debug("OverlayDataPack section unavailable in {0}, overlay will be unavailable", Path.GetFileName(FileName));
                return;
            }
            format80Data = Convert.FromBase64String(overlayDataSection.ConcatenatedValues());
            var overlayDataPack = new byte[1 << 18];

            Format5.DecodeInto(format80Data, overlayDataPack, 80);

            for (int y = 0; y < FullSize.Height; y++)
            {
                for (int x = FullSize.Width * 2 - 2; x >= 0; x--)
                {
                    var t = Tiles[x, y];
                    if (t == null)
                    {
                        continue;
                    }
                    int  idx        = t.Rx + 512 * t.Ry;
                    byte overlay_id = overlayPack[idx];
                    if (overlay_id != 0xFF)
                    {
                        byte overlay_value = overlayDataPack[idx];
                        var  ovl           = new Overlay(overlay_id, overlay_value);
                        ovl.Tile = t;
                        Overlays.Add(ovl);
                    }
                }
            }

            Logger.Debug("Read {0} overlay types", Overlays.Count);
        }
Example #5
0
    private byte[] GetEncoded(List <Tile> tileSet)
    {
        byte[] isoMapPack = new byte[tileSet.Count * 11 + 4];

        long byteIndex = 0;

        foreach (Tile tile in tileSet)
        {
            byte[] tileInBytes = tile.GetTileForMapPack();
            Array.Copy(tileInBytes, 0, isoMapPack, byteIndex, 11);
            byteIndex += 11;
        }

        return(Format5.Encode(isoMapPack, 5));
    }
Example #6
0
        private byte[] GetEncoded(List <IsoTile> tileSetParam)
        {
            // A tile is of 11 bytes. Last 4 bytes of padding is used for termination
            byte[] isoMapPack = new byte[tileSetParam.Count * 11 + 4];

            long di = 0;

            foreach (var tile in tileSetParam)
            {
                var bs = tile.ToMapPack5Entry().ToArray();
                Array.Copy(bs, 0, isoMapPack, di, 11);
                di += 11;
            }

            return(Format5.Encode(isoMapPack, 5));
        }
Example #7
0
        public static unsafe void InjectThumb(Bitmap preview, IniFile map)
        {
            BitmapData bmd = preview.LockBits(new Rectangle(0, 0, preview.Width, preview.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            byte[] image = new byte[preview.Width * preview.Height * 3];
            int    idx   = 0;

            // invert rgb->bgr
            for (int y = 0; y < bmd.Height; y++)
            {
                byte *p = (byte *)bmd.Scan0 + bmd.Stride * y;
                for (int x = 0; x < bmd.Width; x++)
                {
                    byte r = *p++;
                    byte g = *p++;
                    byte b = *p++;

                    image[idx++] = b;
                    image[idx++] = g;
                    image[idx++] = r;
                }
            }

            // encode
            byte[] image_compressed = Format5.Encode(image, 5);

            // base64 encode
            string image_base64 = Convert.ToBase64String(image_compressed, Base64FormattingOptions.None);

            // now overwrite [Preview] and [PreviewPack], inserting them directly after [Basic] if not yet existing
            map.GetOrCreateSection("Preview").SetValue("Size", string.Format("0,0,{0},{1}", preview.Width, preview.Height));

            var section = map.GetOrCreateSection("PreviewPack", "Preview");

            section.Clear();
            section.Index = 0;

            int rowNum = 1;

            for (int i = 0; i < image_base64.Length; i += 70)
            {
                section.SetValue(rowNum++.ToString(CultureInfo.InvariantCulture), image_base64.Substring(i, Math.Min(70, image_base64.Length - i)));
            }
        }
Example #8
0
    private void UpdateOverlaySections()
    {
        MapSection overlaySection     = GetSection("OverlayPack");
        MapSection overlayDataSection = GetSection("OverlayDataPack");

        if (overlaySection != null && overlayDataSection != null)
        {
            byte[] overlayPack     = new byte[1 << 18];
            byte[] overlayDataPack = new byte[1 << 18];

            for (int i = 0; i < 262144; i++)
            {
                overlayPack[i]     = 0xFF;
                overlayDataPack[i] = 0;
            }

            if (overlays != null && overlays.Count > 0)
            {
                foreach (Overlay entry in overlays)
                {
                    int location = (entry.MapY * 512) + entry.MapX;
                    overlayPack[location]     = (byte)entry.OverlayIndex;
                    overlayDataPack[location] = (byte)entry.OverlayFrame;
                }
            }

            string oPackEncoded     = Convert.ToBase64String(Format5.Encode(overlayPack, 80), Base64FormattingOptions.None);
            string oDataPackEncoded = Convert.ToBase64String(Format5.Encode(overlayDataPack, 80), Base64FormattingOptions.None);

            overlaySection.Entries.Clear();
            overlayDataSection.Entries.Clear();

            for (int i = 0, j = 1; i < oPackEncoded.Length; i += 70)
            {
                overlaySection.Entries.Add(j++.ToString(CultureInfo.InvariantCulture), oPackEncoded.Substring(i, Math.Min(70, oPackEncoded.Length - i)));
            }

            for (int i = 0, j = 1; i < oDataPackEncoded.Length; i += 70)
            {
                overlayDataSection.Entries.Add(j++.ToString(CultureInfo.InvariantCulture), oDataPackEncoded.Substring(i, Math.Min(70, oDataPackEncoded.Length - i)));
            }
        }
    }
Example #9
0
    private void InitializeOverlays()
    {
        MapSection overlaySection     = GetSection("OverlayPack");
        MapSection overlayDataSection = GetSection("OverlayDataPack");

        if (overlaySection != null && overlayDataSection != null)
        {
            overlays = new List <Overlay>();

            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair <string, string> entry in overlaySection.Entries)
            {
                sb.Append(entry.Value);
            }
            byte[] format80Data = Convert.FromBase64String(sb.ToString());
            byte[] overlayPack  = new byte[1 << 18];
            Format5.DecodeInto(format80Data, overlayPack, 80);

            sb.Clear();
            foreach (KeyValuePair <string, string> entry in overlayDataSection.Entries)
            {
                sb.Append(entry.Value);
            }
            format80Data = Convert.FromBase64String(sb.ToString());
            byte[] overlayDataPack = new byte[1 << 18];
            Format5.DecodeInto(format80Data, overlayDataPack, 80);

            foreach (Tuple <int, int> cellCoordinate in coordList)
            {
                int  location     = cellCoordinate.Item1 + 512 * cellCoordinate.Item2;
                byte overlayIndex = overlayPack[location];
                if (overlayIndex != 0xFF)
                {
                    overlays.Add(new Overlay(overlayIndex, (int)overlayDataPack[location], cellCoordinate.Item1, cellCoordinate.Item2));
                }
            }
        }
    }
Example #10
0
    private void InitializeTiles()
    {
        MapSection section = GetSection("IsoMapPack5");

        if (section != null)
        {
            tiles = new List <Tile>();
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair <string, string> entry in section.Entries)
            {
                sb.Append(entry.Value);
            }
            byte[] lzoData     = Convert.FromBase64String(sb.ToString());
            int    cells       = (MapWidth * 2 - 1) * MapHeight;
            int    lzoPackSize = cells * 11 + 4;          // last 4 bytes used for termination
            byte[] isoMapPack  = new byte[lzoPackSize];

            int j = 0;
            for (int i = 0; i < cells; i++)
            {
                isoMapPack[j]     = 0x88;
                isoMapPack[j + 1] = 0x40;
                isoMapPack[j + 2] = 0x88;
                isoMapPack[j + 3] = 0x40;
                j += 11;
            }

            Format5.DecodeInto(lzoData, isoMapPack);

            foreach (Tuple <int, int> cellCoordinate in coordList)
            {
                tiles.Add(new Tile(0, 0, 0, 0, cellCoordinate.Item1, cellCoordinate.Item2));
            }

            MemoryFile mf = new MemoryFile(isoMapPack);
            for (int i = 0; i < cells; i++)
            {
                int  rx          = (int)mf.ReadUInt16();
                int  ry          = (int)mf.ReadUInt16();
                int  tileIndex   = mf.ReadInt32();
                byte subIndex    = mf.ReadByte();
                byte heightLevel = mf.ReadByte();
                byte iceGrowth   = mf.ReadByte();

                if (tileIndex >= 65535)
                {
                    tileIndex = 0;                                     // Tile 0xFFFF used as empty/clear
                }
                if (rx < 512 && ry < 512)
                {
                    int index = tiles.FindIndex(tile => tile.MapX == rx && tile.MapY == ry);
                    if (index >= 0)
                    {
                        tiles[index].TileIndex = tileIndex;
                        tiles[index].SubIndex  = subIndex;
                        tiles[index].Level     = heightLevel;
                        tiles[index].IceGrowth = iceGrowth;
                    }
                }
            }
        }
    }
Example #11
0
        /// <summary>Reads the tiles. </summary>
        private void ReadTiles()
        {
            var mapSection = GetSection("IsoMapPack5");

            byte[] lzoData     = Convert.FromBase64String(mapSection.ConcatenatedValues());
            int    cells       = (FullSize.Width * 2 - 1) * FullSize.Height;
            int    lzoPackSize = cells * 11 + 4;          // last 4 bytes contains a lzo pack header saying no more data is left

            var isoMapPack = new byte[lzoPackSize];

            // In case, IsoMapPack5 contains less entries than the number of cells, fill up any number greater
            // than 511 and filter later.
            int j = 0;

            for (int i = 0; i < cells; i++)
            {
                isoMapPack[j]     = 0x88;
                isoMapPack[j + 1] = 0x40;
                isoMapPack[j + 2] = 0x88;
                isoMapPack[j + 3] = 0x40;
                j += 11;
            }

            Format5.DecodeInto(lzoData, isoMapPack);

            // Fill level 0 clear tiles for all array values
            for (ushort y = 0; y < FullSize.Height; y++)
            {
                for (ushort x = 0; x <= FullSize.Width * 2 - 2; x++)
                {
                    ushort dx = (ushort)(x);
                    ushort dy = (ushort)(y * 2 + x % 2);
                    ushort rx = (ushort)((dx + dy) / 2 + 1);
                    ushort ry = (ushort)(dy - rx + FullSize.Width + 1);
                    Tiles[x, y] = new IsoTile(dx, dy, rx, ry, 0, 0, 0, 0);
                }
            }

            // Overwrite with actual entries found in IsoMapPack5
            var mf       = new MemoryFile(isoMapPack);
            int numtiles = 0;

            for (int i = 0; i < cells; i++)
            {
                ushort rx        = mf.ReadUInt16();
                ushort ry        = mf.ReadUInt16();
                int    tilenum   = mf.ReadInt32();
                byte   subtile   = mf.ReadByte();
                byte   z         = mf.ReadByte();
                byte   icegrowth = mf.ReadByte();

                if (tilenum >= 65535)
                {
                    tilenum = 0;                                   // Tile 0xFFFF used as empty/clear
                }
                if (rx <= 511 && ry <= 511)
                {
                    int dx = rx - ry + FullSize.Width - 1;
                    int dy = rx + ry - FullSize.Width - 1;
                    numtiles++;
                    if (dx >= 0 && dx < 2 * Tiles.Width && dy >= 0 && dy < 2 * Tiles.Height)
                    {
                        var tile = new IsoTile((ushort)dx, (ushort)dy, rx, ry, z, tilenum, subtile, icegrowth);
                        Tiles[(ushort)dx, (ushort)dy / 2] = tile;
                    }
                }
            }

            Logger.Debug("Read {0} tiles", numtiles);
        }