Use LandPixels array allocate in hwengine-future library transitional_engine
authorunC0Rr
Tue, 03 Jan 2023 12:05:59 +0100
branchtransitional_engine
changeset 15901 f39f0f614dbf
parent 15900 128ace913837
child 15902 9b73594ac986
Use LandPixels array allocate in hwengine-future library
hedgewars/SDLh.pas
hedgewars/uAIMisc.pas
hedgewars/uGearsHandlersMess.pas
hedgewars/uLand.pas
hedgewars/uLandGraphics.pas
hedgewars/uLandObjects.pas
hedgewars/uLandTexture.pas
hedgewars/uLandUtils.pas
hedgewars/uMisc.pas
hedgewars/uTextures.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
rust/land2d/src/lib.rs
rust/lib-hwengine-future/src/lib.rs
rust/vec2d/src/lib.rs
--- a/hedgewars/SDLh.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/SDLh.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -931,6 +931,9 @@
     TLongWordArray = array[0..16383] of LongWord;
     PLongWordArray = ^TLongWordArray;
 
+    TWordArray = array[0..16383] of Word;
+    PWordArray = ^TWordArray;
+
     PSDL_Thread = Pointer;
     PSDL_mutex = Pointer;
     PSDL_sem = Pointer;
@@ -1033,14 +1036,14 @@
 {$IFDEF WINDOWS}
      TThreadFunction = function (p: pointer): Longword; stdcall;
      pfnSDL_CurrentBeginThread = function (
-        _Security: pointer; 
+        _Security: pointer;
         _StackSize: LongWord;
         _StartAddress: TThreadFunction;
         _ArgList: pointer;
         _InitFlag: Longword;
         _ThrdAddr: PLongword): PtrUInt; cdecl;
     pfnSDL_CurrentEndThread = procedure (_Retval: LongInt); cdecl;
-{$ENDIF} 
+{$ENDIF}
 
 /////////////////////////////////////////////////////////////////
 /////////////////////  FUNCTION DEFINITIONS /////////////////////
@@ -1142,7 +1145,7 @@
 procedure SDL_SetEventFilter(filter: TSDL_EventFilter); cdecl; external SDLLibName;
 
 function  SDL_ShowCursor(toggle: LongInt): LongInt; cdecl; external SDLLibName;
-procedure SDL_WarpMouse(x, y: Word); 
+procedure SDL_WarpMouse(x, y: Word);
 
 function  SDL_GetKeyboardState(numkeys: PLongInt): PByteArray; cdecl; external SDLLibName;
 
@@ -1297,7 +1300,7 @@
 // for sdl2 we provide a SDL_WarpMouse() which calls the right SDL_WarpMouseInWindow() function
 // this has the advantage of reducing 'uses' and 'ifdef' statements
 // (SDLwindow is a private member of uStore module)
-procedure SDL_WarpMouse(x, y: Word); 
+procedure SDL_WarpMouse(x, y: Word);
 begin
     WarpMouse(x, y);
 end;
@@ -1340,7 +1343,7 @@
 function  SDL_CreateThread(fn: Pointer; name: PChar; data: Pointer): PSDL_Thread; cdecl;
 begin
     SDL_CreateThread:= SDL_CreateThread(fn, name, data, nil, nil)
-end;  
+end;
 {$ENDIF}
 
 end.
--- a/hedgewars/uAIMisc.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uAIMisc.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -527,7 +527,7 @@
 
 {        if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then
             begin
-            LandPixels[trunc(y), trunc(x)]:= v;
+            LandPixelGet(trunc(y), trunc(x)):= v;
             UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true);
             end;}
 
@@ -1083,7 +1083,7 @@
 repeat
         {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
             begin
-            LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= Gear^.Hedgehog^.Team^.Clan^.Color;
+            LandPixelGet(hwRound(Gear^.Y), hwRound(Gear^.X)):= Gear^.Hedgehog^.Team^.Clan^.Color;
             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
             end;}
 
@@ -1149,7 +1149,7 @@
 repeat
         {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
             begin
-            LandPixels[hwRound(Gear^.Y), hwRound(Gear^.X)]:= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color;
+            LandPixelGet(hwRound(Gear^.Y), hwRound(Gear^.X)):= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color;
             UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
             end;}
 
--- a/hedgewars/uGearsHandlersMess.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uGearsHandlersMess.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -960,17 +960,17 @@
                             if gun then
                                 begin
                                 LandDirty[yy div 32, xx div 32]:= 1;
-                                if LandPixels[ry, rx] = 0 then
+                                if LandPixelGet(ry, rx) = 0 then
                                     LandSet(ly, lx, lfDamaged or lfObject)
                                 else LandSet(ly, lx, lfDamaged or lfBasic)
                                 end
                             else LandSet(ly, lx, lf);
                         if gun then
-                             LandPixels[ry, rx]:= (Gear^.Tint shr 24         shl RShift) or
+                             LandPixelSet(ry, rx, (Gear^.Tint shr 24         shl RShift) or
                                                   (Gear^.Tint shr 16 and $FF shl GShift) or
                                                   (Gear^.Tint shr  8 and $FF shl BShift) or
-                                                  (p^[px] and AMask)
-                        else LandPixels[ry, rx]:= addBgColor(LandPixels[ry, rx], p^[px]);
+                                                  (p^[px] and AMask))
+                        else LandPixelSet(ry, rx, addBgColor(LandPixelGet(ry, rx), p^[px]));
                         end
                     else allpx:= false
                     end;
--- a/hedgewars/uLand.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uLand.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -41,9 +41,9 @@
 procedure PrettifyLandAlpha();
 begin
     if (cReducedQuality and rqBlurryLand) <> 0 then
-        PrettifyAlpha2D(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2)
+        PrettifyAlpha2D(LAND_HEIGHT div 2, LAND_WIDTH div 2)
     else
-        PrettifyAlpha2D(LandPixels, LAND_HEIGHT, LAND_WIDTH);
+        PrettifyAlpha2D(LAND_HEIGHT, LAND_WIDTH);
 end;
 
 procedure DrawBorderFromImage(Surface: PSDL_Surface);
@@ -107,9 +107,9 @@
                         if ((x + i) and 16) = 0 then c:= c1 else c:= c2;
 
                         if (cReducedQuality and rqBlurryLand) = 0 then
