anchor.diff:    Assert(SameText(ExtractFileExt(aFilename), '.png'));
   
     if aIndex > fRXData.Count then
  -    Allocate(aIndex);
  +    Allocate(aIndex)
  +  else
  +  // RGBA / Mask / HasMask arrays are cleared after 1st usage, so we should reallocate memory for them
  +  if aEnlargeOnly then
  +    AllocateTemp(aIndex);
   
     LoadFromPng(aFolder + aFilename, pngWidth, pngHeight, pngData);
  -  Assert((pngWidth <= 2048) and (pngHeight <= 2048), 'Image size should be less than 2048x2048 pixels');
  +  Assert((pngWidth <= MAX_GAME_ATLAS_SIZE) and (pngHeight <= MAX_GAME_ATLAS_SIZE),
  +         Format('Image size should be less than %dx%d pixels', [MAX_GAME_ATLAS_SIZE, MAX_GAME_ATLAS_SIZE]));
   
     fRXData.Flag[aIndex] := Byte(pngWidth * pngHeight <> 0); //Mark as used (required for saving RXX)
     fRXData.Size[aIndex].X := pngWidth;
  
positive.code:   end;
  
  var
    I, K: Integer;
    spriteSizes: TIndexSizeArray;
    spriteInfo: TBinArray;
    atlasSize, allTilesAtlasSize: Integer;
  
