public void AddAll(DataSource data)
        {
            uint   i;
            Layer  atlasIndex;
            Sprite sprite;

            var color = Sprite.Color.Transparent;

            // Note: Don't add sprites to the layer GuiBuildings.
            // We use the same atlas as for layer Buildings.


            #region Landscape

            atlasIndex = Layer.Landscape;

            // Note:
            // We enlarge all tile sprites to the maximum height of 41 (max mask height) with repeated texture data.
            // The masks are also enlarged to this height but with cleared data (full transparency).
            // This way the masked tiles will show up correctly and we don't need to change sizes when tiles change.

            // add all normal landscape tile sprites
            for (i = 0; i < 33u; ++i) // 33 map tile sprites
            {
                AddSprite(atlasIndex, i, data.GetSprite(Data.Resource.MapGround, i, color).RepeatTo(RenderMap.TILE_RENDER_MAX_HEIGHT));
            }

            // add all tile up mask sprites
            uint numUpMasks = 61u; // 61 tile up mask sprites
            i = 0;
            uint maskIndex = 0;

            while (maskIndex < numUpMasks)
            {
                var mask = data.GetSprite(Data.Resource.MapMaskUp, i, color);

                if (mask != null)
                {
                    AddSprite(atlasIndex, maskIndex + 33u, mask.ClearTo(RenderMap.TILE_RENDER_MAX_HEIGHT));
                    ++maskIndex;
                }

                ++i;
            }

            // add all tile down mask sprites
            uint numDownMasks = 61u; // 61 tile down mask sprites
            i         = 0;
            maskIndex = 0;

            while (maskIndex < numDownMasks)
            {
                var mask = data.GetSprite(Data.Resource.MapMaskDown, i, color);

                if (mask != null)
                {
                    AddSprite(atlasIndex, maskIndex + 33u + 61u, mask.ClearTo(RenderMap.TILE_RENDER_MAX_HEIGHT));
                    ++maskIndex;
                }

                ++i;
            }

            #endregion


            #region Waves

            atlasIndex = Layer.Waves;

            // add water waves
            for (i = 0; i < 16; ++i)
            {
                sprite = data.GetSprite(Data.Resource.MapWaves, i, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, i, sprite);
                }
            }

            // we also need 3 masks
            // the wave sprites have a size of 48x19
            // the masks have a size of 32x25
            // the masks will therefore be sized to 48x25
            sprite = Sprite.CreateFullMask(48u, 25u);

            if (sprite != null)
            {
                AddSprite(atlasIndex, 16u, sprite);
            }

            sprite = data.GetSprite(Data.Resource.MapMaskUp, 40u, color).ClearTo(48, 25);

            if (sprite != null)
            {
                AddSprite(atlasIndex, 17u, sprite);
            }

            sprite = data.GetSprite(Data.Resource.MapMaskDown, 40u, color).ClearTo(48, 25);

            if (sprite != null)
            {
                AddSprite(atlasIndex, 18u, sprite);
            }

            #endregion


            #region Buildings

            atlasIndex = Layer.Buildings;

            // building sprites are located in sprites 144 to 193 (with some gaps)
            for (uint buildingSprite = 144; buildingSprite <= 193; ++buildingSprite)
            {
                sprite = data.GetSprite(Data.Resource.MapObject, buildingSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, buildingSprite, sprite);
                }

                // shadow
                sprite = data.GetSprite(Data.Resource.MapShadow, buildingSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 1000u + buildingSprite, sprite); // we use 1000 as the shadow offset (see RenderBuilding)
                }
            }

            // we also add the build-in-progress mask
            AddSprite(atlasIndex, 5000u, Sprite.CreateHalfMask(80u, 200u, true));

            // as we use this texture atlas also for gui buildings we add the basic flag sprite as well (for each player color)
            // they can be found at index 128-131
            for (i = 0; i < 4; ++i)
            {
                var playerColor = PlayerInfo.PlayerColors[i];
                var flagColor   = new Sprite.Color()
                {
                    Red   = playerColor.Red,
                    Green = playerColor.Green,
                    Blue  = playerColor.Blue,
                    Alpha = 255
                };

                AddSprite(atlasIndex, 128u + i, data.GetSprite(Data.Resource.MapObject, 128u, flagColor));
            }

            // also we need some trees in gui (for the start attack popup)
            // they start at index 0
            for (i = 0; i < 16; ++i)
            {
                AddSprite(atlasIndex, i, data.GetSprite(Data.Resource.MapObject, i, color));
            }

            // we also add the burning sprites
            for (i = 0; i < 16; ++i)
            {
                AddSprite(atlasIndex, 2000u + i, data.GetSprite(Data.Resource.GameObject, 135u + i, color));
            }

            #endregion


            #region Serfs

            atlasIndex = Layer.Serfs;

            // for all player colors

            // heads
            for (uint serfHeadSprite = 0u; serfHeadSprite <= 629u; ++serfHeadSprite)
            {
                sprite = data.GetSprite(Data.Resource.SerfHead, serfHeadSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, serfHeadSprite, sprite);
                }
            }

            // torsos
            // all 4 player colors
            for (uint c = 0; c < 4; ++c)
            {
                var playerColor = PlayerInfo.PlayerColors[c];
                var serfColor   = new Sprite.Color()
                {
                    Red   = playerColor.Red,
                    Green = playerColor.Green,
                    Blue  = playerColor.Blue,
                    Alpha = 255
                };

                for (uint serfTorsoSprite = 0u; serfTorsoSprite <= 540u; ++serfTorsoSprite)
                {
                    sprite = data.GetSprite(Data.Resource.SerfTorso, serfTorsoSprite, serfColor);

                    if (sprite != null)
                    {
                        AddSprite(atlasIndex, 1000u + c * 1000u + serfTorsoSprite, sprite);
                    }
                }
            }

            // shadow
            AddSprite(atlasIndex, 5000u, data.GetSprite(Data.Resource.SerfShadow, 0u, color));

            // add fighting stuff (offset is 5000)
            for (i = 197u; i <= 200u; ++i)
            {
                sprite = data.GetSprite(Data.Resource.GameObject, i, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 5000u + i, sprite);
                }
            }


            #endregion


            #region Map Objects

            atlasIndex = Layer.Objects;

            // sprites 0 - 127 are normal map objects
            for (uint objectSprite = 0; objectSprite < 128; ++objectSprite)
            {
                sprite = data.GetSprite(Data.Resource.MapObject, objectSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, objectSprite, sprite);
                }

                // shadow
                sprite = data.GetSprite(Data.Resource.MapShadow, objectSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 1000u + objectSprite, sprite); // we use 1000 as the shadow offset
                }
            }

            // 128 - 143 are flags
            for (uint objectSprite = 128; objectSprite <= 143; ++objectSprite)
            {
                // shadow
                sprite = data.GetSprite(Data.Resource.MapShadow, objectSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 1000u + objectSprite, sprite.ClearTo(20)); // we use 1000 as the shadow offset
                }

                // all 4 player colors
                for (uint c = 0; c < 4; ++c)
                {
                    var playerColor = PlayerInfo.PlayerColors[c];
                    var flagColor   = new Sprite.Color()
                    {
                        Red   = playerColor.Red,
                        Green = playerColor.Green,
                        Blue  = playerColor.Blue,
                        Alpha = 255
                    };

                    sprite = data.GetSprite(Data.Resource.MapObject, objectSprite, flagColor);

                    if (sprite != null)
                    {
                        // We enlarge the height to 20 as for example the castle
                        // will have a lower/equal baseline otherwise.
                        AddSprite(atlasIndex, objectSprite + c * 16u, sprite.ClearTo(20));
                    }
                }
            }

            // also add resources/materials that can be found at flags or building constructions
            for (uint resourceSprite = 0; resourceSprite <= 25; ++resourceSprite)
            {
                sprite = data.GetSprite(Data.Resource.GameObject, resourceSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 2000u + resourceSprite, sprite.ClearTo(20)); // we use 2000 as the resource offset
                }
            }

            // add special building stuff (offset is 10000)
            for (i = 127u; i <= 196; ++i)
            {
                sprite = data.GetSprite(Data.Resource.GameObject, i, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 10000u + i, sprite);
                }
            }

            // add borders (offset is 20000)
            for (i = 0; i < 10; ++i)
            {
                sprite = data.GetSprite(Data.Resource.MapBorder, i, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 20000u + i, sprite);
                }
            }

            #endregion


            #region Paths

            atlasIndex = Layer.Paths;

            // Note:
            // We enlarge all path sprites to the maximum height of 41 (max mask height) with repeated texture data.
            // The masks are also enlarged to this height but with cleared data (full transparency).
            // This way the masked tiles will show up correctly and we don't need to change sizes when tiles change.

            // 10 path grounds
            for (i = 0; i < 10; ++i)
            {
                sprite = data.GetSprite(Data.Resource.PathGround, i, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, i, sprite.RepeatTo(RenderMap.TILE_RENDER_MAX_HEIGHT));
                }
            }

            // 27 path masks
            for (i = 0; i < 27; ++i)
            {
                sprite = data.GetSprite(Data.Resource.PathMask, i, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, 10u + i, sprite.ClearTo(RenderMap.TILE_WIDTH, RenderMap.TILE_RENDER_MAX_HEIGHT));
                }
            }

            #endregion


            #region Builds

            atlasIndex = Layer.Builds;

            // build sprites are located in sprites 31 to 51 (with a gap)
            // these are build indicators and road build symbols
            for (uint buildSprite = 31; buildSprite <= 51; ++buildSprite)
            {
                sprite = data.GetSprite(Data.Resource.GameObject, buildSprite, color);

                if (sprite != null)
                {
                    AddSprite(atlasIndex, buildSprite, sprite);
                }
            }

            #endregion


            #region Cursor

            atlasIndex = Layer.Cursor;

            AddSprite(atlasIndex, 0u, data.GetSprite(Data.Resource.Cursor, 0u, color));

            #endregion


            #region Gui

            uint index     = 0u;
            var  fontColor = new Sprite.Color()
            {
                Red = 0x73, Green = 0xb3, Blue = 0x43, Alpha = 0xff
            };
            var fontShadowColor = new Sprite.Color()
            {
                Red = 0x00, Green = 0x00, Blue = 0x00, Alpha = 0xff
            };

            AddGuiElements(Data.Resource.ArtBox, 14, ref index, data, color);
            AddGuiElements(Data.Resource.ArtFlag, 7, ref index, data, color);
            AddGuiElements(Data.Resource.ArtLandscape, 1, ref index, data, color);
            AddGuiElements(Data.Resource.CreditsBg, 1, ref index, data, color);
            AddGuiElements(Data.Resource.DottedLines, 7, ref index, data, fontColor); // not sure about the color here
            AddGuiElements(Data.Resource.Font, 44, ref index, data, fontColor);
            AddGuiElements(Data.Resource.FontShadow, 44, ref index, data, fontShadowColor);
            AddGuiElements(Data.Resource.FrameBottom, 26, ref index, data, color); // actually there are only 23 sprites but we have to pass the max sprite number + 1 (non-existent sprites are skipped)
            AddGuiElements(Data.Resource.FramePopup, 4, ref index, data, color);
            AddGuiElements(Data.Resource.FrameSplit, 3, ref index, data, color);
            AddGuiElements(Data.Resource.FrameTop, 4, ref index, data, color);
            AddGuiElements(Data.Resource.Indicator, 8, ref index, data, color);
            AddGuiElements(Data.Resource.Logo, 1, ref index, data, color);
            AddGuiElements(Data.Resource.PanelButton, 25, ref index, data, color);
            //AddGuiElements(Data.Resource.Symbol, 16, ref index, data); // TODO: skip them for now. maybe re-add later
            AddGuiElements(Data.Resource.Icon, 318, ref index, data, color);

            // game init box background
            // we add a compound background of sprites 290-293 with a bigger size
            var backgroundSprites = new Sprite[5];
            backgroundSprites[0] = data.GetSprite(Data.Resource.Icon, 290u, color);
            backgroundSprites[1] = data.GetSprite(Data.Resource.Icon, 291u, color);
            backgroundSprites[2] = data.GetSprite(Data.Resource.Icon, 292u, color);
            backgroundSprites[3] = data.GetSprite(Data.Resource.Icon, 293u, color);
            backgroundSprites[4] = data.GetSprite(Data.Resource.Icon, 294u, color);
            var backgroundCompoundSprite = new Sprite(320u, 184u);

            for (int row = 0; row < 23; ++row)             // 23 rows with 8 pixels each = 184 pixels
            {
                for (int column = 0; column < 8; ++column) // 8 columns with 40 pixels each = 320 pixels
                {
                    backgroundCompoundSprite.Add(column * 40, row * 8, backgroundSprites[row % 5]);
                }
            }

            // index is now 318 inside the icons
            AddSprite(Layer.Gui, index++, backgroundCompoundSprite);

            // notification box background
            // we add a compound background of sprites 314 with a bigger size
            backgroundCompoundSprite = new Sprite(128u, 144u);
            sprite = data.GetSprite(Data.Resource.Icon, 314u, color);

            // 9 rows, 8 columns with 16x16 pixels = 128x144
            for (int row = 0; row < 9; ++row)
            {
                for (int column = 0; column < 8; ++column)
                {
                    backgroundCompoundSprite.Add(column * 16, row * 16, sprite);
                }
            }

            // index is now 319 inside the icons
            AddSprite(Layer.Gui, index++, backgroundCompoundSprite);

            // popup backgrounds
            var popupBackgrounds = Enum.GetValues(typeof(PopupBox.BackgroundPattern));

            foreach (PopupBox.BackgroundPattern popupBackground in popupBackgrounds)
            {
                if (popupBackground >= PopupBox.BackgroundPattern.OverallComparison && popupBackground <= PopupBox.BackgroundPattern.Shield)
                {
                    continue; // these are compound backgrounds that are handled internal
                }
                backgroundCompoundSprite = new Sprite(128u, 144u);
                sprite = data.GetSprite(Data.Resource.Icon, (uint)popupBackground, color);

                // 9 rows, 8 columns with 16x16 pixels = 128x144
                for (int row = 0; row < 9; ++row)
                {
                    for (int column = 0; column < 8; ++column)
                    {
                        backgroundCompoundSprite.Add(column * 16, row * 16, sprite);
                    }
                }

                // index is now (320 + popup box background pattern index) inside the icons
                AddSprite(Layer.Gui, index + (uint)popupBackground, backgroundCompoundSprite);
            }

            // we create a compound icon for game type load
            var loadIcon = new Sprite(32u, 32u);
            loadIcon.Add(data.GetSprite(Data.Resource.Icon, 262u, color));
            loadIcon.Add(14, 5, data.GetSprite(Data.Resource.Icon, 93u, color));

            AddSprite(Layer.Gui, guiResourceOffsets[Data.Resource.Icon] + 500u, loadIcon);

            // Add additional colored player sprites for multiplayer games
            var youBaseSprite = data.GetSprite(Data.Resource.Icon,
                                               PlayerFace.You.GetGraphicIndex(), color);
            var friendBaseSprite = data.GetSprite(Data.Resource.Icon,
                                                  PlayerFace.Friend.GetGraphicIndex(), color);
            var youMask = Sprite.CreateFromStream
                          (
                Assembly.GetExecutingAssembly().GetManifestResourceStream("Freeserf.assets.youmask.png")
                          );
            var friendMask = Sprite.CreateFromStream
                             (
                Assembly.GetExecutingAssembly().GetManifestResourceStream("Freeserf.assets.friendmask.png")
                             );
            Sprite.Color[] youColors =
            {
                new Sprite.Color {
                    Red = 167, Green = 39, Blue = 39, Alpha = 255
                },
                new Sprite.Color {
                    Red = 167, Green = 69, Blue = 192, Alpha = 255
                },
                new Sprite.Color {
                    Red = 201, Green = 183, Blue = 59, Alpha = 255
                },
            };
            for (i = 0; i < 3; ++i)
            {
                // Add 3 main player sprites with colors red, magenta and yellow
                var paintedSprite = youBaseSprite.GetMaskFilled(youColors[i], youMask);
                AddSprite(Layer.Gui, guiResourceOffsets[Data.Resource.Icon] + 600u + i, paintedSprite);
            }
            Sprite.Color[] friendColors =
            {
                new Sprite.Color {
                    Red = 23, Green = 124, Blue = 157, Alpha = 255
                },
                youColors[1],
                youColors[2]
            };
            for (i = 0; i < 3; ++i)
            {
                // Add 3 friend player sprites with colors blue, magenta and yellow
                var paintedSprite = friendBaseSprite.GetMaskFilled(friendColors[i], friendMask);
                AddSprite(Layer.Gui, guiResourceOffsets[Data.Resource.Icon] + 603u + i, paintedSprite);
            }

            #endregion


            #region UI Font

            // add new UI font
            guiResourceOffsets.Add(Data.Resource.UIText, guiResourceOffsets[Data.Resource.Icon] + 1000u);
            AddSprite(Layer.GuiFont, guiResourceOffsets[Data.Resource.UIText], Sprite.CreateFromStream(
                          Assembly.GetExecutingAssembly().GetManifestResourceStream("Freeserf.assets.ui_font.png")
                          ));

            #endregion
        }
        void AddGuiElements(Data.Resource resourceType, uint num, ref uint index, DataSource data, Sprite.Color color)
        {
            guiResourceOffsets.Add(resourceType, index);

            for (uint i = 0; i < num; ++i)
            {
                var sprite = data.GetSprite(resourceType, i, color);

                if (sprite != null)
                {
                    AddSprite(Layer.Gui, index, sprite);
                }

                ++index;
            }
        }