-                            LandPixels[i, x]:= c
+                            LandPixelSet(i, x, c)
                         else
-                            LandPixels[i div 2, x div 2]:= c
+                            LandPixelSet(i div 2, x div 2, c)
                         end;
                     s:= LAND_HEIGHT
                     end
@@ -122,9 +122,9 @@
                     if ((x + y) and 16) = 0 then c:= c1 else c:= c2;
 
                     if (cReducedQuality and rqBlurryLand) = 0 then
-                        LandPixels[y, x]:= c
+                        LandPixelSet(y, x, c)
                     else
-                        LandPixels[y div 2, x div 2]:= c
+                        LandPixelSet(y div 2, x div 2, c)
                     end;
                 end;
 
@@ -141,9 +141,9 @@
                         if ((y + i) and 16) = 0 then c:= c1 else c:= c2;
 
                         if (cReducedQuality and rqBlurryLand) = 0 then
-                            LandPixels[y, i]:= c
+                            LandPixelSet(y, i, c)
                         else
-                            LandPixels[y div 2, i div 2]:= c
+                            LandPixelSet(y div 2, i div 2, c)
                         end;
                     s:= LAND_WIDTH
                     end
@@ -156,9 +156,9 @@
                     if ((x + y) and 16) = 0 then c:= c1 else c:= c2;
 
                     if (cReducedQuality and rqBlurryLand) = 0 then
-                        LandPixels[y, x]:= c
+                        LandPixelSet(y, x, c)
                     else
-                        LandPixels[y div 2, x div 2]:= c
+                        LandPixelSet(y div 2, x div 2, c)
                     end;
                 end
 end;
@@ -406,9 +406,9 @@
     for x:= 0 to LAND_WIDTH - 1 do
     if LandGet(y, x) <> 0 then
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[y, x]:= p^[x]// or AMask
+            LandPixelSet(y, x, p^[x])// or AMask
         else
-            LandPixels[y div 2, x div 2]:= p^[x];
+            LandPixelSet(y div 2, x div 2, p^[x]);
 
     p:= PLongwordArray(@(p^[Surface^.pitch div 4]));
     end;
@@ -444,20 +444,20 @@
             begin
                 if (cReducedQuality and rqBlurryLand) = 0 then
                     begin
-                    if (LandGet(y, x-1) = lfBasic) and (LandPixels[y, x-1] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y, x-1]
+                    if (LandGet(y, x-1) = lfBasic) and (LandPixelGet(y, x-1) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y, x-1))
 
-                    else if (LandGet(y, x+1) = lfBasic) and (LandPixels[y, x+1] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y, x+1]
+                    else if (LandGet(y, x+1) = lfBasic) and (LandPixelGet(y, x+1) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y, x+1))
 
-                    else if (LandGet(y-1, x) = lfBasic) and (LandPixels[y-1, x] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y-1, x]
+                    else if (LandGet(y-1, x) = lfBasic) and (LandPixelGet(y-1, x) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y-1, x))
 
-                    else if (LandGet(y+1, x) = lfBasic) and (LandPixels[y+1, x] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y+1, x];
+                    else if (LandGet(y+1, x) = lfBasic) and (LandPixelGet(y+1, x) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y+1, x));
 
-                    if (((LandPixels[y,x] and AMask) shr AShift) > 10) then
-                        LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (128 shl AShift)
+                    if (((LandPixelGet(y,x) and AMask) shr AShift) > 10) then
+                        LandPixelSet(y, x, (LandPixelGet(y,x) and (not AMask)) or (128 shl AShift))
                     end;
                 LandSet(y, x, lfObject)
             end
@@ -477,20 +477,20 @@
 
                     begin
 
-                    if (LandGet(y, x-1) = lfBasic) and (LandPixels[y,x-1] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y, x-1]
+                    if (LandGet(y, x-1) = lfBasic) and (LandPixelGet(y,x-1) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y, x-1))
 
-                    else if (LandGet(y, x+1) = lfBasic) and (LandPixels[y,x+1] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y, x+1]
+                    else if (LandGet(y, x+1) = lfBasic) and (LandPixelGet(y,x+1) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y, x+1))
 
-                    else if (LandGet(y+1, x) = lfBasic) and (LandPixels[y+1,x] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y+1, x]
+                    else if (LandGet(y+1, x) = lfBasic) and (LandPixelGet(y+1,x) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y+1, x))
 
-                    else if (LandGet(y-1, x) = lfBasic) and (LandPixels[y-1,x] and AMask <> 0) then
-                        LandPixels[y, x]:= LandPixels[y-1, x];
+                    else if (LandGet(y-1, x) = lfBasic) and (LandPixelGet(y-1,x) and AMask <> 0) then
+                        LandPixelSet(y, x, LandPixelGet(y-1, x));
 
-                    if (((LandPixels[y,x] and AMask) shr AShift) > 10) then
-                        LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (64 shl AShift)
+                    if (((LandPixelGet(y,x) and AMask) shr AShift) > 10) then
+                        LandPixelSet(y, x, (LandPixelGet(y,x) and (not AMask)) or (64 shl AShift))
                     end;
                 LandSet(y, x, lfObject)
             end;
@@ -762,9 +762,9 @@
             c:= AMask or RMask or GMask; // FF00FFFF
 
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[y, x]:= c
+            LandPixelSet(y, x, c)
         else
-            LandPixels[y div 2, x div 2]:= c
+            LandPixelSet(y div 2, x div 2, c)
         end
 end;
 
@@ -864,13 +864,13 @@
 
                     if (cReducedQuality and rqBlurryLand) = 0 then
                         begin
-                        LandPixels[y, leftX + w]:= c;
-                        LandPixels[y, rightX - w]:= c2;
+                        LandPixelSet(y, leftX + w, c);
+                        LandPixelSet(y, rightX - w, c2);
                         end
                     else
                         begin
-                        LandPixels[y div 2, (leftX + w) div 2]:= c;
-                        LandPixels[y div 2, (rightX - w) div 2]:= c2;
+                        LandPixelSet(y div 2, (leftX + w) div 2, c);
+                        LandPixelSet(y div 2, (rightX - w) div 2, c2);
                         end;
                     end;
 
@@ -884,9 +884,9 @@
                 c:= AMask or RMask or GMask; // yellow
 
             if (cReducedQuality and rqBlurryLand) = 0 then
