DEADSOFTWARE

did the same thing for binary heap
[d2df-sdl.git] / src / game / g_map.pas
index 5d4f8d87cb5b0ab9a7a9c615b429496d1a6f572f..227835321cad0e6916b103de085d75eb0bafef5f 100644 (file)
@@ -22,7 +22,7 @@ interface
 uses
   SysUtils, Classes,
   e_graphics, g_basic, MAPDEF, g_textures,
-  g_phys, wadreader, g_panel, g_grid, md5, binheap, xprofiler, xparser, xdynrec;
+  g_phys, utils, g_panel, g_grid, md5, binheap, xprofiler, xparser, xdynrec;
 
 type
   TMapInfo = record
@@ -59,7 +59,7 @@ type
 
 function  g_Map_Load(Res: String): Boolean;
 function  g_Map_GetMapInfo(Res: String): TMapInfo;
-function  g_Map_GetMapsList(WADName: String): SArray;
+function  g_Map_GetMapsList(WADName: String): SSArray;
 function  g_Map_Exist(Res: String): Boolean;
 procedure g_Map_Free(freeTextures: Boolean=true);
 procedure g_Map_Update();
@@ -202,6 +202,14 @@ const
   GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore);
 
 
+type
+  TBinHeapPanelDrawCmp = class
+  public
+    class function less (const a, b: TPanel): Boolean; inline;
+  end;
+
+  TBinHeapPanelDraw = specialize TBinaryHeapBase<TPanel, TBinHeapPanelDrawCmp>;
+
 var
   gWalls: TPanelArray;
   gRenderBackgrounds: TPanelArray;
@@ -224,7 +232,7 @@ var
   gdbg_map_use_accel_render: Boolean = true;
   gdbg_map_use_accel_coldet: Boolean = true;
   profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
