memory management for openalbridge
authorkoda
Mon, 21 Jun 2010 16:08:24 +0200
changeset 3529 0e968ba12a84
parent 3516 a8c673657b79 (current diff)
parent 3528 0ad90165fde0 (diff)
child 3530 390e5048d39c
memory management for openalbridge added openalbridge as dependency of hwengine usound formatted clearly
CMakeLists.txt
hedgewars/CMakeLists.txt
hedgewars/uSound.pas
misc/libopenalbridge/CMakeLists.txt
misc/libopenalbridge/commands.c
misc/libopenalbridge/openalbridge.c
misc/libopenalbridge/openalbridge.h
misc/libopenalbridge/openalbridge_t.h
misc/libopenalbridge/tester.c
misc/libopenalbridge/wrappers.c
misc/libopenalbridge/wrappers.h
--- a/CMakeLists.txt	Fri Jun 18 14:45:05 2010 +0200
+++ b/CMakeLists.txt	Mon Jun 21 16:08:24 2010 +0200
@@ -15,10 +15,10 @@
 		FIND_PROGRAM(HGCOMMAND hg)
 		IF(HGCOMMAND)
 			exec_program(${HGCOMMAND} 
-				     ARGS identify ${CMAKE_CURRENT_SOURCE_DIR}
+				     ARGS identify -in ${CMAKE_CURRENT_SOURCE_DIR}
 				     OUTPUT_VARIABLE version_suffix
 				     )
-			STRING(REGEX REPLACE "(.*) +.*" "\\1" version_suffix ${version_suffix})
+			STRING(REGEX REPLACE "(.*) +(.*)" "\\2:\\1" version_suffix ${version_suffix})
 			MESSAGE(STATUS "Builing revision ${version_suffix}")
 			set(version_suffix ".${version_suffix}")
 #			#truncate to numbers only - trying to fix a problem described in http://www.hedgewars.org/node/2019
@@ -183,6 +183,7 @@
 endif(WITH_SERVER)
 
 add_subdirectory(hedgewars)
+add_subdirectory(misc/libopenalbridge)
 if(NOT BUILD_ENGINE_LIBRARY)
 	add_subdirectory(bin)
 	add_subdirectory(QTfrontend)
--- a/QTfrontend/about.cpp	Fri Jun 18 14:45:05 2010 +0200
+++ b/QTfrontend/about.cpp	Mon Jun 21 16:08:24 2010 +0200
@@ -76,7 +76,7 @@
             "Mac OS X/iPhone port, OpenGL-ES conversion: Vittorio Giovara &lt;<a href=\"mailto:vittorio.giovara@gmail.com\">vittorio.giovara@gmail.com</a>&gt;<br>"
             "Gamepad and Lua integration, misc effects: Mario Liebisch &lt;<a href=\"mailto:mario.liebisch@googlemail.com\">mario.liebisch@googlemail.com</a>&gt;<br>"
             "Many engine improvements and graphics: Carlos Vives &lt;<a href=\"mailto:mail@carlosvives.es\">mail@carlosvives.es</a>&gt;<br>"
-            "Don't ask: Richard Karolyi &lt;<a href=\"mailto:sheepluva@ercatec.net\">sheepluva@ercatec.net</a>&gt;<br>"
+            "Few engine and frontend improvements: Richard Karolyi &lt;<a href=\"mailto:sheepluva@ercatec.net\">sheepluva@ercatec.net</a>&gt;<br>"
             "Maze maps: Henning K&uuml;hn &lt;<a href=\"mailto:prg@cooco.de\">prg@cooco.de</a>&gt;"
             "</p><h2>" +
 
--- a/hedgewars/CMakeLists.txt	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/CMakeLists.txt	Mon Jun 21 16:08:24 2010 +0200
@@ -61,7 +61,7 @@
 	uMisc.pas
 	uRandom.pas
 	uScript.pas
-	uSHA.pas
+	adler32.pas
 	uSound.pas
 	uStats.pas
 	uStore.pas
@@ -76,6 +76,7 @@
 	SinTable.inc
 	options.inc
 	${CMAKE_CURRENT_BINARY_DIR}/config.inc
+	openalbridge
 	)
 
 if(BUILD_ENGINE_LIBRARY)
--- a/hedgewars/GSHandlers.inc	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/GSHandlers.inc	Mon Jun 21 16:08:24 2010 +0200
@@ -812,7 +812,7 @@
         end;
 
         if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9)
-           , LAND_INDESTRUCTIBLE) then
+           , lfIndestructible) then
         begin
             Gear^.X := Gear^.X + Gear^.dX;
             Gear^.Y := Gear^.Y + _1_9;
@@ -922,11 +922,11 @@
             // why the call to HedgehogStep then a further increment of X?
             if (prevX = hwRound(HHGear^.X)) and
                CheckLandValue(hwRound(HHGear^.X + SignAs(_6, HHGear^.dX)), hwRound(HHGear^.Y),
-               LAND_INDESTRUCTIBLE) then HedgehogStep(HHGear);
+               lfIndestructible) then HedgehogStep(HHGear);
 
             if (prevX = hwRound(HHGear^.X)) and
                CheckLandValue(hwRound(HHGear^.X + SignAs(_6, HHGear^.dX)), hwRound(HHGear^.Y),
-               LAND_INDESTRUCTIBLE) then HHGear^.X := HHGear^.X + SignAs(_1, HHGear^.dX);
+               lfIndestructible) then HHGear^.X := HHGear^.X + SignAs(_1, HHGear^.dX);
             HHGear^.State := HHGear^.State or gstAttacking
         end;
 
@@ -936,7 +936,7 @@
             BTSteps := 0;
             if CheckLandValue(hwRound(HHGear^.X + Gear^.dX * (cHHRadius + cBlowTorchC) + SignAs(_6,
                Gear^.dX)), hwRound(HHGear^.Y + Gear^.dY * (cHHRadius + cBlowTorchC)),
-               LAND_INDESTRUCTIBLE) then
+               lfIndestructible) then
             begin
                 Gear^.X := HHGear^.X + Gear^.dX * (cHHRadius + cBlowTorchC);
                 Gear^.Y := HHGear^.Y + Gear^.dY * (cHHRadius + cBlowTorchC);
@@ -1795,7 +1795,7 @@
     end;
 
     if CheckLandValue(hwRound(HHGear^.X), hwRound(HHGear^.Y + HHGear^.dY + SignAs(_6,Gear^.dY)),
-       LAND_INDESTRUCTIBLE) then
+       lfIndestructible) then
         HHGear^.Y := HHGear^.Y + HHGear^.dY
 end;
 
@@ -2545,7 +2545,7 @@
        or (not TestCollisionYWithGear(Gear, hwSign(Gear^.dY))
        and not TestCollisionXWithGear(Gear, hwSign(Gear^.dX)))
 // CheckLandValue returns true if the type isn't matched
-       or not CheckLandValue(hwRound(Gear^.Y), hwRound(Gear^.X), LAND_INDESTRUCTIBLE) then
+       or not CheckLandValue(hwRound(Gear^.Y), hwRound(Gear^.X), lfIndestructible) then
     begin
         //out of time or exited ground
         StopSound(Gear^.SoundChannel);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/adler32.pas	Mon Jun 21 16:08:24 2010 +0200