-                LandPixels[topY + w, x]:= c
+                LandPixelSet(topY + w, x, c)
             else
-                LandPixels[(topY + w) div 2, x div 2]:= c;
+                LandPixelSet((topY + w) div 2, x div 2, c);
             end;
         end;
     end;
@@ -914,23 +914,23 @@
         for x:= LongWord(leftX) to LongWord(rightX) do
             for y:= LongWord(topY) to LAND_HEIGHT-1 do
                 begin
-                w:= LandPixels[y,x];
+                w:= LandPixelGet(y,x);
                 w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED +
                       (w shr BShift and $FF) * RGB_LUMINANCE_GREEN +
                       (w shr GShift and $FF) * RGB_LUMINANCE_BLUE));
                 if w > 255 then
                     w:= 255;
-                w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixels[y,x] and AMask);
-                LandPixels[y,x]:= w or (LandPixels[y, x] and AMask)
+                w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixelGet(y,x) and AMask);
+                LandPixelSet(y, x, w or (LandPixelGet(y, x) and AMask))
                 end
     else
         for x:= LongWord(leftX div 2) to LongWord(rightX div 2) do
             for y:= LongWord(topY div 2) to LAND_HEIGHT-1 div 2 do
                 begin
-                w:= LandPixels[y div 2,x div 2];
+                w:= LandPixelGet(y div 2,x div 2);
                 w:= ((w shr RShift and $FF) +  (w shr BShift and $FF) + (w shr GShift and $FF)) div 3;
-                w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixels[y div 2,x div 2] and AMask);
-                LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask)
+                w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixelGet(y div 2,x div 2) and AMask);
+                LandPixelSet(y, x, w or (LandPixelGet(y div 2, x div 2) and AMask))
                 end
     end;
 
@@ -1072,8 +1072,8 @@
     landPixelDigest  : LongInt;
 begin
     landPixelDigest:= 1;
-//    for i:= 0 to LAND_HEIGHT-1 do
-//        landPixelDigest:= Adler32Update(landPixelDigest, @LandGet(i,x), 2);
+    for i:= 0 to LAND_HEIGHT-1 do
+        landPixelDigest:= Adler32Update(landPixelDigest, LandRow(i), LAND_WIDTH*2);
     s:= 'M' + IntToStr(syncedPixelDigest)+'|'+IntToStr(landPixelDigest);
 
     ScriptSetString('LandDigest',IntToStr(landPixelDigest));
@@ -1097,7 +1097,6 @@
 procedure freeModule;
 begin
     DisposeLand;
-    SetLength(LandPixels, 0, 0);
     SetLength(LandDirty, 0, 0);
 end;
 
--- a/hedgewars/uLandGraphics.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uLandGraphics.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -78,13 +78,13 @@
 drawPixelBG := 0;
 if (LandGet(LandY, landX) and lfIndestructible) = 0 then
     begin
-        if ((LandGet(landY, landX) and lfBasic) <> 0) and (((LandPixels[pixelY, pixelX] and AMask) shr AShift) = 255) and (not disableLandBack) then
+        if ((LandGet(landY, landX) and lfBasic) <> 0) and (((LandPixelGet(pixelY, pixelX) and AMask) shr AShift) = 255) and (not disableLandBack) then
         begin
-            LandPixels[pixelY, pixelX]:= LandBackPixel(landX, landY);
+            LandPixelSet(pixelY, pixelX, LandBackPixel(landX, landY));
             inc(drawPixelBG);
         end
-        else if ((LandGet(landY, landX) and lfObject) <> 0) or (((LandPixels[pixelY, pixelX] and AMask) shr AShift) < 255) then
-            LandPixels[pixelY, pixelX]:= ExplosionBorderColorNoA
+        else if ((LandGet(landY, landX) and lfObject) <> 0) or (((LandPixelGet(pixelY, pixelX) and AMask) shr AShift) < 255) then
+            LandPixelSet(pixelY, pixelX, ExplosionBorderColorNoA)
     end;
 end;
 
@@ -93,7 +93,7 @@
 if (LandGet(landY, landX) and lfIndestructible = 0) and
     (((LandGet(landY, landX) and lfBasic) <> 0) or ((LandGet(landY, landX) and lfObject) <> 0)) then
     begin
-    LandPixels[pixelY, pixelX]:= ExplosionBorderColor;
+    LandPixelSet(pixelY, pixelX, ExplosionBorderColor);
     LandSet(landY, landX, (LandGet(landY, landX) or lfDamaged) and (not lfIce));
     LandDirty[landY div 32, landX div 32]:= 1;
     end;
@@ -136,7 +136,7 @@
     // So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness
     iceSurface:= SpritesData[sprIceTexture].Surface;
     icePixels := iceSurface^.pixels;
-    w:= LandPixels[pixelY, pixelX];
+    w:= LandPixelGet(pixelY, pixelX);
     if w > 0 then
         begin
         w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED +
@@ -144,17 +144,17 @@
               (w shr GShift and $FF) * RGB_LUMINANCE_BLUE));
         if w < 128 then w:= w+128;
         if w > 255 then w:= 255;
-        w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixels[pixelY, pixelX] and AMask);
-        LandPixels[pixelY, pixelX]:= addBgColor(w, IceColor);
-        LandPixels[pixelY, pixelX]:= addBgColor(LandPixels[pixelY, pixelX], icePixels^[iceSurface^.w * (pixelY mod iceSurface^.h) + (pixelX mod iceSurface^.w)])
+        w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixelGet(pixelY, pixelX) and AMask);
+        LandPixelSet(pixelY, pixelX, addBgColor(w, IceColor));
+        LandPixelSet(pixelY, pixelX, addBgColor(LandPixelGet(pixelY, pixelX), icePixels^[iceSurface^.w * (pixelY mod iceSurface^.h) + (pixelX mod iceSurface^.w)]))
         end
     else
         begin
-        LandPixels[pixelY, pixelX]:= IceColor and (not AMask) or $E8 shl AShift;
-        LandPixels[pixelY, pixelX]:= addBgColor(LandPixels[pixelY, pixelX], icePixels^[iceSurface^.w * (pixelY mod iceSurface^.h) + (pixelX mod iceSurface^.w)]);
+        LandPixelSet(pixelY, pixelX, IceColor and (not AMask) or $E8 shl AShift);
+        LandPixelSet(pixelY, pixelX, addBgColor(LandPixelGet(pixelY, pixelX), icePixels^[iceSurface^.w * (pixelY mod iceSurface^.h) + (pixelX mod iceSurface^.w)]));
         // silly workaround to avoid having to make background erasure a tadb it smarter about sea ice