-  gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
+  gDrawPanelList: TBinHeapPanelDraw = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()`
 
   gCurrentMap: TDynRecord = nil;
   gCurrentMapFileName: AnsiString = ''; // so we can skip texture reloading
@@ -247,7 +255,7 @@ uses
   GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG,
   g_options, g_triggers, g_player,
   Math, g_monsters, g_saveload, g_language, g_netmsg,
-  utils, sfs, xstreams, hashtable,
+  sfs, xstreams, hashtable, wadreader,
   ImagingTypes, Imaging, ImagingUtility,
   ImagingGif, ImagingNetworkGraphics;
 
@@ -257,6 +265,21 @@ const
   FLAG_SIGNATURE = $47414C46; // 'FLAG'
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+procedure mapWarningCB (const msg: AnsiString; line, col: Integer);
+begin
+  if (line > 0) then
+  begin
+    e_LogWritefln('parse error at (%s,%s): %s', [line, col, msg], TMsgType.Warning);
+  end
+  else
+  begin
+    e_LogWritefln('parse error: %s', [msg], TMsgType.Warning);
+  end;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
 var
   panByGUID: array of TPanel = nil;
 
@@ -491,20 +514,16 @@ begin
 end;
 
 
-function dplLess (a, b: TObject): Boolean;
-var
-  pa, pb: TPanel;
+class function TBinHeapPanelDrawCmp.less (const a, b: TPanel): Boolean; inline;
 begin
-  pa := TPanel(a);
-  pb := TPanel(b);
-  if (pa.tag < pb.tag) then begin result := true; exit; end;
-  if (pa.tag > pb.tag) then begin result := false; exit; end;
-  result := (pa.arrIdx < pb.arrIdx);
+  if (a.tag < b.tag) then begin result := true; exit; end;
+  if (a.tag > b.tag) then begin result := false; exit; end;
+  result := (a.arrIdx < b.arrIdx);
 end;
 
 procedure dplClear ();
 begin
-  if (gDrawPanelList = nil) then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
+  if (gDrawPanelList = nil) then gDrawPanelList := TBinHeapPanelDraw.Create() else gDrawPanelList.clear();
 end;
 
 
@@ -854,7 +873,7 @@ end;
 function CreateNullTexture(RecName: String): Integer;
 begin
   RecName := toLowerCase1251(RecName);
-  if (TextNameHash = nil) then TextNameHash := hashNewStrInt();
+  if (TextNameHash = nil) then TextNameHash := THashStrInt.Create();
   if TextNameHash.get(RecName, result) then exit; // i found her!
 
   SetLength(Textures, Length(Textures)+1);
@@ -881,11 +900,11 @@ var
   a, ResLength: Integer;
 begin
   RecName := toLowerCase1251(RecName);
-  if (TextNameHash = nil) then TextNameHash := hashNewStrInt();
+  if (TextNameHash = nil) then TextNameHash := THashStrInt.Create();
   if TextNameHash.get(RecName, result) then
   begin
     // i found her!
-    //e_LogWritefln('texture ''%s'' already loaded', [RecName]);
+    //e_LogWritefln('texture ''%s'' already loaded (%s)', [RecName, result]);
     exit;
   end;
 
@@ -953,7 +972,9 @@ begin
     SetLength(Textures, Length(Textures)+1);
     if not e_CreateTextureMem(TextureData, ResLength, Textures[High(Textures)].TextureID) then
     begin
+      e_WriteLog(Format('Error loading texture %s', [RecName]), TMsgType.Warning);
       SetLength(Textures, Length(Textures)-1);
+      result := -1;
       Exit;
     end;
     e_GetTextureSize(Textures[High(Textures)].TextureID, @Textures[High(Textures)].Width, @Textures[High(Textures)].Height);
@@ -967,10 +988,10 @@ begin
   else // Íåò òàêîãî ðåóñðñà â WAD'å
   begin
     //e_WriteLog(Format('SHIT! Error loading texture %s : %s', [RecName, g_ExtractFilePathName(RecName)]), MSG_WARNING);
-    if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt();
+    if (BadTextNameHash = nil) then BadTextNameHash := THashStrInt.Create();
     if log and (not BadTextNameHash.get(RecName, a)) then
     begin
-      e_WriteLog(Format('Error loading texture %s', [RecName]), MSG_WARNING);
+      e_WriteLog(Format('Error loading texture %s', [RecName]), TMsgType.Warning);
       //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
     end;
     BadTextNameHash.put(RecName, -1);
@@ -997,11 +1018,11 @@ var
   f, c, frdelay, frloop: Integer;
 begin
   RecName := toLowerCase1251(RecName);
-  if (TextNameHash = nil) then TextNameHash := hashNewStrInt();
+  if (TextNameHash = nil) then TextNameHash := THashStrInt.Create();
   if TextNameHash.get(RecName, result) then
   begin
     // i found her!
-    //e_LogWritefln('animated texture ''%s'' already loaded', [RecName]);
+    //e_LogWritefln('animated texture ''%s'' already loaded (%s)', [RecName, result]);
     exit;
   end;
 
@@ -1009,7 +1030,7 @@ begin
 
   //e_LogWritefln('*** Loading animated texture "%s"', [RecName]);
 
-  if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt();
+  if (BadTextNameHash = nil) then BadTextNameHash := THashStrInt.Create();
   if BadTextNameHash.get(RecName, f) then
   begin
     //e_WriteLog(Format('no animation texture %s (don''t worry)', [RecName]), MSG_NOTIFY);
@@ -1027,10 +1048,10 @@ begin
 
     if not WAD.GetResource(g_ExtractFilePathName(RecName), TextureWAD, ResLength, log) then
     begin
-      if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt();
+      if (BadTextNameHash = nil) then BadTextNameHash := THashStrInt.Create();
       if log and (not BadTextNameHash.get(RecName, f)) then
       begin
-        e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING);
+        e_WriteLog(Format('Error loading animation texture %s', [RecName]), TMsgType.Warning);
         //e_WriteLog(Format('WAD Reader error: %s', [WAD.GetLastErrorStr]), MSG_WARNING);
       end;
       BadTextNameHash.put(RecName, -1);
@@ -1049,7 +1070,7 @@ begin
 
     if ResLength < 6 then
     begin
-      e_WriteLog(Format('Animated texture file "%s" too short', [RecName]), MSG_WARNING);
+      e_WriteLog(Format('Animated texture file "%s" too short', [RecName]), TMsgType.Warning);
       BadTextNameHash.put(RecName, -1);
       exit;
     end;
@@ -1061,7 +1082,7 @@ begin
       // íåò, ýòî ñóïåðìåí!
       if not WAD.ReadMemory(TextureWAD, ResLength) then
       begin
-        e_WriteLog(Format('Animated texture WAD file "%s" is invalid', [RecName]), MSG_WARNING);
+        e_WriteLog(Format('Animated texture WAD file "%s" is invalid', [RecName]), TMsgType.Warning);
         BadTextNameHash.put(RecName, -1);
         exit;
       end;
@@ -1069,7 +1090,7 @@ begin
       // ×èòàåì INI-ðåñóðñ àíèì. òåêñòóðû è çàïîìèíàåì åãî óñòàíîâêè:
       if not WAD.GetResource('TEXT/ANIM', TextData, ResLength) then
       begin
-        e_WriteLog(Format('Animated texture file "%s" has invalid INI', [RecName]), MSG_WARNING);
+        e_WriteLog(Format('Animated texture file "%s" has invalid INI', [RecName]), TMsgType.Warning);
         BadTextNameHash.put(RecName, -1);
         exit;
       end;
@@ -1079,7 +1100,7 @@ begin
       TextureResource := cfg.ReadStr('', 'resource', '');
       if TextureResource = '' then
       begin
-        e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), MSG_WARNING);
+        e_WriteLog(Format('Animated texture WAD file "%s" has no "resource"', [RecName]), TMsgType.Warning);
         BadTextNameHash.put(RecName, -1);
         exit;
       end;
@@ -1096,7 +1117,7 @@ begin
       // ×èòàåì ðåñóðñ òåêñòóð (êàäðîâ) àíèì. òåêñòóðû â ïàìÿòü:
       if not WAD.GetResource('TEXTURES/'+TextureResource, TextureData, ResLength) then
       begin
-        e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), MSG_WARNING);
+        e_WriteLog(Format('Animated texture WAD file "%s" has no texture "%s"', [RecName, 'TEXTURES/'+TextureResource]), TMsgType.Warning);
         BadTextNameHash.put(RecName, -1);
         exit;
       end;
@@ -1121,10 +1142,10 @@ begin
         end
         else
         begin
-          if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt();
+          if (BadTextNameHash = nil) then BadTextNameHash := THashStrInt.Create();
           if log and (not BadTextNameHash.get(RecName, f)) then
           begin
-            e_WriteLog(Format('Error loading animation texture %s', [RecName]), MSG_WARNING);
+            e_WriteLog(Format('Error loading animation texture %s', [RecName]), TMsgType.Warning);
           end;
           BadTextNameHash.put(RecName, -1);
         end;
@@ -1145,13 +1166,13 @@ begin
       GlobalMetadata.ClearMetaItemsForSaving();
       if not LoadMultiImageFromMemory(TextureWAD, ResLength, ia) then
       begin
-        e_WriteLog(Format('Animated texture file "%s" cannot be loaded', [RecName]), MSG_WARNING);
+        e_WriteLog(Format('Animated texture file "%s" cannot be loaded', [RecName]), TMsgType.Warning);
         BadTextNameHash.put(RecName, -1);
         exit;
       end;
       if length(ia) = 0 then
       begin
-        e_WriteLog(Format('Animated texture file "%s" has no frames', [RecName]), MSG_WARNING);
+        e_WriteLog(Format('Animated texture file "%s" has no frames', [RecName]), TMsgType.Warning);
         BadTextNameHash.put(RecName, -1);
         exit;
       end;
@@ -1195,7 +1216,7 @@ begin
       //writeln(' creating animated texture with ', length(ia), ' frames (delay:', _speed, '; backloop:', _backanimation, ') from "', RecName, '"...');
       //for f := 0 to high(ia) do writeln('  frame #', f, ': ', ia[f].width, 'x', ia[f].height);
       f := ord(_backanimation);
-      e_WriteLog(Format('Animated texture file "%s": %d frames (delay:%d; back:%d; frdelay:%d; frloop:%d), %dx%d', [RecName, length(ia), _speed, f, frdelay, frloop, _width, _height]), MSG_NOTIFY);
+      e_WriteLog(Format('Animated texture file "%s": %d frames (delay:%d; back:%d; frdelay:%d; frloop:%d), %dx%d', [RecName, length(ia), _speed, f, frdelay, frloop, _width, _height]), TMsgType.Notify);
 
       SetLength(Textures, Length(Textures)+1);
       // cîçäàåì êàäðû àíèì. òåêñòóðû èç êàðòèíîê
@@ -1213,10 +1234,10 @@ begin
       end
       else
       begin
-        if (BadTextNameHash = nil) then BadTextNameHash := hashNewStrInt();
+        if (BadTextNameHash = nil) then BadTextNameHash := THashStrInt.Create();
         if log  and (not BadTextNameHash.get(RecName, f)) then
         begin
-          e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), MSG_WARNING);
+          e_WriteLog(Format('Error loading animation texture "%s" images', [RecName]), TMsgType.Warning);
         end;
         BadTextNameHash.put(RecName, -1);
       end;
@@ -1499,7 +1520,7 @@ var
       if (pan.proxyId <> -1) then
       begin
         {$IF DEFINED(D2F_DEBUG)}
-        e_WriteLog(Format('DUPLICATE wall #%d(%d) enabled (%d); type:%08x', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.PanelType]), MSG_NOTIFY);
+        e_WriteLog(Format('DUPLICATE wall #%d(%d) enabled (%d); type:%08x', [Integer(idx), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.PanelType]), TMsgType.Notify);
         {$ENDIF}
         continue;
       end;
@@ -1604,7 +1625,7 @@ var
   PanelID: DWORD;
   AddTextures: TAddTextureArray;
   TriggersTable: array of TTRec;
-  FileName, mapResName, s, TexName: String;
+  FileName, mapResName, TexName, s: AnsiString;
   Data: Pointer;
   Len: Integer;
   ok, isAnim: Boolean;
@@ -1617,6 +1638,7 @@ var
   //moveActive: Boolean;
   pan: TPanel;
   mapOk: Boolean = false;
+  usedTextures: THashStrInt = nil; // key: mapTextureList
 begin
   mapGrid.Free();
   mapGrid := nil;
@@ -1637,7 +1659,7 @@ begin
     if (gCurrentMap = nil) then
     begin
       FileName := g_ExtractWadName(Res);
-      e_WriteLog('Loading map WAD: '+FileName, MSG_NOTIFY);
+      e_WriteLog('Loading map WAD: '+FileName, TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_WAD_FILE], 0, False);
 
       WAD := TWADFile.Create();
@@ -1667,7 +1689,7 @@ begin
       end;
 
       // Çàãðóçêà êàðòû:
-      e_LogWritefln('Loading map: %s', [mapResName], MSG_NOTIFY);
+      e_LogWritefln('Loading map: %s', [mapResName], TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_MAP], 0, False);
 
       stt := getTimeMicro();
@@ -1708,7 +1730,7 @@ begin
     monsters := gCurrentMap['monster'];
 
     // Çàãðóçêà îïèñàíèÿ êàðòû:
-    e_WriteLog('  Reading map info...', MSG_NOTIFY);
+    e_WriteLog('  Reading map info...', TMsgType.Notify);
     g_Game_SetLoadingText(_lc[I_LOAD_MAP_HEADER], 0, False);
 
     with gMapInfo do
@@ -1727,34 +1749,56 @@ begin
     // Äîáàâëåíèå òåêñòóð â Textures[]:
     if (mapTextureList <> nil) and (mapTextureList.count > 0) then
     begin
-      e_WriteLog('  Loading textures:', MSG_NOTIFY);
+      e_WriteLog('  Loading textures:', TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_TEXTURES], mapTextureList.count-1, False);
 
-      cnt := -1;
-      for rec in mapTextureList do
-      begin
-        Inc(cnt);
-        s := rec.Resource;
-        {$IF DEFINED(D2F_DEBUG_TXLOAD)}
-        e_WriteLog(Format('    Loading texture #%d: %s', [cnt, s]), MSG_NOTIFY);
-        {$ENDIF}
-        //if g_Map_IsSpecialTexture(s) then e_WriteLog('      SPECIAL!', MSG_NOTIFY);
-        if rec.Anim then
-        begin
-          // Àíèìèðîâàííàÿ òåêñòóðà
-          ntn := CreateAnimTexture(rec.Resource, FileName, True);
-          if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [s]));
-        end
-        else
+      // find used textures
+      usedTextures := THashStrInt.Create();
+      try
+        if (panels <> nil) and (panels.count > 0) then
         begin
-          // Îáû÷íàÿ òåêñòóðà
-          ntn := CreateTexture(rec.Resource, FileName, True);
-          if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [s]));
+          for rec in panels do
+          begin
+            texrec := rec.TextureRec;
+            if (texrec <> nil) then usedTextures.put(toLowerCase1251(texrec.Resource), 42);
+          end;
         end;
-        if (ntn < 0) then ntn := CreateNullTexture(rec.Resource);
 
-        rec.tagInt := ntn; // remember texture number
-        g_Game_StepLoading();
+        cnt := -1;
+        for rec in mapTextureList do
+        begin
+          Inc(cnt);
+          if not usedTextures.has(toLowerCase1251(rec.Resource)) then
+          begin
+            rec.tagInt := -1; // just in case
+            e_LogWritefln('    Unused texture #%d: %s', [cnt, rec.Resource]);
+          end
+          else
+          begin
+            {$IF DEFINED(D2F_DEBUG_TXLOAD)}
+            e_LogWritefln('    Loading texture #%d: %s', [cnt, rec.Resource]);
+            {$ENDIF}
+            //if g_Map_IsSpecialTexture(s) then e_WriteLog('      SPECIAL!', MSG_NOTIFY);
+            if rec.Anim then
+            begin
+              // Àíèìèðîâàííàÿ òåêñòóðà
+              ntn := CreateAnimTexture(rec.Resource, FileName, True);
+              if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_ANIM], [rec.Resource]));
+            end
+            else
+            begin
+              // Îáû÷íàÿ òåêñòóðà
+              ntn := CreateTexture(rec.Resource, FileName, True);
+              if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [rec.Resource]));
+            end;
+            if (ntn < 0) then ntn := CreateNullTexture(rec.Resource);
+
+            rec.tagInt := ntn; // remember texture number
+          end;
+          g_Game_StepLoading();
+        end;
+      finally
+        usedTextures.Free();
       end;
 
       // set panel tagInt to texture index
@@ -1768,13 +1812,14 @@ begin
       end;
     end;
 
+
     // Çàãðóçêà òðèããåðîâ
     gTriggerClientID := 0;
-    e_WriteLog('  Loading triggers...', MSG_NOTIFY);
+    e_WriteLog('  Loading triggers...', TMsgType.Notify);
     g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS], 0, False);
 
     // Çàãðóçêà ïàíåëåé
-    e_WriteLog('  Loading panels...', MSG_NOTIFY);
+    e_WriteLog('  Loading panels...', TMsgType.Notify);
     g_Game_SetLoadingText(_lc[I_LOAD_PANELS], 0, False);
 
     // check texture numbers for panels
@@ -1784,7 +1829,7 @@ begin
       begin
         if (rec.tagInt < 0) then
         begin
-          e_WriteLog('error loading map: invalid texture index for panel', MSG_FATALERROR);
+          e_WriteLog('error loading map: invalid texture index for panel', TMsgType.Fatal);
           result := false;
           gCurrentMap.Free();
           gCurrentMap := nil;
@@ -1797,7 +1842,7 @@ begin
     // Ñîçäàíèå òàáëèöû òðèããåðîâ (ñîîòâåòñòâèå ïàíåëåé òðèããåðàì)
     if (triggers <> nil) and (triggers.count > 0) then
     begin
-      e_WriteLog('  Setting up trigger table...', MSG_NOTIFY);
+      e_WriteLog('  Setting up trigger table...', TMsgType.Notify);
       //SetLength(TriggersTable, triggers.count);
       g_Game_SetLoadingText(_lc[I_LOAD_TRIGGERS_TABLE], triggers.count-1, False);
 
@@ -1825,7 +1870,7 @@ begin
     // Ñîçäàåì ïàíåëè
     if (panels <> nil) and (panels.count > 0) then
     begin
-      e_WriteLog('  Setting up trigger links...', MSG_NOTIFY);
+      e_WriteLog('  Setting up trigger links...', TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_LINK_TRIGGERS], panels.count-1, False);
 
       pannum := -1;
@@ -1981,6 +2026,7 @@ begin
         //e_LogWritefln('PANADD: pannum=%s', [pannum]);
 
         // Ñîçäàåì ïàíåëü è çàïîìèíàåì åå GUID
+        //e_LogWritefln('new panel; tcount=%s; curtex=%s', [Length(AddTextures), CurTex]);
         PanelID := CreatePanel(rec, AddTextures, CurTex);
         //e_LogWritefln('panel #%s of type %s got guid #%s', [pannum, rec.PanelType, PanelID]);
         rec.userPanelId := PanelID; // remember game panel id, we'll fix triggers later
@@ -2011,7 +2057,7 @@ begin
     end;
 
     // create map grid, init other grids (for monsters, for example)
-    e_WriteLog('Creating map grid', MSG_NOTIFY);
+    e_WriteLog('Creating map grid', TMsgType.Notify);
     mapCreateGrid();
 
     // Åñëè íå LoadState, òî ñîçäàåì òðèããåðû
@@ -2045,31 +2091,31 @@ begin
     end;
 
     // Çàãðóçêà ïðåäìåòîâ
-    e_WriteLog('  Loading items...', MSG_NOTIFY);
+    e_WriteLog('  Loading items...', TMsgType.Notify);
     g_Game_SetLoadingText(_lc[I_LOAD_ITEMS], 0, False);
 
     // Åñëè íå LoadState, òî ñîçäàåì ïðåäìåòû
     if (items <> nil) and not gLoadGameMode then
     begin
-      e_WriteLog('  Spawning items...', MSG_NOTIFY);
+      e_WriteLog('  Spawning items...', TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_CREATE_ITEMS], 0, False);
       for rec in items do CreateItem(rec);
     end;
 
     // Çàãðóçêà îáëàñòåé
-    e_WriteLog('  Loading areas...', MSG_NOTIFY);
+    e_WriteLog('  Loading areas...', TMsgType.Notify);
     g_Game_SetLoadingText(_lc[I_LOAD_AREAS], 0, False);
 
     // Åñëè íå LoadState, òî ñîçäàåì îáëàñòè
     if areas <> nil then
     begin
-      e_WriteLog('  Creating areas...', MSG_NOTIFY);
+      e_WriteLog('  Creating areas...', TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_CREATE_AREAS], 0, False);
       for rec in areas do CreateArea(rec);
     end;
 
     // Çàãðóçêà ìîíñòðîâ
-    e_WriteLog('  Loading monsters...', MSG_NOTIFY);
+    e_WriteLog('  Loading monsters...', TMsgType.Notify);
     g_Game_SetLoadingText(_lc[I_LOAD_MONSTERS], 0, False);
 
     gTotalMonsters := 0;
@@ -2077,7 +2123,7 @@ begin
     // Åñëè íå LoadState, òî ñîçäàåì ìîíñòðîâ
     if (monsters <> nil) and not gLoadGameMode then
     begin
-      e_WriteLog('  Spawning monsters...', MSG_NOTIFY);
+      e_WriteLog('  Spawning monsters...', TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_CREATE_MONSTERS], 0, False);
       for rec in monsters do CreateMonster(rec);
     end;
@@ -2089,7 +2135,7 @@ begin
     // Çàãðóçêà íåáà
     if (gMapInfo.SkyName <> '') then
     begin
-      e_WriteLog('  Loading sky: ' + gMapInfo.SkyName, MSG_NOTIFY);
+      e_WriteLog('  Loading sky: ' + gMapInfo.SkyName, TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_SKY], 0, False);
       FileName := g_ExtractWadName(gMapInfo.SkyName);
 
@@ -2115,7 +2161,7 @@ begin
     ok := False;
     if gMapInfo.MusicName <> '' then
     begin
-      e_WriteLog('  Loading music: ' + gMapInfo.MusicName, MSG_NOTIFY);
+      e_WriteLog('  Loading music: ' + gMapInfo.MusicName, TMsgType.Notify);
       g_Game_SetLoadingText(_lc[I_LOAD_MUSIC], 0, False);
       FileName := g_ExtractWadName(gMapInfo.MusicName);
 
@@ -2179,7 +2225,7 @@ begin
     end;
   end;
 
-  e_WriteLog('Done loading map.', MSG_NOTIFY);
+  e_WriteLog('Done loading map.', TMsgType.Notify);
   Result := True;
 end;
 
@@ -2248,11 +2294,11 @@ begin
   mapReader.Free();
 end;
 
-function g_Map_GetMapsList(WADName: string): SArray;
+function g_Map_GetMapsList(WADName: string): SSArray;
 var
   WAD: TWADFile;
   a: Integer;
-  ResList: SArray;
+  ResList: SSArray;
 begin
   Result := nil;
   WAD := TWADFile.Create();
@@ -2277,7 +2323,7 @@ function g_Map_Exist(Res: string): Boolean;
 var
   WAD: TWADFile;
   FileName, mnn: string;
-  ResList: SArray;
+  ResList: SSArray;
   a: Integer;
 begin
   Result := False;
@@ -3014,7 +3060,7 @@ begin
     Obj.Y := -1000;
     Obj.Vel.X := 0;
     Obj.Vel.Y := 0;
-    Direction := D_LEFT;
+    Direction := TDirection.D_LEFT;
     State := FLAG_STATE_NONE;
     if FlagPoints[Flag] <> nil then
     begin
@@ -3042,14 +3088,14 @@ begin
         if State = FLAG_STATE_NONE then
           continue;
 
-        if Direction = D_LEFT then
+        if Direction = TDirection.D_LEFT then
           begin
-            Mirror := M_HORIZONTAL;
+            Mirror := TMirrorType.Horizontal;
             dx := -1;
           end
         else
           begin
-            Mirror := M_NONE;
+            Mirror := TMirrorType.None;
             dx := 1;
           end;
 
@@ -3091,7 +3137,7 @@ var
     // Ñîñòîÿíèå ôëàãà
     utils.writeInt(st, Byte(flag^.State));
     // Íàïðàâëåíèå ôëàãà
-    if flag^.Direction = D_LEFT then b := 1 else b := 2; // D_RIGHT
+    if flag^.Direction = TDirection.D_LEFT then b := 1 else b := 2; // D_RIGHT
     utils.writeInt(st, Byte(b));
     // Îáúåêò ôëàãà
     Obj_SaveState(st, @flag^.Obj);
@@ -3170,7 +3216,7 @@ var
     flag^.State := utils.readByte(st);
     // Íàïðàâëåíèå ôëàãà
     b := utils.readByte(st);
-    if (b = 1) then flag^.Direction := D_LEFT else flag^.Direction := D_RIGHT; // b = 2
+    if (b = 1) then flag^.Direction := TDirection.D_LEFT else flag^.Direction := TDirection.D_RIGHT; // b = 2
     // Îáúåêò ôëàãà
     Obj_LoadState(@flag^.Obj, st);
   end;
@@ -3253,4 +3299,6 @@ begin
 end;
 
 
+begin
+  DynWarningCB := mapWarningCB;
 end.