anchor.diff:  interface
   uses
     {$IFDEF Unix} LCLIntf, LCLType, {$ENDIF}
  -  Classes, Graphics, Math, SysUtils,
  +  Classes, Graphics, Math, SysUtils, Generics.Collections,
     KM_CommonTypes, KM_Defaults, KM_Pics, KM_PNG, KM_Render, KM_ResTexts, KM_ResTileset, KM_ResHouses
     {$IFDEF FPC}, zstream {$ENDIF}
     {$IFDEF WDC}, ZLib {$ENDIF};
  
positive.code:   MK: TKMTileMaskKind;
    MT: TKMTileMaskType;
    MST: TKMTileMaskSubType;
    TerrainId, MaskId: Word;
    MaskFullType: PKMMaskFullType;
    GenTerrainInfo: TKMGenTerrainInfo;
  
    TexId,{ K,} L, M, {P, }Q, MId, Tmp: Integer;
    GenTilesCnt, GenTilesCntTemp: Integer;
    StraightPixel{, RotatePixel}: Cardinal;
    GeneratedMasks: TStringList;
  begin
    Assert(not aLegacyGeneration or (aSprites = nil));
    
    if aLegacyGeneration then
    begin
      //static arrays could be reset via its variable
      FillChar(gGenTerrainTransitionsLegacy, SizeOf(gGenTerrainTransitionsLegacy), #0); //Init array, it could be init on previous tileset load
      TexId := 4999;
      fGenTexIdStartILegacy := TexId;
      GenTilesCntTemp := (Integer(High(TKMTerrainKind)) - 1)*Integer(High(TKMTileMaskKind))
                     *Integer(High(TKMTileMaskType))*(Integer(High(TKMTileMaskSubType)) + 1);
      SetLength(fGenTerrainToTerKindLegacy, GenTilesCntTemp);
      FillChar(fGenTerrainToTerKindLegacy[0], SizeOf(fGenTerrainToTerKindLegacy[0])*GenTilesCntTemp, #0);
    end
    else
    begin
      //static arrays could be reset via its variable
      FillChar(gGenTerrainTransitions, SizeOf(gGenTerrainTransitions), #0); //Init array, it could be init on previous tileset load
      TexId := Length(aSprites.fRXData.RGBA) + 1;
      fGenTexIdStartI := TexId;
      GenTilesCnt := Integer(High(TKMTerrainKind))*Integer(High(TKMTileMaskKind))
                     *Integer(High(TKMTileMaskType))*(Integer(High(TKMTileMaskSubType)) + 1);
      SetLength(fGenTerrainToTerKind, GenTilesCnt);
      aSprites.Allocate(TexId + GenTilesCnt);
      FillChar(fGenTerrainToTerKind[0], SizeOf(fGenTerrainToTerKind[0])*GenTilesCnt, #0);
    end;
    GeneratedMasks := TStringList.Create;
  //  K := 0;
    try
      //for all Terrain Kinds
      for TK := Low(TKMTerrainKind) to High(TKMTerrainKind) do
      begin
        if TK = tkCustom then Continue;
  
        if aLegacyGeneration and (TK = tkSnowOnGrass) then Continue;
  
        TerrainId := BASE_TERRAIN[TK] + 1; // in fRXData Tiles are 1-based
  
        //for all Mask Kinds
        for MK := Low(TKMTileMaskKind) to High(TKMTileMaskKind) do
        begin
          if MK = mkNone then Continue;
  
          if aLegacyGeneration and (MK = mkSoft2) then Continue;
  
          //for all Mask Types
          for MT := Low(TKMTileMaskType) to High(TKMTileMaskType) do
          begin
            if MT = mtNone then Continue;
  
            // for all Mask subtypes
            for MST := Low(TKMTileMaskSubType) to High(TKMTileMaskSubType) do //Mask subtypes (actual masks for layers)
            begin
              MaskId := TILE_MASKS_FOR_LAYERS[MK, MT, MST] + 1;
              if MaskId = 0 then Continue;   //Ignore non existent masks
  
              // We could use same mask image for several masktypes/subtypes
              MId := GeneratedMasks.IndexOf(IntToStr(MaskId));
              if MId > -1 then
              begin
                MaskFullType := PKMMaskFullType(GeneratedMasks.Objects[MId]);
  
                if aLegacyGeneration then
                  Tmp := gGenTerrainTransitionsLegacy[TK, MaskFullType.Kind, MaskFullType.MType, MaskFullType.SubType]
                else
                  Tmp := gGenTerrainTransitions[TK, MaskFullType.Kind, MaskFullType.MType, MaskFullType.SubType];
                  
                if Tmp <> 0 then
                begin
                  if aLegacyGeneration then
                    gGenTerrainTransitionsLegacy[TK, MK, MT, MST] := Tmp
                  else
                    gGenTerrainTransitions[TK, MK, MT, MST] := Tmp;
                  Continue;
                end;
              end else begin
                System.New(MaskFullType);
                MaskFullType.Kind := MK;
                MaskFullType.MType := MT;
                MaskFullType.SubType := MST;
                GeneratedMasks.AddObject(IntToStr(MaskId), TObject(MaskFullType));
              end;
  
      //        for K := 0 to 3 do //Rotation
      //        begin
                GenTerrainInfo.TerKind := TK;
                GenTerrainInfo.Mask.Kind := MK;
                GenTerrainInfo.Mask.MType := MT;
                GenTerrainInfo.Mask.SubType := MST;
                
                if aLegacyGeneration then
                begin
                  gGenTerrainTransitionsLegacy[TK, MK, MT, MST] := TexId - 1;
                  fGenTerrainToTerKindLegacy[TexId - fGenTexIdStartILegacy] := GenTerrainInfo;
                end
                else
                begin
                  SetLength(aSprites.fRXData.RGBA[TexId], aSprites.fRXData.Size[TerrainId].X*aSprites.fRXData.Size[TerrainId].Y); //32*32 actually...
                  SetLength(aSprites.fRXData.Mask[TexId], aSprites.fRXData.Size[TerrainId].X*aSprites.fRXData.Size[TerrainId].Y);
                  aSprites.fRXData.Flag[TexId] := aSprites.fRXData.Flag[TerrainId];
                  aSprites.fRXData.Size[TexId].X := aSprites.fRXData.Size[TerrainId].X;
                  aSprites.fRXData.Size[TexId].Y := aSprites.fRXData.Size[TerrainId].Y;
                  aSprites.fRXData.Pivot[TexId] := aSprites.fRXData.Pivot[TerrainId];
                  aSprites.fRXData.HasMask[TexId] := False;
                  gGenTerrainTransitions[TK, MK, MT, MST] := TexId - 1; //TexId is 1-based, but textures we use - 0 based
                  fGenTerrainToTerKind[TexId - fGenTexIdStartI] := GenTerrainInfo;
                
      //          gLog.AddTime(Format('TerKind: %10s Mask: %10s TexId: %d ', [GetEnumName(TypeInfo(TKMTerrainKind), Integer(I)),
      //                                                        GetEnumName(TypeInfo(TKMTileMaskType), Integer(J)), TexId]));
  
      //          fGenTerrainToTerKind.Add(IntToStr(TexId) + '=' + IntToStr(Integer(I)));
                  for L := 0 to aSprites.fRXData.Size[TerrainId].Y - 1 do
                    for M := 0 to aSprites.fRXData.Size[TerrainId].X - 1 do
                    begin
        //              Rotate(K, L, M, P, Q, aSprites.fRXData.Size[TerrainId].X - 1);
                      StraightPixel := L * aSprites.fRXData.Size[TerrainId].X  + M;
        //              RotatePixel := StraightPixel; //P * aSprites.fRXData.Size[TerrainId].X  + Q;
                      aSprites.fRXData.RGBA[TexId, StraightPixel] := ($FFFFFF or (aSprites.fRXData.RGBA[MaskId, StraightPixel] shl 24))
                                                         and aSprites.fRXData.RGBA[TerrainId, StraightPixel{RotatePixel}];
                    end;
                end;
                Inc(TexId);
      //        end;
            end;
          end;
        end;
      end;
      if aLegacyGeneration then
        SetLength(fGenTerrainToTerKindLegacy, TexId - fGenTexIdStartILegacy)
      else
      begin
        // There could be usused place in arrays, as we could use same mask image for different purposes
        aSprites.Allocate(TexId);
        SetLength(fGenTerrainToTerKind, TexId - fGenTexIdStartI);
      end;
      
    finally
      for Q := 0 to GeneratedMasks.Count - 1 do
        System.Dispose(PKMMaskFullType(GeneratedMasks.Objects[Q]));
      FreeAndNil(GeneratedMasks);
    end;
  end;
  
  
  
negative.code:     PxWidth, PxHeight: Word;
    end;
  
    gGenTerrainTransitions: array[Succ(tkCustom)..High(TKMTerrainKind)]
                              of array[Succ(mkNone)..High(TKMTileMaskKind)]
                                of array[Succ(mtNone)..High(TKMTileMaskType)]
                                  of array[TKMTileMaskSubType] //mask components (subtypes)
  //                                  of array[0..3] //Terrain Rotation
                                      of Word;
  
    gGenTerrainTransitionsLegacy: array[Succ(tkCustom)..High(TKMTerrainKind)]
                                    of array[Succ(mkNone)..High(TKMTileMaskKind)]
                                      of array[Succ(mtNone)..High(TKMTileMaskType)]
                                        of array[TKMTileMaskSubType] //mask components (subtypes)
  //                                        of array[0..3] //Terrain Rotation
                                            of Word;
  implementation
  uses
    KromUtils,
  