-        if LandPixels[pixelY, pixelX] and AMask shr AShift = 255 then
-            LandPixels[pixelY, pixelX]:= LandPixels[pixelY, pixelX] and (not AMask) or 254 shl AShift;
+        if LandPixelGet(pixelY, pixelX) and AMask shr AShift = 255 then
+            LandPixelSet(pixelY, pixelX, LandPixelGet(pixelY, pixelX) and (not AMask) or 254 shl AShift);
         end;
 end;
 
@@ -165,10 +165,10 @@
 if (pixelX < LeftX) or (pixelX > RightX) or (pixelY < TopY) then exit;
 if isLandscapeEdge(getPixelWeight(landX, landY)) then
     begin
-    if (LandPixels[pixelY, pixelX] and AMask < 255) and (LandPixels[pixelY, pixelX] and AMask > 0) then
-        LandPixels[pixelY, pixelX] := (IceEdgeColor and (not AMask)) or (LandPixels[pixelY, pixelX] and AMask)
-    else if (LandPixels[pixelY, pixelX] and AMask < 255) or (LandGet(landY, landX) > 255) then
-        LandPixels[pixelY, pixelX] := IceEdgeColor
+    if (LandPixelGet(pixelY, pixelX) and AMask < 255) and (LandPixelGet(pixelY, pixelX) and AMask > 0) then
+        LandPixelSet(pixelY, pixelX, (IceEdgeColor and (not AMask)) or (LandPixelGet(pixelY, pixelX) and AMask))
+    else if (LandPixelGet(pixelY, pixelX) and AMask < 255) or (LandGet(landY, landX) > 255) then
+        LandPixelSet(pixelY, pixelX, IceEdgeColor)
     end
 else if LandGet(landY, landX) > 255 then
     begin
@@ -203,7 +203,7 @@
             begin
             calculatePixelsCoordinates(i, y, px, py);
             if ((LandGet(y, i) and lfIndestructible) = 0) and (not disableLandBack or (LandGet(y, i) > 255))  then
-                LandPixels[py, px]:= ExplosionBorderColorNoA;
+                LandPixelSet(py, px, ExplosionBorderColorNoA);
             end;
     icePixel:
         for i:= fromPix to toPix do
@@ -488,10 +488,10 @@
                     begin
                     by:= ty div 2; bx:= tx div 2;
                     end;