@@ -0,0 +1,152 @@
+unit Adler32;
+
+{ZLib - Adler32 checksum function}
+
+
+interface
+
+(*************************************************************************
+
+ DESCRIPTION     :  ZLib - Adler32 checksum function
+
+ REQUIREMENTS    :  TP5-7, D1-D7/D9-D10/D12, FPC, VP
+
+ EXTERNAL DATA   :  ---
+
+ MEMORY USAGE    :  ---
+
+ DISPLAY MODE    :  ---
+
+ REFERENCES      :  RFC 1950 (http://tools.ietf.org/html/rfc1950)
+
+
+ Version  Date      Author      Modification
+ -------  --------  -------     ------------------------------------------
+ 0.10     30.08.03  W.Ehrhardt  Initial version based on MD5 layout
+ 2.10     30.08.03  we          Common vers., XL versions for Win32
+ 2.20     27.09.03  we          FPC/go32v2
+ 2.30     05.10.03  we          STD.INC, TP5.0
+ 2.40     10.10.03  we          common version, english comments
+ 3.00     01.12.03  we          Common version 3.0
+ 3.01     22.05.05  we          Adler32UpdateXL (i,n: integer)
+ 3.02     17.12.05  we          Force $I- in Adler32File
+ 3.03     07.08.06  we          $ifdef BIT32: (const fname: shortstring...)
+ 3.04     10.02.07  we          Adler32File: no eof, XL and filemode via $ifdef
+ 3.05     04.07.07  we          BASM16: speed-up factor 15
+ 3.06     12.11.08  we          uses BTypes, Ptr2Inc and/or Str255
+ 3.07     25.04.09  we          updated RFC URL(s)
+ 3.08     19.07.09  we          D12 fix: assign with typecast string(fname)
+**************************************************************************)
+
+(*-------------------------------------------------------------------------
+ (C) Copyright 2002-2009 Wolfgang Ehrhardt
+
+ This software is provided 'as-is', without any express or implied warranty.
+ In no event will the authors be held liable for any damages arising from
+ the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software in
+    a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+----------------------------------------------------------------------------*)
+
+(*
+As per the license above, noting that this implementation of adler32 was stripped of everything we didn't need.
+That means no btypes, file loading, and the assembly version disabled.
+*)
+
+procedure Adler32Update(var adler: longint; Msg: pointer; Len: longint);
+
+implementation
+
+(*
+$ifdef BASM16
+
+procedure Adler32Update(var adler: longint; Msg: pointer; Len: longint);
+  //-update Adler32 with Msg data
+const
+  BASE = 65521; // max. prime < 65536 
+  NMAX =  5552; // max. n with 255n(n+1)/2 + (n+1)(BASE-1) < 2^32
+type
+  LH    = packed record
+            L,H: word;
+          end;
+var
+  s1,s2: longint;
+  n: integer;
+begin
+  s1 := LH(adler).L;
+  s2 := LH(adler).H;
+  while Len > 0 do begin
+    if Len<NMAX then n := Len else n := NMAX;
+    //BASM increases speed from about 52 cyc/byte to about 3.7 cyc/byte
+    asm
+                    mov  cx,[n]
+            db $66; mov  ax,word ptr [s1]
+            db $66; mov  di,word ptr [s2]
+                    les  si,[msg]
+      @@1:  db $66, $26, $0f, $b6, $1c      // movzx ebx,es:[si]
+                    inc  si
+            db $66; add  ax,bx              // inc(s1, pByte(Msg)^)
+            db $66; add  di,ax              // inc(s2, s1
+                    dec  cx
+                    jnz  @@1
+            db $66; sub  cx,cx
+                    mov  cx,BASE
+            db $66; sub  dx,dx
+            db $66; div  cx
+            db $66; mov  word ptr [s1],dx   // s1 := s1 mod BASE
+            db $66; sub  dx,dx
+            db $66; mov  ax,di
+            db $66; div  cx
+            db $66; mov  word ptr [s2],dx   // s2 := s2 mod BASE
+                    mov  word ptr [msg],si  // save offset for next chunk
+    end;
+    dec(len, n);
+  end;
+  LH(adler).L := word(s1);
+  LH(adler).H := word(s2);
+end;
+*)
+
+procedure Adler32Update(var adler: longint; Msg: pointer; Len: longint);
+  {-update Adler32 with Msg data}
+const
+  BASE = 65521; {max. prime < 65536 }
+  NMAX =  3854; {max. n with 255n(n+1)/2 + (n+1)(BASE-1) < 2^31}
+type
+  LH    = packed record
+            L,H: word;
+          end;
+var
+  s1,s2: longint;
+  i,n: integer;
+begin
+  s1 := LH(adler).L;
+  s2 := LH(adler).H;
+  while Len > 0 do begin
+    if Len<NMAX then n := Len else n := NMAX;
+    for i:=1 to n do begin
+      inc(s1, pByte(Msg)^);
+      inc(Msg);
+      inc(s2, s1);
+    end;
+    s1 := s1 mod BASE;
+    s2 := s2 mod BASE;
+    dec(len, n);
+  end;
+  LH(adler).L := word(s1);
+  LH(adler).H := word(s2);
+end;
+
+end.
--- a/hedgewars/uConsts.pas	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/uConsts.pas	Mon Jun 21 16:08:24 2010 +0200
@@ -249,10 +249,11 @@
 {$ENDIF}
 
 // To allow these to layer, going to treat them as masks. The bottom byte is reserved for objects
-    LAND_BASIC          = $8000;  // white
-    LAND_INDESTRUCTIBLE = $4000;  // red
-    LAND_OBJECT         = $2000;  // no idea
-    LAND_DAMAGED        = $1000;  // no idea
+// TODO - set lfBasic for all solid land, ensure all uses of the flags can handle multiple flag bits
+    lfBasic          = $8000;  // white
+    lfIndestructible = $4000;  // red
+    lfObject         = $2000;  // no idea
+    lfDamaged        = $1000;  // no idea
 
     cMaxPower     = 1500;
     cMaxAngle     = 2048;
--- a/hedgewars/uLand.pas	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/uLand.pas	Mon Jun 21 16:08:24 2010 +0200
@@ -57,7 +57,7 @@
 function  LandBackPixel(x, y: LongInt): LongWord;
 
 implementation
-uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, uSHA, uIO, uLandTexture;
+uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, Adler32, uIO, uLandTexture;
 
 operator=(const a, b: direction) c: Boolean;
 begin
@@ -70,20 +70,13 @@
               end;
 
 procedure LogLandDigest;
-var ctx: TSHA1Context;
-    dig: TSHA1Digest;
-    s: shortstring;
+var s: shortstring;
+    adler: LongInt;
 begin
-{$HINTS OFF}
-SHA1Init(ctx);
-{$HINTS ON}
-SHA1UpdateLongwords(ctx, @Land, sizeof(Land));
-dig:= SHA1Final(ctx);
-s:='M{'+inttostr(dig[0])+':'
-       +inttostr(dig[1])+':'
-       +inttostr(dig[2])+':'
-       +inttostr(dig[3])+':'
-       +inttostr(dig[4])+'}';
+adler:= 1;
+Adler32Update(adler, @Land, sizeof(Land));
+s:= 'M'+inttostr(adler);
+
 CheckLandDigest(s);
 SendIPCRaw(@s[0], Length(s) + 1)
 end;
@@ -561,7 +554,7 @@
 begin
 for y:= 0 to LAND_HEIGHT - 1 do
     for x:= 0 to LAND_WIDTH - 1 do
-        Land[y, x]:= LAND_BASIC;
+        Land[y, x]:= lfBasic;
 
 {$HINTS OFF}
 SetPoints(Template, pa);
@@ -582,7 +575,7 @@
          with FillPoints^[i] do
               FillLand(x, y);
 
-DrawEdge(pa, LAND_BASIC);
+DrawEdge(pa, lfBasic);
 
 MaxHedgehogs:= Template.MaxHedgehogs;
 hasGirders:= Template.hasGirders;
@@ -605,8 +598,8 @@
             else
             begin
                if Land[y, x] = 0 then
-                   Land[y, x]:= LAND_BASIC
-               else if Land[y, x] = LAND_BASIC then
+                   Land[y, x]:= lfBasic
+               else if Land[y, x] = lfBasic then
                    Land[y, x]:= 0;
             end;
     end;
@@ -978,7 +971,7 @@
 
 for x := 0 to playWidth do
     for y := off_y to LAND_HEIGHT - 1 do
-        Land[y, x] := LAND_BASIC;
+        Land[y, x] := lfBasic;
 
 for y := 0 to num_cells_y - 1 do
     for x := 0 to num_cells_x - 1 do
@@ -1079,7 +1072,7 @@
 else
 begin
     x := 0;
-    while Land[cellsize div 2 + cellsize + off_y, x] = LAND_BASIC do
+    while Land[cellsize div 2 + cellsize + off_y, x] = lfBasic do
         x := x + 1;
     while Land[cellsize div 2 + cellsize + off_y, x] = 0 do
         x := x + 1;
@@ -1165,9 +1158,9 @@
                     if ((AMask and p^[x]) = 0) then  // Tiy was having trouble generating transparent black
                         Land[cpY + y, cpX + x]:= 0
                     else if p^[x] = (AMask or RMask) then
-                        Land[cpY + y, cpX + x]:= LAND_INDESTRUCTIBLE
+                        Land[cpY + y, cpX + x]:= lfIndestructible
                     else if p^[x] = $FFFFFFFF then
-                        Land[cpY + y, cpX + x]:= LAND_BASIC;
+                        Land[cpY + y, cpX + x]:= lfBasic;
                 end;
                 p:= @(p^[tmpsurf^.pitch div 4]);
             end;
@@ -1261,15 +1254,15 @@
     for y:= 0 to LAND_HEIGHT - 1 do
         for x:= 0 to LAND_WIDTH - 1 do
             if (y < topY) or (x < leftX) or (x > rightX) then
-                Land[y, x]:= LAND_INDESTRUCTIBLE;
+                Land[y, x]:= lfIndestructible;
     // experiment hardcoding cave
     // also try basing cave dimensions on map/template dimensions, if they exist
     for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade
         begin
         for y:= topY to LAND_HEIGHT - 1 do
             begin
-            Land[y, leftX + w]:= LAND_INDESTRUCTIBLE;
-            Land[y, rightX - w]:= LAND_INDESTRUCTIBLE;
+            Land[y, leftX + w]:= lfIndestructible;
+            Land[y, rightX - w]:= lfIndestructible;
             if (y + w) mod 32 < 16 then
                 c:= AMask
             else
@@ -1285,7 +1278,7 @@
 
         for x:= leftX to rightX do
             begin
-            Land[topY + w, x]:= LAND_INDESTRUCTIBLE;
+            Land[topY + w, x]:= lfIndestructible;
             if (x + w) mod 32 < 16 then
                 c:= AMask
             else
--- a/hedgewars/uLandGraphics.pas	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/uLandGraphics.pas	Mon Jun 21 16:08:24 2010 +0200
@@ -46,19 +46,19 @@
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-        if (Land[y + dy, i] and LAND_INDESTRUCTIBLE) = 0 then
+        if (Land[y + dy, i] and lfIndestructible) = 0 then
             Land[y + dy, i]:= Value;
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-        if (Land[y - dy, i] and LAND_INDESTRUCTIBLE) = 0 then
+        if (Land[y - dy, i] and lfIndestructible) = 0 then
             Land[y - dy, i]:= Value;
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-        if (Land[y + dx, i] and LAND_INDESTRUCTIBLE) = 0 then
+        if (Land[y + dx, i] and lfIndestructible) = 0 then
             Land[y + dx, i]:= Value;
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-        if (Land[y - dx, i] and LAND_INDESTRUCTIBLE) = 0 then
+        if (Land[y - dx, i] and lfIndestructible) = 0 then
             Land[y - dx, i]:= Value;
 end;
 
@@ -145,7 +145,7 @@
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-        if (not isMap and ((Land[y + dy, i] and LAND_INDESTRUCTIBLE) = 0)) or ((Land[y + dy, i] and LAND_BASIC) <> 0) then
+        if (not isMap and ((Land[y + dy, i] and lfIndestructible) = 0)) or ((Land[y + dy, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
             LandPixels[(y + dy) div 2, i div 2]:= 0;
 {$ELSE}
@@ -153,7 +153,7 @@
 {$ENDIF}
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-        if (not isMap and ((Land[y - dy, i] and LAND_INDESTRUCTIBLE) = 0)) or ((Land[y - dy, i] and LAND_BASIC) <> 0) then
+        if (not isMap and ((Land[y - dy, i] and lfIndestructible) = 0)) or ((Land[y - dy, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
              LandPixels[(y - dy) div 2, i div 2]:= 0;
 {$ELSE}
@@ -161,7 +161,7 @@
 {$ENDIF}
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-        if (not isMap and ((Land[y + dx, i] and LAND_INDESTRUCTIBLE) = 0)) or ((Land[y + dx, i] and LAND_BASIC) <> 0) then
+        if (not isMap and ((Land[y + dx, i] and lfIndestructible) = 0)) or ((Land[y + dx, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
             LandPixels[(y + dx) div 2, i div 2]:= 0;
 {$ELSE}
@@ -169,7 +169,7 @@
 {$ENDIF}
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-        if (not isMap and ((Land[y - dx, i] and LAND_INDESTRUCTIBLE) = 0)) or ((Land[y - dx, i] and LAND_BASIC) <> 0) then
+        if (not isMap and ((Land[y - dx, i] and lfIndestructible) = 0)) or ((Land[y - dx, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
              LandPixels[(y - dx) div 2, i div 2]:= 0;
 {$ELSE}
@@ -182,7 +182,7 @@
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-       if ((Land[y + dy, i] and LAND_BASIC) <> 0) then
+       if ((Land[y + dy, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
           LandPixels[(y + dy) div 2, i div 2]:= LandBackPixel(i, y + dy)
 {$ELSE}
@@ -190,13 +190,13 @@
 {$ENDIF}
        else
 {$IFDEF DOWNSCALE}
-          if (Land[y + dy, i] = LAND_OBJECT) then LandPixels[(y + dy) div 2, i div 2]:= 0;
+          if ((Land[y + dy, i] and lfObject) <> 0) then LandPixels[(y + dy) div 2, i div 2]:= 0;
 {$ELSE}
-          if (Land[y + dy, i] = LAND_OBJECT) then LandPixels[y + dy, i]:= 0;
+          if ((Land[y + dy, i] and lfObject) <> 0) then LandPixels[y + dy, i]:= 0;
 {$ENDIF}
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-       if ((Land[y - dy, i] and LAND_BASIC) <> 0) then
+       if ((Land[y - dy, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
           LandPixels[(y - dy) div 2, i div 2]:= LandBackPixel(i, y - dy)
 {$ELSE}
@@ -204,13 +204,13 @@
 {$ENDIF}
        else
 {$IFDEF DOWNSCALE}
-          if (Land[y - dy, i] = LAND_OBJECT) then LandPixels[(y - dy) div 2, i div 2]:= 0;
+          if ((Land[y - dy, i] and lfObject) <> 0) then LandPixels[(y - dy) div 2, i div 2]:= 0;
 {$ELSE}
-          if (Land[y - dy, i] = LAND_OBJECT) then LandPixels[y - dy, i]:= 0;
+          if ((Land[y - dy, i] and lfObject) <> 0) then LandPixels[y - dy, i]:= 0;
 {$ENDIF}
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-       if ((Land[y + dx, i] and LAND_BASIC) <> 0) then
+       if ((Land[y + dx, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
            LandPixels[(y + dx) div 2, i div 2]:= LandBackPixel(i, y + dx)
 {$ELSE}
@@ -218,13 +218,13 @@
 {$ENDIF}
        else
 {$IFDEF DOWNSCALE}
-          if (Land[y + dx, i] = LAND_OBJECT) then LandPixels[(y + dx) div 2, i div 2]:= 0;
+          if ((Land[y + dx, i] and lfObject) <> 0) then LandPixels[(y + dx) div 2, i div 2]:= 0;
 {$ELSE}
-          if (Land[y + dx, i] = LAND_OBJECT) then LandPixels[y + dx, i]:= 0;
+          if ((Land[y + dx, i] and lfObject) <> 0) then LandPixels[y + dx, i]:= 0;
 {$ENDIF}
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-       if ((Land[y - dx, i] and LAND_BASIC) <> 0) then
+       if ((Land[y - dx, i] and lfBasic) <> 0) then
 {$IFDEF DOWNSCALE}
           LandPixels[(y - dx) div 2, i div 2]:= LandBackPixel(i, y - dx)
 {$ELSE}
@@ -232,9 +232,9 @@
 {$ENDIF}
        else
 {$IFDEF DOWNSCALE}
-          if (Land[y - dx, i] = LAND_OBJECT) then LandPixels[(y - dx) div 2, i div 2]:= 0;
+          if ((Land[y - dx, i] and lfObject) <> 0) then LandPixels[(y - dx) div 2, i div 2]:= 0;
 {$ELSE}
-          if (Land[y - dx, i] = LAND_OBJECT) then LandPixels[y - dx, i]:= 0;
+          if ((Land[y - dx, i] and lfObject) <> 0) then LandPixels[y - dx, i]:= 0;
 {$ENDIF}
 end;
 
@@ -243,53 +243,53 @@
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-       if ((Land[y + dy, i] and LAND_BASIC) <> 0) or (Land[y + dy, i] = LAND_OBJECT) then
+       if ((Land[y + dy, i] and lfBasic) <> 0) or ((Land[y + dy, i] and lfObject) <> 0) then
           begin
 {$IFDEF DOWNSCALE}
           LandPixels[(y + dy) div 2, i div 2]:= cExplosionBorderColor;
 {$ELSE}
           LandPixels[y + dy, i]:= cExplosionBorderColor;
 {$ENDIF}
-          Land[y + dy, i]:= Land[y + dy, i] or LAND_DAMAGED;
+          Land[y + dy, i]:= Land[y + dy, i] or lfDamaged;
           Despeckle(i, y + dy);
           LandDirty[(y + dy) div 32, i div 32]:= 1;
           end;
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-       if ((Land[y - dy, i] and LAND_BASIC) <> 0) or (Land[y - dy, i] = LAND_OBJECT) then
+       if ((Land[y - dy, i] and lfBasic) <> 0) or ((Land[y - dy, i] and lfObject) <> 0) then
           begin
 {$IFDEF DOWNSCALE}
           LandPixels[(y - dy) div 2, i div 2]:= cExplosionBorderColor;
 {$ELSE}
           LandPixels[y - dy, i]:= cExplosionBorderColor;
 {$ENDIF}
-          Land[y - dy, i]:= Land[y - dy, i] or LAND_DAMAGED;
+          Land[y - dy, i]:= Land[y - dy, i] or lfDamaged;
           Despeckle(i, y - dy);
           LandDirty[(y - dy) div 32, i div 32]:= 1;
           end;
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-       if ((Land[y + dx, i] and LAND_BASIC) <> 0) or (Land[y + dx, i] = LAND_OBJECT) then
+       if ((Land[y + dx, i] and lfBasic) <> 0) or ((Land[y + dx, i] and lfObject) <> 0) then
            begin
 {$IFDEF DOWNSCALE}
            LandPixels[(y + dx) div 2, i div 2]:= cExplosionBorderColor;
 {$ELSE}
            LandPixels[y + dx, i]:= cExplosionBorderColor;
 {$ENDIF}
-           Land[y + dx, i]:= Land[y + dx, i] or LAND_DAMAGED;
+           Land[y + dx, i]:= Land[y + dx, i] or lfDamaged;
            Despeckle(i, y + dx);
            LandDirty[(y + dx) div 32, i div 32]:= 1;
            end;
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-       if ((Land[y - dx, i] and LAND_BASIC) <> 0) or (Land[y - dx, i] = LAND_OBJECT) then
+       if ((Land[y - dx, i] and lfBasic) <> 0) or ((Land[y - dx, i] and lfObject) <> 0) then
           begin
 {$IFDEF DOWNSCALE}
           LandPixels[(y - dx) div 2, i div 2]:= cExplosionBorderColor;
 {$ELSE}
           LandPixels[y - dx, i]:= cExplosionBorderColor;
 {$ENDIF}
-          Land[y - dx, i]:= Land[y - dx, i] or LAND_DAMAGED;
+          Land[y - dx, i]:= Land[y - dx, i] or lfDamaged;
           Despeckle(i, y - dy);
           LandDirty[(y - dx) div 32, i div 32]:= 1;
           end;
@@ -377,13 +377,13 @@
     begin
     for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
         for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
-            if (Land[ty, tx] and LAND_BASIC) <> 0 then
+            if (Land[ty, tx] and lfBasic) <> 0 then
 {$IFDEF DOWNSCALE}
                 LandPixels[ty div 2, tx div 2]:= LandBackPixel(tx, ty)
 {$ELSE}
                 LandPixels[ty, tx]:= LandBackPixel(tx, ty)
 {$ENDIF}
-            else if Land[ty, tx] = LAND_OBJECT then
+            else if (Land[ty, tx] and lfObject) <> 0 then
 {$IFDEF DOWNSCALE}
                 LandPixels[ty div 2, tx div 2]:= 0;
 {$ELSE}
@@ -399,14 +399,14 @@
     begin
     for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
         for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
-            if ((Land[ty, tx] and LAND_BASIC) <> 0) or (Land[ty, tx] = LAND_OBJECT) then
+            if ((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0) then
                 begin
 {$IFDEF DOWNSCALE}
                 LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor;
 {$ELSE}
                 LandPixels[ty, tx]:= cExplosionBorderColor;
 {$ENDIF}
-                Land[ty, tx]:= Land[ty, tx] or LAND_DAMAGED;
+                Land[ty, tx]:= Land[ty, tx] or lfDamaged;
                 LandDirty[(y + dy) shr 5, i shr 5]:= 1;
                 end;
     inc(y, dY)
@@ -443,10 +443,10 @@
     ty:= hwRound(Y);
     if ((ty and LAND_HEIGHT_MASK) = 0) and
        ((tx and LAND_WIDTH_MASK) = 0) and
-       (((Land[ty, tx] and LAND_BASIC) <> 0) or 
-       (Land[ty, tx] = LAND_OBJECT)) then
+       (((Land[ty, tx] and lfBasic) <> 0) or 
+       ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        Land[ty, tx]:= Land[ty, tx] or LAND_DAMAGED;
+        Land[ty, tx]:= Land[ty, tx] or lfDamaged;
 {$IFDEF DOWNSCALE}
         LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
 {$ELSE}
@@ -470,10 +470,10 @@
     ty:= hwRound(Y);
     if ((ty and LAND_HEIGHT_MASK) = 0) and
        ((tx and LAND_WIDTH_MASK) = 0) and
-       (((Land[ty, tx] and LAND_BASIC) <> 0) or 
-       (Land[ty, tx] = LAND_OBJECT)) then
+       (((Land[ty, tx] and lfBasic) <> 0) or 
+       ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        Land[ty, tx]:= Land[ty, tx] or LAND_DAMAGED;
+        Land[ty, tx]:= Land[ty, tx] or lfDamaged;
 {$IFDEF DOWNSCALE}
         LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
 {$ELSE}
@@ -489,15 +489,15 @@
         Y:= Y + dY;
         tx:= hwRound(X);
         ty:= hwRound(Y);
-        if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and ((Land[ty, tx] and LAND_INDESTRUCTIBLE) = 0) then
+        if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and ((Land[ty, tx] and lfIndestructible) = 0) then
             begin
-            if (Land[ty, tx] and LAND_BASIC) <> 0 then
+            if (Land[ty, tx] and lfBasic) <> 0 then
 {$IFDEF DOWNSCALE}
                 LandPixels[ty div 2, tx div 2]:= LandBackPixel(tx, ty)
 {$ELSE}
                 LandPixels[ty, tx]:= LandBackPixel(tx, ty)
 {$ENDIF}
-            else if Land[ty, tx] = LAND_OBJECT then
+            else if (Land[ty, tx] and lfObject) <> 0 then
 {$IFDEF DOWNSCALE}
                 LandPixels[ty div 2, tx div 2]:= 0;
 {$ELSE}
@@ -514,10 +514,10 @@
     ty:= hwRound(Y);
     if ((ty and LAND_HEIGHT_MASK) = 0) and
        ((tx and LAND_WIDTH_MASK) = 0) and
-       (((Land[ty, tx] and LAND_BASIC) <> 0) or 
-       (Land[ty, tx] = LAND_OBJECT)) then
+       (((Land[ty, tx] and lfBasic) <> 0) or 
+       ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        Land[ty, tx]:= Land[ty, tx] or LAND_DAMAGED;
+        Land[ty, tx]:= Land[ty, tx] or lfDamaged;
 {$IFDEF DOWNSCALE}
         LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
 {$ELSE}
@@ -541,10 +541,10 @@
     ty:= hwRound(Y);
     if ((ty and LAND_HEIGHT_MASK) = 0) and
        ((tx and LAND_WIDTH_MASK) = 0) and
-       (((Land[ty, tx] and LAND_BASIC) <> 0) or 
-       (Land[ty, tx] = LAND_OBJECT)) then
+       (((Land[ty, tx] and lfBasic) <> 0) or 
+       ((Land[ty, tx] and lfObject) <> 0)) then
         begin
-        Land[ty, tx]:= Land[ty, tx] or LAND_DAMAGED;
+        Land[ty, tx]:= Land[ty, tx] or lfDamaged;
 {$IFDEF DOWNSCALE}
         LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
 {$ELSE}
@@ -620,7 +620,7 @@
             for x:= 0 to Pred(w) do
                 if PLongword(@(p^[x * 4]))^ <> 0 then
                    begin
-                   Land[cpY + y, cpX + x]:= LAND_OBJECT;
+                   Land[cpY + y, cpX + x]:= lfObject;
 {$IFDEF DOWNSCALE}
                    LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= PLongword(@(p^[x * 4]))^
 {$ELSE}
@@ -644,7 +644,7 @@
 function Despeckle(X, Y: LongInt): boolean;
 var nx, ny, i, j, c: LongInt;
 begin
-if (Land[Y, X] > 255) and ((Land[Y, X] and LAND_INDESTRUCTIBLE) = 0) and ((Land[Y, X] and LAND_DAMAGED) <> 0)then // check neighbours
+if ((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0) then // check neighbours
     begin
     c:= 0;
     for i:= -1 to 1 do
@@ -661,9 +661,9 @@
     if c < 4 then // 0-3 neighbours
         begin
 {$IFDEF DOWNSCALE}
-        if (Land[Y, X] and LAND_BASIC) <> 0 then LandPixels[Y div 2, X div 2]:= LandBackPixel(X, Y) else LandPixels[Y div 2, X div 2]:= 0;
+        if (Land[Y, X] and lfBasic) <> 0 then LandPixels[Y div 2, X div 2]:= LandBackPixel(X, Y) else LandPixels[Y div 2, X div 2]:= 0;
 {$ELSE}
-        if (Land[Y, X] and LAND_BASIC) <> 0 then LandPixels[Y, X]:= LandBackPixel(X, Y) else LandPixels[Y, X]:= 0;
+        if (Land[Y, X] and lfBasic) <> 0 then LandPixels[Y, X]:= LandBackPixel(X, Y) else LandPixels[Y, X]:= 0;
 {$ENDIF}
         Land[Y, X]:= 0;
         exit(true);
--- a/hedgewars/uLandObjects.pas	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/uLandObjects.pas	Mon Jun 21 16:08:24 2010 +0200
@@ -93,7 +93,7 @@
             LandPixels[cpY + y, cpX + x]:= p^[x];
 {$ENDIF}
         if ((Land[cpY + y, cpX + x] and $FF00) = 0) and ((p^[x] and AMask) <> 0) then 
-            Land[cpY + y, cpX + x]:= LAND_OBJECT
+            Land[cpY + y, cpX + x]:= lfObject
         end;
     p:= @(p^[Image^.pitch shr 2])
     end;
@@ -211,23 +211,31 @@
 end;
 
 function CheckLand(rect: TSDL_Rect; dX, dY, Color: Longword): boolean;
-var i: LongInt;
+var tmpx, tmpx2, tmpy, tmpy2, bx, by: LongInt;
     bRes: boolean = true;
 begin
 inc(rect.x, dX);
 inc(rect.y, dY);
-i:= 0;
+bx:= rect.x + rect.w;
+by:= rect.y + rect.h;
 {$WARNINGS OFF}
-while (i <= rect.w) and bRes do
+tmpx:= rect.x;
+tmpx2:= bx;
+while (tmpx <= bx - rect.w div 2 - 1) and bRes do
       begin
-      bRes:= (Land[rect.y, rect.x + i] = Color) and (Land[rect.y + rect.h, rect.x + i] = Color);
-      inc(i)
+      bRes:= (Land[rect.y, tmpx] = Color) and (Land[by, tmpx] = Color) and
+             (Land[rect.y, tmpx2] = Color) and (Land[by, tmpx2] = Color);
+      inc(tmpx);
+      dec(tmpx2)
       end;
-i:= 0;
-while (i <= rect.h) and bRes do
+tmpy:= rect.y+1;
+tmpy2:= by-1;
+while (tmpy <= by - rect.h div 2 - 1) and bRes do
       begin
-      bRes:= (Land[rect.y + i, rect.x] = Color) and (Land[rect.y + i, rect.x + rect.w] = Color);
-      inc(i)
+      bRes:= (Land[tmpy, rect.x] = Color) and (Land[tmpy, bx] = Color) and
+             (Land[tmpy2, rect.x] = Color) and (Land[tmpy2, bx] = Color);
+      inc(tmpy);
+      dec(tmpy2)
       end;
 {$WARNINGS ON}
 CheckLand:= bRes;
@@ -238,7 +246,7 @@
     bRes: boolean;
 begin
 with Obj do
-     if CheckLand(inland, x, y, LAND_BASIC) then
+     if CheckLand(inland, x, y, lfBasic) then
         begin
         bRes:= true;
         i:= 1;
@@ -318,7 +326,7 @@
     repeat
         y:= 8;
         repeat
-            if CheckLand(r, x, y - 8, LAND_BASIC)
+            if CheckLand(r, x, y - 8, lfBasic)
             and not CheckIntersect(x, y, Width, Height) then
             begin
             ar[cnt].x:= x;
--- a/hedgewars/uSound.pas	Fri Jun 18 14:45:05 2010 +0200
+++ b/hedgewars/uSound.pas	Mon Jun 21 16:08:24 2010 +0200
@@ -40,8 +40,8 @@
 procedure PlaySound(snd: TSound; keepPlaying: boolean);
 procedure PlaySound(snd: TSound; voicepack: PVoicepack);
 procedure PlaySound(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean);
-function LoopSound(snd: TSound): LongInt;
-function LoopSound(snd: TSound; voicepack: PVoicepack): LongInt;
+function  LoopSound(snd: TSound): LongInt;
+function  LoopSound(snd: TSound; voicepack: PVoicepack): LongInt;
 procedure PlayMusic;
 procedure PauseMusic;
 procedure ResumeMusic;
@@ -65,14 +65,14 @@
 var i: Longword;
 begin
 i:= 0;
-while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do
+    while (voicepacks[i].name <> name) and (voicepacks[i].name <> '') do
     begin
-    inc(i);
-    TryDo(i <= cMaxTeams, 'Engine bug: AskForVoicepack i > cMaxTeams', true)
+        inc(i);
+        TryDo(i <= cMaxTeams, 'Engine bug: AskForVoicepack i > cMaxTeams', true)
     end;
 
-voicepacks[i].name:= name;
-AskForVoicepack:= @voicepacks[i]
+    voicepacks[i].name:= name;
+    AskForVoicepack:= @voicepacks[i]
 end;
 
 procedure InitSound;
@@ -110,22 +110,22 @@
 var i: TSound;
     t: Longword;
 begin
-for t:= 0 to cMaxTeams do
-    if voicepacks[t].name <> '' then
-        for i:= Low(TSound) to High(TSound) do
-            if voicepacks[t].chunks[i] <> nil then
-                Mix_FreeChunk(voicepacks[t].chunks[i]);
+    for t:= 0 to cMaxTeams do
+        if voicepacks[t].name <> '' then
+            for i:= Low(TSound) to High(TSound) do
+                if voicepacks[t].chunks[i] <> nil then
+                    Mix_FreeChunk(voicepacks[t].chunks[i]);
 
-if Mus <> nil then
-    Mix_FreeMusic(Mus);
+    if Mus <> nil then
+        Mix_FreeMusic(Mus);
 
 {$IFDEF SDL_MIXER_NEWER}
-// make sure all instances of sdl_mixer are unloaded before continuing
-while Mix_Init(0) <> 0 do
-    Mix_Quit();
+    // make sure all instances of sdl_mixer are unloaded before continuing
+    while Mix_Init(0) <> 0 do
+        Mix_Quit();
 {$ENDIF}    
 
-Mix_CloseAudio();
+    Mix_CloseAudio();
 end;
 
 procedure SoundLoad;
@@ -137,28 +137,28 @@
 
     defVoicepack:= AskForVoicepack('Default');
 
-for i:= Low(TSound) to High(TSound) do
-    if (Soundz[i].Path <> ptVoices) and (Soundz[i].FileName <> '') then
+    for i:= Low(TSound) to High(TSound) do
+        if (Soundz[i].Path <> ptVoices) and (Soundz[i].FileName <> '') then
         begin
-        s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName;
-        WriteToConsole(msgLoading + s + ' ');
-        defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
-        TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true);
-        WriteLnToConsole(msgOK);
+            s:= Pathz[Soundz[i].Path] + '/' + Soundz[i].FileName;
+            WriteToConsole(msgLoading + s + ' ');
+            defVoicepack^.chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
+            TryDo(defVoicepack^.chunks[i] <> nil, msgFailed, true);
+            WriteLnToConsole(msgOK);
         end;
 
-for t:= 0 to cMaxTeams do
-    if voicepacks[t].name <> '' then
-        for i:= Low(TSound) to High(TSound) do
-            if (Soundz[i].Path = ptVoices) and (Soundz[i].FileName <> '') then
+    for t:= 0 to cMaxTeams do
+        if voicepacks[t].name <> '' then
+            for i:= Low(TSound) to High(TSound) do
+                if (Soundz[i].Path = ptVoices) and (Soundz[i].FileName <> '') then
                 begin
-                s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName;
-                WriteToConsole(msgLoading + s + ' ');
-                voicepacks[t].chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
-                if voicepacks[t].chunks[i] = nil then
-                    WriteLnToConsole(msgFailed)
-                else
-                    WriteLnToConsole(msgOK)
+                    s:= Pathz[Soundz[i].Path] + '/' + voicepacks[t].name + '/' + Soundz[i].FileName;
+                    WriteToConsole(msgLoading + s + ' ');
+                    voicepacks[t].chunks[i]:= Mix_LoadWAV_RW(SDL_RWFromFile(Str2PChar(s), 'rb'), 1);
+                    if voicepacks[t].chunks[i] = nil then
+                        WriteLnToConsole(msgFailed)
+                    else
+                        WriteLnToConsole(msgOK)
                 end;
 end;
 
@@ -179,15 +179,16 @@
 
 procedure PlaySound(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean);
 begin
-if (not isSoundEnabled) or fastUntilLag then exit;
-
-if keepPlaying and (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then
-    exit;
+    if (not isSoundEnabled) or fastUntilLag then
+        exit;
 
-if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then
-    lastChan[snd]:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], 0, -1)
-else
-    lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1)
+    if keepPlaying and (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then
+        exit;
+
+    if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then
+        lastChan[snd]:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], 0, -1)
+    else
+        lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1)
 end;
 
 function LoopSound(snd: TSound): LongInt;
@@ -197,76 +198,79 @@
 
 function LoopSound(snd: TSound; voicepack: PVoicepack): LongInt;
 begin
-if (not isSoundEnabled) or fastUntilLag then
+    if (not isSoundEnabled) or fastUntilLag then
     begin
-    LoopSound:= -1;
-    exit
+        LoopSound:= -1;
+        exit
     end;
 
-if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then
-    LoopSound:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], -1, -1)
-else
-    LoopSound:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], -1, -1)
+    if (voicepack <> nil) and (voicepack^.chunks[snd] <> nil) then
+        LoopSound:= Mix_PlayChannelTimed(-1, voicepack^.chunks[snd], -1, -1)
+    else
+        LoopSound:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], -1, -1)
 end;
 
 procedure StopSound(snd: TSound);
 begin
-if not isSoundEnabled then exit;
-if (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then
+    if not isSoundEnabled then exit;
+    if (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then
     begin
-    Mix_HaltChannel(lastChan[snd]);
-    lastChan[snd]:= -1;
+        Mix_HaltChannel(lastChan[snd]);
+        lastChan[snd]:= -1;
     end;
 end;
 
 procedure StopSound(chn: LongInt);
 begin
-if not isSoundEnabled then exit;
-if (chn <> -1) and (Mix_Playing(chn) <> 0) then Mix_HaltChannel(chn);
+    if not isSoundEnabled then exit;
+
+    if (chn <> -1) and (Mix_Playing(chn) <> 0) then
+        Mix_HaltChannel(chn);
 end;
 
 procedure PlayMusic;
 var s: shortstring;
 begin
-if (not isSoundEnabled)
-    or (MusicFN = '')
-    or (not isMusicEnabled) then exit;
+    if (not isSoundEnabled) or (MusicFN = '') or (not isMusicEnabled) then
+        exit;
+
+    s:= PathPrefix + '/Music/' + MusicFN;
+    WriteToConsole(msgLoading + s + ' ');
 
-s:= PathPrefix + '/Music/' + MusicFN;
-WriteToConsole(msgLoading + s + ' ');
+    Mus:= Mix_LoadMUS(Str2PChar(s));
+    TryDo(Mus <> nil, msgFailed, false);
+    WriteLnToConsole(msgOK);
 
-Mus:= Mix_LoadMUS(Str2PChar(s));
-TryDo(Mus <> nil, msgFailed, false);
-WriteLnToConsole(msgOK);
-
-SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false)
+    SDLTry(Mix_FadeInMusic(Mus, -1, 3000) <> -1, false)
 end;
 
 function ChangeVolume(voldelta: LongInt): LongInt;
 begin
-if not isSoundEnabled then
-    exit(0);
+    if not isSoundEnabled then
+        exit(0);
 
-inc(Volume, voldelta);
-if Volume < 0 then Volume:= 0;
-Mix_Volume(-1, Volume);
-Volume:= Mix_Volume(-1, -1);
-if isMusicEnabled then Mix_VolumeMusic(Volume * 4 div 8);
-ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME
+    inc(Volume, voldelta);
+    if Volume < 0 then Volume:= 0;
+    Mix_Volume(-1, Volume);
+    Volume:= Mix_Volume(-1, -1);
+    if isMusicEnabled then Mix_VolumeMusic(Volume * 4 div 8);
+    ChangeVolume:= Volume * 100 div MIX_MAX_VOLUME
 end;
 
 procedure PauseMusic;
 begin
-if (MusicFN = '') or (not isMusicEnabled) then exit;
+    if (MusicFN = '') or (not isMusicEnabled) then
+        exit;
 
-Mix_PauseMusic(Mus);
+    Mix_PauseMusic(Mus);
 end;
 
 procedure ResumeMusic;
 begin
-if (MusicFN = '') or (not isMusicEnabled) then exit;
+    if (MusicFN = '') or (not isMusicEnabled) then
+        exit;
 
-Mix_ResumeMusic(Mus);
+    Mix_ResumeMusic(Mus);
 end;
 
 procedure initModule;
--- a/misc/libopenalbridge/CMakeLists.txt	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/CMakeLists.txt	Mon Jun 21 16:08:24 2010 +0200
@@ -7,9 +7,7 @@
 set(LIBRARY_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH})
 
 #list of source files for libraries
-set(openal_src
-	openalbridge.c loaders.c wrappers.c errlib.c
-)
+set(openal_src openalbridge.c loaders.c wrappers.c commands.c)
 
 #build a static library for human systems
 set (build_type STATIC)
@@ -17,9 +15,7 @@
 #visualstudio and windows in general don't like static linking, so we're building the library in shared mode
 if(WIN32)
 #workaround for visualstudio (wants headers in the source list)
-	set(openal_src
-		openalbridge.h openalbridge_t.h loaders.h wrappers.h globals.h oggvorbis.h errlib.h ${openal_src}
-	)
+	set(openal_src *.h ${openal_src})
 #deps for the shared library
 	link_libraries(${VORBISFILE_LIBRARY})
 	link_libraries(${VORBIS_LIBRARY})
@@ -39,3 +35,8 @@
 #install it in the executable directory
 	install(TARGETS openalbridge DESTINATION bin)
 endif(WIN32)
+
+#type make openalbridge_test to get a small executable test
+add_executable(openalbridge_test "${hedgewars_SOURCE_DIR}/misc/libopenalbridge/tester.c")
+target_link_libraries(openalbridge_test openalbridge ${OPENAL_LIBRARY} ${OGGVORBIS_LIBRARIES})
+
--- a/misc/libopenalbridge/commands.c	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/commands.c	Mon Jun 21 16:08:24 2010 +0200
@@ -92,8 +92,6 @@
             fprintf(stderr,"(Bridge Warning) - failed to play sound %d\n", index);
             return;
         }
-        
-        the_sounds[index].stats++;
     }
 }
 
--- a/misc/libopenalbridge/openalbridge.c	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/openalbridge.c	Mon Jun 21 16:08:24 2010 +0200
@@ -34,22 +34,14 @@
 
 // Initialize an OpenAL contex and allocate memory space for data and buffers
 // It can be called twice to increase the cache size
-int openal_init (int memorysize) {
+int openal_init (void) {
     ALCcontext *context;
     ALCdevice *device;
     int i;
         
     // reuse old context and resize the existing 
     if (openal_ready() == AL_TRUE) {
-        cache_size += memorysize;
-        fprintf(stderr,"(Bridge Info) - already initialized, resizing cache to %d\n", cache_size);
-        the_sounds = (al_sound_t *)Realloc (the_sounds, sizeof(al_sound_t) * cache_size);
-        for (i = cache_size - memorysize; i < cache_size; i++) {
-            the_sounds[i].filename = NULL;
-            the_sounds[i].buffer = -1;
-            the_sounds[i].source_index = -1;
-            the_sounds[i].stats = 0;
-        }
+        fprintf(stderr,"(Bridge Info) - already initialized\n");
         instances_number++;
         return AL_TRUE;
     }
@@ -57,12 +49,9 @@
     cache_pointer = 0;
     instances_number++;
     
-    // set the memory dimentsion and the increment width when reallocating
-    if (memorysize <= 0)
-        cache_size = 50;
-    else
-        cache_size = memorysize;
-
+    // initial memory size
+    cache_size = 50;
+    
     // open hardware device if present
     device = alcOpenDevice(NULL);
     sources_number = 16;
@@ -110,12 +99,8 @@
     }
 
     the_sounds = (al_sound_t *)Malloc (sizeof(al_sound_t) * cache_size);
-    for (i = 0; i < cache_size; i++) {
-        the_sounds[i].filename = NULL;
-        the_sounds[i].buffer = -1;
-        the_sounds[i].source_index = -1;
-        the_sounds[i].stats = 0;
-    }
+    for (i = 0; i < cache_size; i++)
+        the_sounds[i] = new_sound_el();
 
     alGetError();
     return AL_TRUE;
@@ -135,15 +120,16 @@
 
     instances_number--;
     if (instances_number > 0) {
+        // release memory only when last session ends
         return;
     }
     
-    //TODO: free other stuff also
-    for (i = 0; i < cache_size; i++)
-        alDeleteBuffers (1, &the_sounds[i].buffer);
+    for (i = 0; i < cache_size; i++) {
+        openal_unloadfile(i);
+    }
     free(the_sounds);
 
-    alSourceStopv	(sources_number, Sources);
+    alSourceStopv (sources_number, Sources);
     alDeleteSources (sources_number, Sources);
 
     free(Sources);
@@ -174,8 +160,8 @@
     ALenum format, error;
     ALsizei bitsize, freq;
     uint32_t fileformat;
-    al_sound_t soundData;
-    int len, i;
+    al_sound_t sound_data;
+    int len, i, index = -1;
     char *data;
     FILE *fp;
     
@@ -193,16 +179,24 @@
 #endif
             return i;
         }
+        // if we don't have memory available search for a free element
+        if (cache_pointer >= cache_size)
+            if (the_sounds[i].is_used == AL_FALSE)
+                index = i; 
     }
 
-    if (cache_pointer >= cache_size) {
-        fprintf(stderr,"(Bridge ERROR) - Cache size limit reached; consider allocating more space\n", filename);
-        return -2;
-    }
+    if (index == -1 && cache_pointer >= cache_size) {
+        fprintf(stderr,"(Bridge Info) - No free spots found; doubling cache size\n", filename);
+        cache_size *= 2;
+        the_sounds = (al_sound_t *)Realloc (the_sounds, sizeof(al_sound_t) * cache_size);
+        for (i = cache_size - 50; i < cache_size; i++) 
+            the_sounds[i] = new_sound_el();
+    } else 
+        index = ++cache_pointer;
+    
     
     // detect the file format, as written in the first 4 bytes of the header
     fp = Fopen (filename, "rb");
-
     if (fp == NULL) {
         fprintf(stderr,"(Bridge ERROR) - File %s not loaded\n", filename);
         return -3;
@@ -210,7 +204,6 @@
 
     error = fread (&fileformat, sizeof(uint32_t), 1, fp);
     fclose (fp);
-
     if (error < 0) {
         fprintf(stderr,"(Bridge ERROR) - File %s is too short\n", filename);
         return -4;
@@ -231,26 +224,26 @@
 
     if (error != 0) {
         fprintf(stderr,"(Bridge ERROR) - error loading file %s\n", filename);
-        free(data);
+        if(data)
+            free(data);
         return -6;
     }
 
-    alGenBuffers(1, &soundData.buffer);
-    soundData.filename = filename;
-    soundData.source_index = -1;
-    soundData.stats = 0;
+    // alGenBuffers happens here
+    sound_data = init_sound_el(filename);
     
     if (AL_NO_ERROR != alGetError()) {
-        fprintf(stderr,"(Bridge ERROR) - Failed to allocate memory for buffers\n");
+        fprintf(stderr,"(Bridge ERROR) - Failed to allocate memory for buffer %d\n", index);
+        free(data);
         return -5;
     }
     
     // copy pcm data in one buffer and free it
-    alBufferData(soundData.buffer, format, data, bitsize, freq);
+    alBufferData(sound_data.buffer, format, data, bitsize, freq);
     free(data);
 
     if (AL_NO_ERROR != alGetError()) {
-        fprintf(stderr,"(Bridge ERROR) - Failed to write data to buffers\n");
+        fprintf(stderr,"(Bridge ERROR) - Failed to write data to buffer %d\n", index);
         return -8;
     }
     
@@ -260,6 +253,21 @@
     fprintf(stderr,"(Bridge Info) - successfully loaded %s\n", filename);
 
     // returns the index of the source you just loaded, increments it and exits
-    the_sounds[cache_pointer] = soundData;
-    return cache_pointer++;
+    the_sounds[index] = sound_data;
+    return index;
 }
+
+
+void openal_unloadfile (uint32_t index) {
+    ALint state;
+
+    if (openal_ready() == AL_TRUE && index < cache_size && the_sounds[index].is_used == AL_TRUE) {
+        alGetSourcei (Sources[the_sounds[index].source_index], AL_SOURCE_STATE, &state);
+        if (state == AL_PLAYING || state == AL_PAUSED)
+            openal_stopsound(index);
+        
+        // free memory and 
+        alDeleteBuffers (1, &the_sounds[index].buffer);
+        the_sounds[index] = new_sound_el();
+    }
+}
\ No newline at end of file
--- a/misc/libopenalbridge/openalbridge.h	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/openalbridge.h	Mon Jun 21 16:08:24 2010 +0200
@@ -27,7 +27,7 @@
 #endif
 
     // init audio context and allocate memory
-    int openal_init               (int memorysize);
+    int openal_init               (void);
 
     // close audio subsytem and free memory
     void openal_close             (void);
--- a/misc/libopenalbridge/openalbridge_t.h	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/openalbridge_t.h	Mon Jun 21 16:08:24 2010 +0200
@@ -32,7 +32,7 @@
     const char *filename;       // name of the sound file
     ALuint buffer;              // actual sound content
     uint32_t source_index;      // index of the associated source
-    uint32_t stats;             // number of times the sound has been played
+    ALboolean is_used;          // tells if the element can be overwritten
 } al_sound_t;
 #pragma pack()
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libopenalbridge/tester.c	Mon Jun 21 16:08:24 2010 +0200
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include "openalbridge.h"
+
+int main (int argc, int **argv) {
+    
+    openal_init();
+    
+    openal_close();
+    
+    return 0;
+}
\ No newline at end of file
--- a/misc/libopenalbridge/wrappers.c	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/wrappers.c	Mon Jun 21 16:08:24 2010 +0200
@@ -44,7 +44,7 @@
 }
 
 
-FILE *Fopen (const char *fname, char *mode)	{
+FILE *Fopen (const char *fname, char *mode) {
     FILE *fp;
 
     fp = fopen(fname,mode);
@@ -55,3 +55,24 @@
 }
 
 
+al_sound_t new_sound_el (void) {
+    al_sound_t sound;
+    
+    sound.filename = NULL;
+    sound.buffer = -1;
+    sound.source_index = -1;
+    sound.is_used = AL_FALSE;
+
+    return sound;
+}
+
+al_sound_t init_sound_el (const char *str) {
+    al_sound_t sound;
+    
+    sound.filename = str;
+    sound.source_index = -1;
+    sound.is_used = AL_TRUE;
+    alGenBuffers(1, &sound.buffer);
+
+    return sound;
+}
--- a/misc/libopenalbridge/wrappers.h	Fri Jun 18 14:45:05 2010 +0200
+++ b/misc/libopenalbridge/wrappers.h	Mon Jun 21 16:08:24 2010 +0200
@@ -26,5 +26,7 @@
 void *Realloc (void *aptr, size_t nbytes);
 FILE *Fopen (const char *fname, char *mode);
 void helper_fade (void *tmp);
+al_sound_t new_sound_el (void);
+al_sound_t init_sound_el (const char *str);
 
 #endif /*_OALB_WRAPPERS_H*/