negative.code: 
  
  {$IFNDEF NO_OGL}
  procedure TKMSpritePack.MakeGFX_BinPacking(aTexType: TKMTexFormat; aStartingIndex: Integer; var aBaseRAM, aColorRAM, aTexCount: Cardinal;
                                             aFillGFXData: Boolean = True; aOnStopExecution: TBooleanFuncSimple = nil);
  var
    I: Integer;
    idList: TList<Integer>;
  begin
    idList := TList<Integer>.Create;
    try
      for I := aStartingIndex to fRXData.Count do
        idList.Add(I);
  
      MakeGFX_BinPacking(aTexType, idList, aBaseRAM, aColorRAM, aTexCount, aFillGFXData, aOnStopExecution);
    finally
      idList.Free;
    end;
  end;
  
  
  procedure TKMSpritePack.PrepareAtlases(aSpriteInfo: TBinArray; aMode: TKMSpriteAtlasType; aTexType: TKMTexFormat; var aBaseRAM, aColorRAM, aTexCount: Cardinal;
                                         aFillGFXData: Boolean = True; aOnStopExecution: TBooleanFuncSimple = nil);
  var
    I, K, L, M: Integer;
    CT, CL, Pixel: Cardinal;
    texID: Cardinal;
    ID: Integer;
    TD: TKMCardinalArray;
    texFilter: TKMFilterType;
  begin
  //  gLog.AddTime('Length(aSpriteInfo) = ' + IntToStr(Length(aSpriteInfo)));
    //Prepare atlases
    for I := 0 to Length(aSpriteInfo) - 1 do
    begin
  //    if I * 2 + 1 >= I - 1 then
  //      gLog.AddTime('I = ' + IntToStr(I));
      Assert(MakePOT(aSpriteInfo[I].Width) = aSpriteInfo[I].Width);
      Assert(MakePOT(aSpriteInfo[I].Height) = aSpriteInfo[I].Height);
      SetLength(TD, 0);
      SetLength(TD, aSpriteInfo[I].Width * aSpriteInfo[I].Height);
  
      //Copy sprite to Atlas
      for K := 0 to High(aSpriteInfo[I].Sprites) do
      begin
        ID := aSpriteInfo[I].Sprites[K].SpriteID;
        for L := 0 to fRXData.Size[ID].Y - 1 do
        for M := 0 to fRXData.Size[ID].X - 1 do
        begin
          CT := aSpriteInfo[I].Sprites[K].PosY;
          CL := aSpriteInfo[I].Sprites[K].PosX;
          Pixel := (CT + L) * aSpriteInfo[I].Width + CL + M;
          if aMode = saBase then
            TD[Pixel] := fRXData.RGBA[ID, L * fRXData.Size[ID].X + M]
          else
            TD[Pixel] := $FFFFFF or (fRXData.Mask[ID, L * fRXData.Size[ID].X + M] shl 24);
  
          //Fill padding with edge pixels
          if fPad > 0 then
          begin
            if (M = 0) then
            begin
              TD[Pixel - 1] := TD[Pixel];
              if (L = 0) then
                TD[Pixel - aSpriteInfo[I].Width - 1] := TD[Pixel]
              else
              if (L = fRXData.Size[ID].Y - 1) then
                TD[Pixel + aSpriteInfo[I].Width - 1] := TD[Pixel];
            end;
  
            if (M = fRXData.Size[ID].X - 1) then
            begin
              TD[Pixel + 1] := TD[Pixel];
              if (L = 0) then
                TD[Pixel - aSpriteInfo[I].Width + 1] := TD[Pixel]
              else
              if (L = fRXData.Size[ID].Y - 1) then
                TD[Pixel + aSpriteInfo[I].Width + 1] := TD[Pixel];
            end;
  
            if (L = 0) then                       TD[Pixel - aSpriteInfo[I].Width] := TD[Pixel];
            if (L = fRXData.Size[ID].Y - 1) then  TD[Pixel + aSpriteInfo[I].Width] := TD[Pixel];
          end;
  
          //Sprite outline
          if OUTLINE_ALL_SPRITES and (
            (L = 0) or (M = 0)
            or (L = fRXData.Size[ID].Y - 1)
            or (M = fRXData.Size[ID].X - 1)) then
            TD[Pixel] := $FF0000FF;
        end;
      end;
  
      if aFillGFXData then
      begin
        //Generate texture once
        texFilter := ftNearest;
        if LINEAR_FILTER_SPRITES and (fRT in [rxTrees, rxHouses, rxUnits]) then
          texFilter := ftLinear;
  
        texID := TRender.GenTexture(aSpriteInfo[I].Width, aSpriteInfo[I].Height, @TD[0], aTexType, texFilter, texFilter);
  
        //Now that we know texture IDs we can fill GFXData structure
        SetGFXData(texID, aSpriteInfo[I], aMode);
      end else begin
        Assert(InRange(I, Low(fGFXPrepData[aMode]), High(fGFXPrepData[aMode])),
               Format('Preloading sprite index out of range: %d, range [%d;%d]', [I, Low(fGFXPrepData[aMode]), High(fGFXPrepData[aMode])]));
        // Save prepared data for generating later (in main thread)
        fGFXPrepData[aMode, I].SpriteInfo := aSpriteInfo[I];
        fGFXPrepData[aMode, I].TexType := aTexType;
        fGFXPrepData[aMode, I].Data := TD;
      end;
  
      if aMode = saBase then
        Inc(aBaseRAM, aSpriteInfo[I].Width * aSpriteInfo[I].Height * TEX_FORMAT_SIZE[aTexType])
      else
        Inc(aColorRAM, aSpriteInfo[I].Width * aSpriteInfo[I].Height * TEX_FORMAT_SIZE[aTexType]);
  
      Inc(aTexCount);
  
      if aFillGFXData and EXPORT_SPRITE_ATLASES and (fRT in EXPORT_SPRITE_ATLASES_LIST) then
        SaveTextureToPNG(aSpriteInfo[I].Width, aSpriteInfo[I].Height, RXInfo[fRT].FileName + '_' +
                         SPRITE_TYPE_EXPORT_NAME[aMode] + IntToStr(I), TD);
    end;
  end;
  
  
  //This algorithm is planned to take advantage of more efficient 2D bin packing
  procedure TKMSpritePack.MakeGFX_BinPacking(aTexType: TKMTexFormat; aIDList: TList<Integer>; var aBaseRAM, aColorRAM, aTexCount: Cardinal;
                                             aFillGFXData: Boolean = True; aOnStopExecution: TBooleanFuncSimple = nil);
  
  
    function StopExec: Boolean;
    begin
  