-                if ((LandGet(ty, tx) and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then
-                    LandPixels[by, bx]:= LandBackPixel(tx, ty)
-                else if ((LandGet(ty, tx) and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
-                    LandPixels[by, bx]:= LandPixels[by, bx] and (not AMASK)
+                if ((LandGet(ty, tx) and lfBasic) <> 0) and (((LandPixelGet(by,bx) and AMask) shr AShift) = 255) and (not disableLandBack) then
+                    LandPixelSet(by, bx, LandBackPixel(tx, ty))
+                else if ((LandGet(ty, tx) and lfObject) <> 0) or (((LandPixelGet(by,bx) and AMask) shr AShift) < 255) then
+                    LandPixelSet(by, bx, LandPixelGet(by, bx) and (not AMASK))
                 end
             end;
     inc(y, dY)
@@ -507,9 +507,9 @@
             if ((LandGet(ty, tx) and lfBasic) <> 0) or ((LandGet(ty, tx) and lfObject) <> 0) then
                 begin
                  if (cReducedQuality and rqBlurryLand) = 0 then
-                    LandPixels[ty, tx]:= ExplosionBorderColor
+                    LandPixelSet(ty, tx, ExplosionBorderColor)
                 else
-                    LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor;
+                    LandPixelSet(ty div 2, tx div 2, ExplosionBorderColor);
 
                 LandSet(ty, tx, (LandGet(ty, tx) or lfDamaged) and (not lfIce));
                 LandDirty[ty div 32, tx div 32]:= 1;
@@ -540,9 +540,9 @@
         if despeckle then
             LandDirty[ty div 32, tx div 32]:= 1;
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[ty, tx]:= ExplosionBorderColor
+            LandPixelSet(ty, tx, ExplosionBorderColor)
         else
-            LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
+            LandPixelSet(ty div 2, tx div 2, ExplosionBorderColor)
         end
     end;
 end;
@@ -590,9 +590,9 @@
             LandDirty[ty div 32, tx div 32]:= 1
             end;
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[ty, tx]:= ExplosionBorderColor
+            LandPixelSet(ty, tx, ExplosionBorderColor)
         else
-            LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
+            LandPixelSet(ty div 2, tx div 2, ExplosionBorderColor)
         end
     end;
     nx:= nx - dY;
@@ -622,10 +622,10 @@
                 begin
                 by:= ty div 2; bx:= tx div 2;
                 end;
-            if ((LandGet(ty, tx) and lfBasic) <> 0) and (((LandPixels[by,bx] and AMask) shr AShift) = 255) and (not disableLandBack) then
-                LandPixels[by, bx]:= LandBackPixel(tx, ty)
-            else if ((LandGet(ty, tx) and lfObject) <> 0) or (((LandPixels[by,bx] and AMask) shr AShift) < 255) then
-                LandPixels[by, bx]:= LandPixels[by, bx] and (not AMASK);
+            if ((LandGet(ty, tx) and lfBasic) <> 0) and (((LandPixelGet(by,bx) and AMask) shr AShift) = 255) and (not disableLandBack) then
+                LandPixelSet(by, bx, LandBackPixel(tx, ty))
+            else if ((LandGet(ty, tx) and lfObject) <> 0) or (((LandPixelGet(by,bx) and AMask) shr AShift) < 255) then
+                LandPixelSet(by, bx, LandPixelGet(by, bx) and (not AMASK));
             LandSet(ty, tx, 0);
             end
         end;
@@ -651,9 +651,9 @@
         if despeckle then
             LandDirty[ty div 32, tx div 32]:= 1;
         if (cReducedQuality and rqBlurryLand) = 0 then
-            LandPixels[ty, tx]:= ExplosionBorderColor
+            LandPixelSet(ty, tx, ExplosionBorderColor)
         else
-            LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor
+            LandPixelSet(ty div 2, tx div 2, ExplosionBorderColor)
         end
     end;
     nx:= nx - dY;
@@ -796,25 +796,25 @@
                 if (not behind) or (LandGet(cpY + y, cpX + x) and lfLandMask = 0) then
                     begin
                     if (LandFlags and lfBasic <> 0) or
-                       ((LandPixels[gY, gX] and AMask shr AShift > 128) and  // This test assumes lfBasic and lfObject differ only graphically
+                       ((LandPixelGet(gY, gX) and AMask shr AShift > 128) and  // This test assumes lfBasic and lfObject differ only graphically
                          (LandFlags and (lfObject or lfIce) = 0)) then
                          LandSet(cpY + y, cpX + x, lfBasic or LandFlags)
                     else if (LandFlags and lfIce = 0) then
 						 LandSet(cpY + y, cpX + x, lfObject or LandFlags)
 					else LandSet(cpY + y, cpX + x, LandFlags)
                     end;
-                if (not behind) or (LandPixels[gY, gX] = 0) then
+                if (not behind) or (LandPixelGet(gY, gX) = 0) then
                     begin
                     if tint = $FFFFFFFF then
-                        LandPixels[gY, gX]:= PLongword(@(p^[x * 4]))^
+                        LandPixelSet(gY, gX, PLongword(@(p^[x * 4]))^)
                     else
                         begin
                         pixel:= PLongword(@(p^[x * 4]))^;
-                        LandPixels[gY, gX]:=
+                        LandPixelSet(gY, gX,
                            ceil((pixel shr RShift and $FF) * ((tint shr 24) / 255)) shl RShift or
                            ceil((pixel shr GShift and $FF) * ((tint shr 16 and $ff) / 255)) shl GShift or
                            ceil((pixel shr BShift and $FF) * ((tint shr  8 and $ff) / 255)) shl BShift or
-                           ceil((pixel shr AShift and $FF) * ((tint and $ff) / 255)) shl AShift;
+                           ceil((pixel shr AShift and $FF) * ((tint and $ff) / 255)) shl AShift);
                         end
                     end
                 end;
@@ -847,7 +847,7 @@
 for ty:= 0 to height - 1 do
     for tx:= 0 to width - 1 do
         begin
-        LandPixels[ty, tx]:= 0;
+        LandPixelSet(ty, tx, 0);
         LandSet(Y + ty, X + tx, 0);
         end;
 end;
@@ -918,7 +918,7 @@
                     begin
                     if not onlyEraseLF then
                         begin
-                        LandPixels[gY, gX]:= 0;
+                        LandPixelSet(gY, gX, 0);
                         LandSet(cpY + y, cpX + x, 0)
                         end
                     else LandSet(cpY + y, cpX + x, LandGet(cpY + y, cpX + x) and (not LandFlags))
@@ -1028,7 +1028,7 @@
         yy:= Y div 2;
     end;
 
-    pixelsweep:= (LandGet(Y, X) <= lfAllObjMask) and ((LandPixels[yy, xx] and AMask) <> 0);
+    pixelsweep:= (LandGet(Y, X) <= lfAllObjMask) and ((LandPixelGet(yy, xx) and AMask) <> 0);
     if (((LandGet(Y, X) and lfDamaged) <> 0) and ((LandGet(Y, X) and lfIndestructible) = 0)) or pixelsweep then
     begin
         c:= 0;
@@ -1047,10 +1047,10 @@
                                 ny:= Y div 2 + i;
                                 nx:= X div 2 + j;
                                 if ((ny and (LAND_HEIGHT_MASK div 2)) = 0) and ((nx and (LAND_WIDTH_MASK div 2)) = 0) then
-                                    if (LandPixels[ny, nx] and AMASK) <> 0 then
+                                    if (LandPixelGet(ny, nx) and AMASK) <> 0 then
                                         inc(c);
                             end
-                            else if (LandPixels[ny, nx] and AMASK)  <> 0 then
+                            else if (LandPixelGet(ny, nx) and AMASK)  <> 0 then
                                     inc(c);
                         end
                     else if LandGet(ny, nx) > 255 then
@@ -1061,9 +1061,9 @@
         if c < 4 then // 0-3 neighbours
         begin
             if ((LandGet(Y, X) and lfBasic) <> 0) and (not disableLandBack) then
-                LandPixels[yy, xx]:= LandBackPixel(X, Y)
+                LandPixelSet(yy, xx, LandBackPixel(X, Y))
             else
-                LandPixels[yy, xx]:= LandPixels[yy, xx] and (not AMASK);
+                LandPixelSet(yy, xx, LandPixelGet(yy, xx) and (not AMASK));
 
             if not pixelsweep then
             begin
@@ -1106,7 +1106,7 @@
         // only consider undamaged neighbors (also leads to skipping itself)
         if (LandGet(ny, nx) and lfDamaged) = 0 then
             begin
-            pixel:= LandPixels[ny, nx];
+            pixel:= LandPixelGet(ny, nx);
             inc(r, (pixel and RMask) shr RShift);
             inc(g, (pixel and GMask) shr GShift);
             inc(b, (pixel and BMask) shr BShift);
@@ -1132,7 +1132,7 @@
 g:= g div 8;
 b:= b div 8;
 a:= a div 8;
-LandPixels[y,x]:= (r shl RShift) or (g shl GShift) or (b shl BShift) or (a shl AShift);
+LandPixelSet(y, x, (r shl RShift) or (g shl GShift) or (b shl BShift) or (a shl AShift));
 
 end;
 
@@ -1147,21 +1147,21 @@
         begin
         if (cReducedQuality and rqBlurryLand) = 0 then
             begin
-            if ((LandPixels[y,x] and AMask) shr AShift) < 10 then
-                LandPixels[y,x]:= (ExplosionBorderColor and (not AMask)) or (128 shl AShift)
+            if ((LandPixelGet(y,x) and AMask) shr AShift) < 10 then
+                LandPixelSet(y,x, (ExplosionBorderColor and (not AMask)) or (128 shl AShift))
             else
-                LandPixels[y,x]:=
-                                (((((LandPixels[y,x] and RMask shr RShift) div 2)+((ExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
-                                (((((LandPixels[y,x] and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
-                                (((((LandPixels[y,x] and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift)
+                LandPixelSet(y,x,
+                                (((((LandPixelGet(y,x) and RMask shr RShift) div 2)+((ExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
+                                (((((LandPixelGet(y,x) and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
+                                (((((LandPixelGet(y,x) and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift))
             end;
 {
         if (LandGet(y, x-1) = lfObject) then
-            LandGet(y,x):= lfObject
+            LandSet(y,x, lfObject)
         else if (LandGet(y, x+1) = lfObject) then
-            LandGet(y,x):= lfObject
+            LandSet(y,x, lfObject)
         else
-            LandGet(y,x):= lfBasic;
+            LandSet(y,x, lfBasic);
 }
         end
     else if ((((LandGet(y, x-1) and lfDamaged) <> 0) and ((LandGet(y+1,x-1) and lfDamaged) <> 0) and ((LandGet(y+2,x) and lfDamaged) <> 0))
@@ -1175,13 +1175,13 @@
         begin
         if (cReducedQuality and rqBlurryLand) = 0 then
             begin
-            if ((LandPixels[y,x] and AMask) shr AShift) < 10 then
-                LandPixels[y,x]:= (ExplosionBorderColor and (not AMask)) or (64 shl AShift)
+            if ((LandPixelGet(y,x) and AMask) shr AShift) < 10 then
+                LandPixelSet(y,x, (ExplosionBorderColor and (not AMask)) or (64 shl AShift))
             else
-                LandPixels[y,x]:=
-                                (((((LandPixels[y,x] and RMask shr RShift) * 3 div 4)+((ExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
-                                (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
-                                (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift)
+                LandPixelSet(y,x,
+                                (((((LandPixelGet(y,x) and RMask shr RShift) * 3 div 4)+((ExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
+                                (((((LandPixelGet(y,x) and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
+                                (((((LandPixelGet(y,x) and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift))
             end;
 {
         if (LandGet(y, x-1) = lfObject) then
@@ -1196,17 +1196,17 @@
 }
         end
     end
-else if ((cReducedQuality and rqBlurryLand) = 0) and ((LandPixels[Y, X] and AMask) = AMask)
+else if ((cReducedQuality and rqBlurryLand) = 0) and ((LandPixelGet(Y, X) and AMask) = AMask)
 and (LandGet(Y, X) and (lfDamaged or lfBasic) = lfBasic)
 and (Y > topY + 1) and (Y < LAND_HEIGHT-2) and (X > leftX + 1) and (X < rightX - 1) then
     begin
     if ((((LandGet(y, x-1) and lfDamaged) <> 0) and (((LandGet(y+1,x) and lfDamaged) <> 0)) or ((LandGet(y-1,x) and lfDamaged) <> 0))
     or (((LandGet(y, x+1) and lfDamaged) <> 0) and (((LandGet(y-1,x) and lfDamaged) <> 0) or ((LandGet(y+1,x) and lfDamaged) <> 0)))) then
         begin
-        LandPixels[y,x]:=
-                        (((((LandPixels[y,x] and RMask shr RShift) div 2)+((ExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
-                        (((((LandPixels[y,x] and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
-                        (((((LandPixels[y,x] and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift)
+        LandPixelSet(y,x,
+                        (((((LandPixelGet(y,x) and RMask shr RShift) div 2)+((ExplosionBorderColor and RMask) shr RShift) div 2) and $FF) shl RShift) or
+                        (((((LandPixelGet(y,x) and GMask shr GShift) div 2)+((ExplosionBorderColor and GMask) shr GShift) div 2) and $FF) shl GShift) or
+                        (((((LandPixelGet(y,x) and BMask shr BShift) div 2)+((ExplosionBorderColor and BMask) shr BShift) div 2) and $FF) shl BShift) or ($FF shl AShift))
         end
     else if ((((LandGet(y, x-1) and lfDamaged) <> 0) and ((LandGet(y+1,x-1) and lfDamaged) <> 0) and ((LandGet(y+2,x) and lfDamaged) <> 0))
     or (((LandGet(y, x-1) and lfDamaged) <> 0) and ((LandGet(y-1,x-1) and lfDamaged) <> 0) and ((LandGet(y-2,x) and lfDamaged) <> 0))
@@ -1217,10 +1217,10 @@
     or (((LandGet(y+1, x) and lfDamaged) <> 0) and ((LandGet(y+1,x-1) and lfDamaged) <> 0) and ((LandGet(y,x-2) and lfDamaged) <> 0))
     or (((LandGet(y-1, x) and lfDamaged) <> 0) and ((LandGet(y-1,x-1) and lfDamaged) <> 0) and ((LandGet(y,x-2) and lfDamaged) <> 0))) then
         begin
-        LandPixels[y,x]:=
-                        (((((LandPixels[y,x] and RMask shr RShift) * 3 div 4)+((ExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
-                        (((((LandPixels[y,x] and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
-                        (((((LandPixels[y,x] and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift)
+        LandPixelSet(y,x,
+                        (((((LandPixelGet(y,x) and RMask shr RShift) * 3 div 4)+((ExplosionBorderColor and RMask) shr RShift) div 4) and $FF) shl RShift) or
+                        (((((LandPixelGet(y,x) and GMask shr GShift) * 3 div 4)+((ExplosionBorderColor and GMask) shr GShift) div 4) and $FF) shl GShift) or
+                        (((((LandPixelGet(y,x) and BMask shr BShift) * 3 div 4)+((ExplosionBorderColor and BMask) shr BShift) div 4) and $FF) shl BShift) or ($FF shl AShift))
         end
     end
 end;
--- a/hedgewars/uLandObjects.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uLandObjects.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -153,9 +153,9 @@
             color:= p^[x];
 
         if (cReducedQuality and rqBlurryLand) = 0 then
-            pLandColor:= @LandPixels[cpY + y, cpX + x]
+            pLandColor:= @(LandPixelRow(cpY + y)^[cpX + x])
         else
-            pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2];
+            pLandColor:= @(LandPixelRow((cpY + y) div 2)^[(cpX + x) div 2]);
 
         landColor:= pLandColor^;
         alpha:= (landColor and AMask) shr AShift;
@@ -208,9 +208,9 @@
         if (color and AMask) <> 0 then
             begin
             if (cReducedQuality and rqBlurryLand) = 0 then
-                pLandColor:= @LandPixels[cpY + y, cpX + x]
+                pLandColor:= @(LandPixelRow(cpY + y)^[cpX + x])
             else
-                pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2];
+                pLandColor:= @(LandPixelRow((cpY + y) div 2)^[(cpX + x) div 2]);
 
             alpha:= (color and AMask) shr AShift;
             if ((alpha <> $FF) and ((pLandColor^) <> 0)) then
@@ -263,9 +263,9 @@
         color:= p^[x];
 
         if (cReducedQuality and rqBlurryLand) = 0 then
-            pLandColor:= @LandPixels[cpY + y, cpX + x]
+            pLandColor:= @(LandPixelRow(cpY + y)^[cpX + x])
         else
-            pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2];
+            pLandColor:= @(LandPixelRow((cpY + y) div 2)^[(cpX + x) div 2]);
 
         landColor:= pLandColor^;
         alpha:= (landColor and AMask) shr AShift;
--- a/hedgewars/uLandTexture.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uLandTexture.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -50,7 +50,7 @@
 var ty: Longword;
 begin
 for ty:= 0 to TEXSIZE - 1 do
-    Move(LandPixels[y * TEXSIZE + ty, x * TEXSIZE], tmpPixels[ty, 0], sizeof(Longword) * TEXSIZE);
+    Move(LandPixelRow(y * TEXSIZE + ty)^[x * TEXSIZE], tmpPixels[ty, 0], sizeof(Longword) * TEXSIZE);
 
 Pixels:= @tmpPixels
 end;
@@ -129,14 +129,14 @@
                     // first check edges
                     while isEmpty and (ty < TEXSIZE) do
                         begin
-                        isEmpty:= LandPixels[ly + ty, lx] and AMask = 0;
-                        if isEmpty then isEmpty:= LandPixels[ly + ty, Pred(lx + TEXSIZE)] and AMask = 0;
+                        isEmpty:= LandPixelGet(ly + ty, lx) and AMask = 0;
+                        if isEmpty then isEmpty:= LandPixelGet(ly + ty, Pred(lx + TEXSIZE)) and AMask = 0;
                         inc(ty)
                         end;
                     while isEmpty and (tx < TEXSIZE-1) do
                         begin
-                        isEmpty:= LandPixels[ly, lx + tx] and AMask = 0;
-                        if isEmpty then isEmpty:= LandPixels[Pred(ly + TEXSIZE), lx + tx] and AMask = 0;
+                        isEmpty:= LandPixelGet(ly, lx + tx) and AMask = 0;
+                        if isEmpty then isEmpty:= LandPixelGet(Pred(ly + TEXSIZE), lx + tx) and AMask = 0;
                         inc(tx)
                         end;
                     // then search every other remaining. does this sort of stuff defeat compiler opts?
@@ -146,7 +146,7 @@
                         tx:= 2;
                         while isEmpty and (tx < TEXSIZE-1) do
                             begin
-                            isEmpty:= LandPixels[ly + ty, lx + tx] and AMask = 0;
+                            isEmpty:= LandPixelGet(ly + ty, lx + tx) and AMask = 0;
                             inc(tx,2)
                             end;
                         inc(ty,2);
@@ -158,7 +158,7 @@
                         tx:= 1;
                         while isEmpty and (tx < TEXSIZE-1) do
                             begin
-                            isEmpty:= LandPixels[ly + ty, lx + tx] and AMask = 0;
+                            isEmpty:= LandPixelGet(ly + ty, lx + tx) and AMask = 0;
                             inc(tx,2)
                             end;
                         inc(ty,2);
--- a/hedgewars/uLandUtils.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uLandUtils.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -1,5 +1,6 @@
 unit uLandUtils;
 interface
+uses SDLh;
 
 procedure ResizeLand(width, height: LongWord);
 procedure DisposeLand();
@@ -7,9 +8,14 @@
 
 function  LandGet(y, x: LongInt): Word;
 procedure LandSet(y, x: LongInt; value: Word);
+function  LandRow(row: LongInt): PWordArray;
 
 procedure FillLand(x, y: LongInt; border, value: Word);
 
+function  LandPixelGet(y, x: LongInt): Longword;
+procedure LandPixelSet(y, x: LongInt; value: Longword);
+function  LandPixelRow(row: LongInt): PLongwordArray;
+
 implementation
 uses uUtils, uConsts, uVariables, uTypes;
 
@@ -18,8 +24,13 @@
 procedure dispose_game_field(game_field: pointer); cdecl; external LibFutureName;
 function  land_get(game_field: pointer; x, y: LongInt): Word; cdecl; external LibFutureName;
 procedure land_set(game_field: pointer; x, y: LongInt; value: Word); cdecl; external LibFutureName;
+function  land_row(game_field: pointer; row: LongInt): PWordArray; cdecl; external LibFutureName;
 procedure land_fill(game_field: pointer; x, y: LongInt; border, fill: Word); cdecl; external LibFutureName;
 
+function  land_pixel_get(game_field: pointer; x, y: LongInt): Longword; cdecl; external LibFutureName;
+procedure land_pixel_set(game_field: pointer; x, y: LongInt; value: Longword); cdecl; external LibFutureName;
+function  land_pixel_row(game_field: pointer; row: LongInt): PLongwordArray; cdecl; external LibFutureName;
+
 var gameField: pointer;
 
 function  LandGet(y, x: LongInt): Word;
@@ -32,11 +43,31 @@
     land_set(gameField, x, y, value)
 end;
 
+function  LandRow(row: LongInt): PWordArray;
+begin
+    LandRow:= land_row(gameField, row)
+end;
+
 procedure FillLand(x, y: LongInt; border, value: Word);
 begin
     land_fill(gameField, x, y, border, value)
 end;
 
+function  LandPixelGet(y, x: LongInt): Longword;
+begin
+    LandPixelGet:= land_pixel_get(gameField, x, y)
+end;
+
+procedure LandPixelSet(y, x: LongInt; value: Longword);
+begin
+    land_pixel_set(gameField, x, y, value)
+end;
+
+function  LandPixelRow(row: LongInt): PLongwordArray;
+begin
+    LandPixelRow:= land_pixel_row(gameField, row)
+end;
+
 procedure ResizeLand(width, height: LongWord);
 var potW, potH: LongInt;
 begin
@@ -49,10 +80,6 @@
     LAND_WIDTH_MASK:= not(LAND_WIDTH-1);
     LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1);
     cWaterLine:= LAND_HEIGHT;
-    if (cReducedQuality and rqBlurryLand) = 0 then
-        SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH)
-    else
-        SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2);
 
     gameField:= create_game_field(LAND_WIDTH, LAND_HEIGHT);
     SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32));
--- a/hedgewars/uMisc.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uMisc.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -288,7 +288,7 @@
     for y:= 0 to LAND_HEIGHT-1 do
         for x:= 0 to LAND_WIDTH-1 do
             if dump = 2 then
-                PLongWordArray(p)^[y*LAND_WIDTH+x]:= LandPixels[LAND_HEIGHT-1-y, x]
+                PLongWordArray(p)^[y*LAND_WIDTH+x]:= LandPixelGet(LAND_HEIGHT-1-y, x)
             else
                 begin
                 if LandGet(LAND_HEIGHT-1-y, x) and lfIndestructible = lfIndestructible then
--- a/hedgewars/uTextures.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uTextures.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -26,14 +26,14 @@
 procedure Surface2GrayScale(surf: PSDL_Surface);
 function  Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
 procedure PrettifySurfaceAlpha(surf: PSDL_Surface; pixels: PLongwordArray);
-procedure PrettifyAlpha2D(pixels: TLandArray; height, width: LongWord);
+procedure PrettifyAlpha2D(height, width: LongWord);
 procedure FreeAndNilTexture(var tex: PTexture);
 
 procedure initModule;
 procedure freeModule;
 
 implementation
-uses GLunit, uUtils, uVariables, uConsts, uDebug, uConsole;
+uses GLunit, uUtils, uVariables, uConsts, uDebug, uConsole, uLandUtils;
 
 var TextureList: PTexture;
 
@@ -194,7 +194,7 @@
     PrettifyAlpha(pixels, nil, si, li, w);
 end;
 
-procedure PrettifyAlpha2D(pixels: TLandArray; height, width: LongWord);
+procedure PrettifyAlpha2D(height, width: LongWord);
 var
     // current y; last x, second last y of array;
     y, lx, sly: LongWord;
@@ -203,10 +203,10 @@
     lx:= width - 1;
     for y:= 0 to sly do
         begin
-        PrettifyAlpha(PLongWordArray(pixels[y]), PLongWordArray(pixels[y+1]), 0, lx, 0);
+        PrettifyAlpha(LandPixelRow(y), LandPixelRow(y+1), 0, lx, 0);
         end;
     // don't forget last row
-    PrettifyAlpha(PLongWordArray(pixels[sly+1]), nil, 0, lx, 0);
+    PrettifyAlpha(LandPixelRow(sly+1), nil, 0, lx, 0);
 end;
 
 function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
--- a/hedgewars/uTypes.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uTypes.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -545,7 +545,6 @@
             gidInfAttack, gidResetWeps, gidPerHogAmmo, gidTagTeam, gidMoreWind);
 
 
-    TLandArray = packed array of array of LongWord;
     TDirtyTag = packed array of array of byte;
 
     TPreview  = packed array[0..127, 0..31] of byte;
--- a/hedgewars/uVariables.pas	Mon Jan 02 15:59:26 2023 +0100
+++ b/hedgewars/uVariables.pas	Tue Jan 03 12:05:59 2023 +0100
@@ -2589,7 +2589,6 @@
         );
 
 var
-    LandPixels: TLandArray;
     LandDirty: TDirtyTag;
     hasBorder: boolean;
     hasGirders: boolean;
--- a/rust/land2d/src/lib.rs	Mon Jan 02 15:59:26 2023 +0100
+++ b/rust/land2d/src/lib.rs	Tue Jan 03 12:05:59 2023 +0100
@@ -1,4 +1,4 @@
-use std::{cmp, ops::Index};
+use std::{cmp, ops::Index, ops::IndexMut};
 
 use integral_geometry::{ArcPoints, EquidistantPoints, Line, Point, PotSize, Rect, Size, SizeMask};
 
@@ -288,6 +288,13 @@
     }
 }
 
+impl<T> IndexMut<usize> for Land2D<T> {
+    #[inline]
+    fn index_mut(&mut self, row: usize) -> &mut [T] {
+        &mut self.pixels[row]
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
--- a/rust/lib-hwengine-future/src/lib.rs	Mon Jan 02 15:59:26 2023 +0100
+++ b/rust/lib-hwengine-future/src/lib.rs	Tue Jan 03 12:05:59 2023 +0100
@@ -23,6 +23,16 @@
 }
 
 #[no_mangle]
+pub extern "C" fn land_set(game_field: &mut GameField, x: i32, y: i32, value: u16) {
+    game_field.collision.map(y, x, |p| *p = value);
+}
+
+#[no_mangle]
+pub extern "C" fn land_row(game_field: &mut GameField, row: i32) -> *mut u16 {
+    game_field.collision[row as usize].as_mut_ptr()
+}
+
+#[no_mangle]
 pub extern "C" fn land_fill(
     game_field: &mut GameField,
     x: i32,
@@ -36,11 +46,6 @@
 }
 
 #[no_mangle]
-pub extern "C" fn land_set(game_field: &mut GameField, x: i32, y: i32, value: u16) {
-    game_field.collision.map(y, x, |p| *p = value);
-}
-
-#[no_mangle]
 pub extern "C" fn land_pixel_get(game_field: &mut GameField, x: i32, y: i32) -> u32 {
     game_field.pixels.map(y, x, |p| *p)
 }
@@ -51,6 +56,11 @@
 }
 
 #[no_mangle]
+pub extern "C" fn land_pixel_row(game_field: &mut GameField, row: i32) -> *mut u32 {
+    game_field.pixels[row as usize].as_mut_ptr()
+}
+
+#[no_mangle]
 pub extern "C" fn dispose_game_field(game_field: *mut GameField) {
     unsafe { drop(Box::from_raw(game_field)) };
 }
--- a/rust/vec2d/src/lib.rs	Mon Jan 02 15:59:26 2023 +0100
+++ b/rust/vec2d/src/lib.rs	Tue Jan 03 12:05:59 2023 +0100
@@ -102,7 +102,7 @@
             slice,
             mem
         };
-        
+
         slice::from_raw_parts(
             self.data.as_ptr() as *const u8,
             self.data.len() * mem::size_of::<T>(),