DEADSOFTWARE

osx: fix map test on osx
[d2df-editor.git] / src / editor / f_main.pas
index 99ddcd9b1a25a3ed1d3c035816546506779ed9b1..8e7636043b89a072bdfdfa1cd2d85ae889c16f4f 100644 (file)
@@ -8,7 +8,7 @@ uses
   LCLIntf, LCLType, SysUtils, Variants, Classes, Graphics,
   Controls, Forms, Dialogs, StdCtrls, Buttons,
   ComCtrls, ValEdit, Types, Menus, ExtCtrls,
   LCLIntf, LCLType, SysUtils, Variants, Classes, Graphics,
   Controls, Forms, Dialogs, StdCtrls, Buttons,
   ComCtrls, ValEdit, Types, Menus, ExtCtrls,
-  CheckLst, Grids, OpenGLContext, utils, UTF8Process;
+  CheckLst, Grids, OpenGLContext, Utils, UTF8Process;
 
 type
 
 
 type
 
@@ -124,6 +124,7 @@ type
   // Панель применения свойств:
     PanelPropApply: TPanel;
     bApplyProperty: TButton;
   // Панель применения свойств:
     PanelPropApply: TPanel;
     bApplyProperty: TButton;
+    MapTestTimer: TTimer;
   // Редактор свойств объектов:
     vleObjectProperty: TValueListEditor;
 
   // Редактор свойств объектов:
     vleObjectProperty: TValueListEditor;
 
@@ -218,6 +219,7 @@ type
     procedure RenderPanelPaint(Sender: TObject);
     procedure RenderPanelResize(Sender: TObject);
     procedure Splitter1Moved(Sender: TObject);
     procedure RenderPanelPaint(Sender: TObject);
     procedure RenderPanelResize(Sender: TObject);
     procedure Splitter1Moved(Sender: TObject);
+    procedure MapTestCheck(Sender: TObject);
     procedure vleObjectPropertyEditButtonClick(Sender: TObject);
     procedure vleObjectPropertyApply(Sender: TObject);
     procedure vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings);
     procedure vleObjectPropertyEditButtonClick(Sender: TObject);
     procedure vleObjectPropertyApply(Sender: TObject);
     procedure vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings);
@@ -286,14 +288,14 @@ const
 
 var
   MainForm: TMainForm;
 
 var
   MainForm: TMainForm;
-  EditorDir: String;
+  StartMap: String;
   OpenedMap: String;
   OpenedWAD: String;
 
   DotColor: TColor;
   DotEnable: Boolean;
   OpenedMap: String;
   OpenedWAD: String;
 
   DotColor: TColor;
   DotEnable: Boolean;
-  DotStep: Byte;
-  DotStepOne, DotStepTwo: Byte;
+  DotStep: Word;
+  DotStepOne, DotStepTwo: Word;
   DotSize: Byte;
   DrawTexturePanel: Boolean;
   DrawPanelSize: Boolean;
   DotSize: Byte;
   DrawTexturePanel: Boolean;
   DrawPanelSize: Boolean;
@@ -313,7 +315,7 @@ var
   TestOptionsAllowExit: Boolean;
   TestOptionsWeaponStay: Boolean;
   TestOptionsMonstersDM: Boolean;
   TestOptionsAllowExit: Boolean;
   TestOptionsWeaponStay: Boolean;
   TestOptionsMonstersDM: Boolean;
-  TestD2dExe: String;
+  TestD2dExe, TestD2DArgs: String;
   TestMapOnce: Boolean;
 
   LayerEnabled: Array [LAYER_BACK..LAYER_TRIGGERS] of Boolean =
   TestMapOnce: Boolean;
 
   LayerEnabled: Array [LAYER_BACK..LAYER_TRIGGERS] of Boolean =
@@ -337,11 +339,11 @@ uses
   f_options, e_graphics, e_log, GL, Math,
   f_mapoptions, g_basic, f_about, f_mapoptimization,
   f_mapcheck, f_addresource_texture, g_textures,
   f_options, e_graphics, e_log, GL, Math,
   f_mapoptions, g_basic, f_about, f_mapoptimization,
   f_mapcheck, f_addresource_texture, g_textures,
-  f_activationtype, f_keys,
+  f_activationtype, f_keys, wadreader, fileutil,
   MAPREADER, f_selectmap, f_savemap, WADEDITOR, MAPDEF,
   g_map, f_saveminimap, f_addresource, CONFIG, f_packmap,
   f_addresource_sound, f_maptest, f_choosetype,
   MAPREADER, f_selectmap, f_savemap, WADEDITOR, MAPDEF,
   g_map, f_saveminimap, f_addresource, CONFIG, f_packmap,
   f_addresource_sound, f_maptest, f_choosetype,
-  g_language, f_selectlang, ClipBrd, g_resources;
+  g_language, f_selectlang, ClipBrd, g_resources, g_options;
 
 const
   UNDO_DELETE_PANEL   = 1;
 
 const
   UNDO_DELETE_PANEL   = 1;
@@ -442,8 +444,10 @@ var
   LastMovePoint: Types.TPoint;
   MouseLDown: Boolean;
   MouseRDown: Boolean;
   LastMovePoint: Types.TPoint;
   MouseLDown: Boolean;
   MouseRDown: Boolean;
+  MouseMDown: Boolean;
   MouseLDownPos: Types.TPoint;
   MouseRDownPos: Types.TPoint;
   MouseLDownPos: Types.TPoint;
   MouseRDownPos: Types.TPoint;
+  MouseMDownPos: Types.TPoint;
 
   SelectFlag: Byte = SELECTFLAG_NONE;
   MouseAction: Byte = MOUSEACTION_NONE;
 
   SelectFlag: Byte = SELECTFLAG_NONE;
   MouseAction: Byte = MOUSEACTION_NONE;
@@ -455,6 +459,8 @@ var
 
   UndoBuffer: Array of Array of TUndoRec = nil;
 
 
   UndoBuffer: Array of Array of TUndoRec = nil;
 
+  MapTestProcess: TProcessUTF8;
+  MapTestFile: String;
 
 {$R *.lfm}
 
 
 {$R *.lfm}
 
@@ -694,10 +700,10 @@ begin
   begin
     ScaleSz := 16 div Scale;
   // Размер видимой части карты:
   begin
     ScaleSz := 16 div Scale;
   // Размер видимой части карты:
-    rx := min(Normalize16(Width), Normalize16(gMapInfo.Width)) div 2;
-    ry := min(Normalize16(Height), Normalize16(gMapInfo.Height)) div 2;
+    rx := Min(Normalize16(Width), Normalize16(gMapInfo.Width)) div 2;
+    ry := Min(Normalize16(Height), Normalize16(gMapInfo.Height)) div 2;
   // Место клика на мини-карте:
   // Место клика на мини-карте:
-    MapOffset.X := X - (Width-max(gMapInfo.Width div ScaleSz, 1)-1);
+    MapOffset.X := X - (Width - Max(gMapInfo.Width div ScaleSz, 1) - 1);
     MapOffset.Y := Y - 1;
   // Это же место на "большой" карте:
     MapOffset.X := MapOffset.X * ScaleSz;
     MapOffset.Y := Y - 1;
   // Это же место на "большой" карте:
     MapOffset.X := MapOffset.X * ScaleSz;
@@ -706,17 +712,11 @@ begin
     MapOffset.X := MapOffset.X - rx;
     MapOffset.Y := MapOffset.Y - ry;
   // Выход за границы:
     MapOffset.X := MapOffset.X - rx;
     MapOffset.Y := MapOffset.Y - ry;
   // Выход за границы:
-    if MapOffset.X < 0 then
-      MapOffset.X := 0;
-    if MapOffset.Y < 0 then
-      MapOffset.Y := 0;
-    if MapOffset.X > MainForm.sbHorizontal.Max then
-      MapOffset.X := MainForm.sbHorizontal.Max;
-    if MapOffset.Y > MainForm.sbVertical.Max then
-      MapOffset.Y := MainForm.sbVertical.Max;
+    MapOffset.X := EnsureRange(MapOffset.X, MainForm.sbHorizontal.Min, MainForm.sbHorizontal.Max);
+    MapOffset.Y := EnsureRange(MapOffset.Y, MainForm.sbVertical.Min, MainForm.sbVertical.Max);
   // Кратно 16:
   // Кратно 16:
-    MapOffset.X := Normalize16(MapOffset.X);
-    MapOffset.Y := Normalize16(MapOffset.Y);
+  //  MapOffset.X := Normalize16(MapOffset.X);
+  //  MapOffset.Y := Normalize16(MapOffset.Y);
   end;
 
   MainForm.sbHorizontal.Position := MapOffset.X;
   end;
 
   MainForm.sbHorizontal.Position := MapOffset.X;
@@ -1410,6 +1410,20 @@ begin
                   EditStyle := esSimple;
                   MaxLength := 5;
                 end;
                   EditStyle := esSimple;
                   MaxLength := 5;
                 end;
+                case Data.DamageKind of
+                  3: str := _lc[I_PROP_TR_DAMAGE_KIND_3];
+                  4: str := _lc[I_PROP_TR_DAMAGE_KIND_4];
+                  5: str := _lc[I_PROP_TR_DAMAGE_KIND_5];
+                  6: str := _lc[I_PROP_TR_DAMAGE_KIND_6];
+                  7: str := _lc[I_PROP_TR_DAMAGE_KIND_7];
+                  8: str := _lc[I_PROP_TR_DAMAGE_KIND_8];
+                  else str := _lc[I_PROP_TR_DAMAGE_KIND_0];
+                end;
+                with ItemProps[InsertRow(_lc[I_PROP_TR_DAMAGE_KIND], str, True)] do
+                begin
+                  EditStyle := esPickList;
+                  ReadOnly := True;
+                end;
               end;
 
             TRIGGER_HEALTH:
               end;
 
             TRIGGER_HEALTH:
@@ -1829,7 +1843,7 @@ end;
 
 procedure ErrorMessageBox(str: String);
 begin
 
 procedure ErrorMessageBox(str: String);
 begin
-  MessageBox(0, PChar(str), PChar(_lc[I_MSG_ERROR]),
+  Application.MessageBox(PChar(str), PChar(_lc[I_MSG_ERROR]),
              MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1);
 end;
 
              MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1);
 end;
 
@@ -1920,7 +1934,6 @@ begin
   if aWAD = _lc[I_WAD_SPECIAL_MAP] then
     begin // Файл карты
       g_ProcessResourceStr(OpenedMap, @fn, nil, nil);
   if aWAD = _lc[I_WAD_SPECIAL_MAP] then
     begin // Файл карты
       g_ProcessResourceStr(OpenedMap, @fn, nil, nil);
-    //FileName := EditorDir+'maps\'+ExtractFileName(fn);
       FileName := fn;
       ResourceName := ':'+SectionName+'\'+aTex;
     end
       FileName := fn;
       ResourceName := ':'+SectionName+'\'+aTex;
     end
@@ -1932,7 +1945,7 @@ begin
       end
     else
       begin // Внешний WAD
       end
     else
       begin // Внешний WAD
-        FileName := EditorDir+'wads/'+aWAD;
+        FileName := WadsDir + DirectorySeparator + aWAD;
         ResourceName := aWAD+':'+SectionName+'\'+aTex;
       end;
 
         ResourceName := aWAD+':'+SectionName+'\'+aTex;
       end;
 
@@ -2569,45 +2582,27 @@ end;
 
 procedure TMainForm.aRecentFileExecute(Sender: TObject);
 var
 
 procedure TMainForm.aRecentFileExecute(Sender: TObject);
 var
-  n, pw: Integer;
-  s, fn: String;
-  b: Boolean;
+  n: Integer;
+  fn, s: String;
 begin
   s := LowerCase((Sender as TMenuItem).Caption);
   Delete(s, Pos('&', s), 1);
   s := Trim(Copy(s, 1, 2));
   n := StrToIntDef(s, 0) - 1;
 begin
   s := LowerCase((Sender as TMenuItem).Caption);
   Delete(s, Pos('&', s), 1);
   s := Trim(Copy(s, 1, 2));
   n := StrToIntDef(s, 0) - 1;
-
-  if (n < 0) or (n >= RecentFiles.Count) then
-    Exit;
-
-  s := RecentFiles[n];
-  pw := Pos('.wad:\', LowerCase(s));
-  b := False;
-  
-  if pw > 0 then
-    begin // Map name included
-      fn := Copy(s, 1, pw + 3);
-      Delete(s, 1, pw + 5);
-      if (FileExists(fn)) then
-      begin
-        OpenMap(fn, s);
-        b := True;
-      end;
+  if (n >= 0) and (n <= RecentFiles.Count) then
+  begin
+    fn := g_ExtractWadName(RecentFiles[n]);
+    if FileExists(fn) then
+    begin
+      s := g_ExtractFilePathName(RecentFiles[n]);
+      OpenMap(fn, s)
     end
     end
-  else // Only wad name
-    if (FileExists(s)) then
+    else if Application.MessageBox(PChar(_lc[I_MSG_DEL_RECENT_PROMT]), PChar(_lc[I_MSG_DEL_RECENT]), MB_ICONQUESTION or MB_YESNO) = idYes then
     begin
     begin
-      OpenMap(s, '');
-      b := True;
-    end;
-
-  if (not b) and (MessageBox(0, PChar(_lc[I_MSG_DEL_RECENT_PROMT]),
-    PChar(_lc[I_MSG_DEL_RECENT]), MB_ICONQUESTION or MB_YESNO) = idYes) then
-  begin
-    RecentFiles.Delete(n);
-    RefreshRecentMenu();
-  end;
+      RecentFiles.Delete(n);
+      RefreshRecentMenu();
+    end
+  end
 end;
 
 procedure TMainForm.aEditorOptionsExecute(Sender: TObject);
 end;
 
 procedure TMainForm.aEditorOptionsExecute(Sender: TObject);
@@ -2625,10 +2620,10 @@ var
   config: TConfig;
 begin
   ID := 0;
   config: TConfig;
 begin
   ID := 0;
-  g_ReadResource(EditorDir + 'data/game.wad', 'FONTS', cfgres, cfgdata, cfglen);
+  g_ReadResource(GameWad, 'FONTS', cfgres, cfgdata, cfglen);
   if cfgdata <> nil then
   begin
   if cfgdata <> nil then
   begin
-    if not g_CreateTextureWAD('FONT_STD', EditorDir + 'data/game.wad:FONTS\' + texture) then
+    if not g_CreateTextureWAD('FONT_STD', GameWad + ':FONTS\' + texture) then
       e_WriteLog('ERROR ERROR ERROR', MSG_WARNING);
 
     config := TConfig.CreateMem(cfgdata, cfglen);
       e_WriteLog('ERROR ERROR ERROR', MSG_WARNING);
 
     config := TConfig.CreateMem(cfgdata, cfglen);
@@ -2656,9 +2651,10 @@ var
 begin
   Randomize();
 
 begin
   Randomize();
 
-  EditorDir := ExtractFilePath(Application.ExeName);
-
-  e_InitLog(EditorDir+'Editor.log', WM_NEWFILE);
+  e_WriteLog('Doom 2D: Forever Editor version ' + EDITOR_VERSION, MSG_NOTIFY);
+  e_WriteLog('Build date: ' + EDITOR_BUILDDATE + ' ' + EDITOR_BUILDTIME, MSG_NOTIFY);
+  e_WriteLog('Build hash: ' + g_GetBuildHash(), MSG_NOTIFY);
+  e_WriteLog('Build by: ' + g_GetBuilderName(), MSG_NOTIFY);
 
   slInvalidTextures := TStringList.Create;
 
 
   slInvalidTextures := TStringList.Create;
 
@@ -2678,7 +2674,7 @@ begin
   OpenedMap := '';
   OpenedWAD := '';
 
   OpenedMap := '';
   OpenedWAD := '';
 
-  config := TConfig.CreateFile(EditorDir+'Editor.cfg');
+  config := TConfig.CreateFile(CfgFileName);
 
   if config.ReadInt('Editor', 'XPos', -1) = -1 then
     Position := poDesktopCenter
 
   if config.ReadInt('Editor', 'XPos', -1) = -1 then
     Position := poDesktopCenter
@@ -2733,8 +2729,8 @@ begin
     DotSize := 2
   else
     DotSize := 1;
     DotSize := 2
   else
     DotSize := 1;
-  OpenDialog.InitialDir := config.ReadStr('Editor', 'LastOpenDir', EditorDir);
-  SaveDialog.InitialDir := config.ReadStr('Editor', 'LastSaveDir', EditorDir);
+  OpenDialog.InitialDir := config.ReadStr('Editor', 'LastOpenDir', MapsDir);
+  SaveDialog.InitialDir := config.ReadStr('Editor', 'LastSaveDir', MapsDir);
 
   s := config.ReadStr('Editor', 'Language', '');
   gLanguage := s;
 
   s := config.ReadStr('Editor', 'Language', '');
   gLanguage := s;
@@ -2839,12 +2835,22 @@ begin
     else
       a := 0;
 
     else
       a := 0;
 
-    for x := 0 to (RenderPanel.Width div DotStep) do
-      for y := 0 to (RenderPanel.Height div DotStep) do
-        e_DrawPoint(DotSize, x*DotStep + a, y*DotStep + a,
+    x := MapOffset.X mod DotStep;
+    y := MapOffset.Y mod DotStep;
+
+    while x < RenderPanel.Width do
+    begin
+      while y < RenderPanel.Height do
+      begin
+        e_DrawPoint(DotSize, x + a, y + a,
                     GetRValue(DotColor),
                     GetGValue(DotColor),
                     GetBValue(DotColor));
                     GetRValue(DotColor),
                     GetGValue(DotColor),
                     GetBValue(DotColor));
+        y += DotStep;
+      end;
+      x += DotStep;
+      y := MapOffset.Y mod DotStep;
+    end;
   end;
 
 // Превью текстуры:
   end;
 
 // Превью текстуры:
@@ -3095,18 +3101,13 @@ procedure TMainForm.FormResize(Sender: TObject);
 begin
   e_SetViewPort(0, 0, RenderPanel.Width, RenderPanel.Height);
 
 begin
   e_SetViewPort(0, 0, RenderPanel.Width, RenderPanel.Height);
 
-  if gMapInfo.Width >= RenderPanel.Width then
-    sbHorizontal.Max := Normalize16(gMapInfo.Width-RenderPanel.Width+16)
-  else
-    sbHorizontal.Max := 0;
-
-  if gMapInfo.Height >= RenderPanel.Height then
-    sbVertical.Max := Normalize16(gMapInfo.Height-RenderPanel.Height+16)
-  else
-    sbVertical.Max := 0;
+  sbHorizontal.Min := Min(gMapInfo.Width - RenderPanel.Width, -RenderPanel.Width div 2);
+  sbHorizontal.Max := Max(0, gMapInfo.Width - RenderPanel.Width div 2);
+  sbVertical.Min := Min(gMapInfo.Height - RenderPanel.Height, -RenderPanel.Height div 2);
+  sbVertical.Max := Max(0, gMapInfo.Height - RenderPanel.Height div 2);
 
 
-  MapOffset.X := -Normalize16(sbHorizontal.Position);
-  MapOffset.Y := -Normalize16(sbVertical.Position);
+  MapOffset.X := -sbHorizontal.Position;
+  MapOffset.Y := -sbVertical.Position;
 end;
 
 procedure SelectNextObject(X, Y: Integer; ObjectType: Byte; ID: DWORD);
 end;
 
 procedure SelectNextObject(X, Y: Integer; ObjectType: Byte; ID: DWORD);
@@ -3597,6 +3598,16 @@ begin
         end;
   end; // if Button = mbRight
 
         end;
   end; // if Button = mbRight
 
+  if Button = mbMiddle then // Middle Mouse Button
+  begin
+    SetCapture(RenderPanel.Handle);
+    RenderPanel.Cursor := crSize;
+  end;
+
+  MouseMDown := Button = mbMiddle;
+  if MouseMDown then
+    MouseMDownPos := Mouse.CursorPos;
+
   MouseRDown := Button = mbRight;
   if MouseRDown then
     MouseRDownPos := MousePos;
   MouseRDown := Button = mbRight;
   if MouseRDown then
     MouseRDownPos := MousePos;
@@ -3634,6 +3645,8 @@ begin
     MouseLDown := False;
   if Button = mbRight then
     MouseRDown := False;
     MouseLDown := False;
   if Button = mbRight then
     MouseRDown := False;
+  if Button = mbMiddle then
+    MouseMDown := False;
 
   DrawRect := nil;
   ResizeType := RESIZETYPE_NONE;
 
   DrawRect := nil;
   ResizeType := RESIZETYPE_NONE;
@@ -3943,7 +3956,7 @@ begin
         MouseAction := MOUSEACTION_NONE;
       end;
     end // if Button = mbLeft...
         MouseAction := MOUSEACTION_NONE;
       end;
     end // if Button = mbLeft...
-  else // Right Mouse Button:
+  else if Button = mbRight then // Right Mouse Button:
     begin
       if MouseAction = MOUSEACTION_NOACTION then
       begin
     begin
       if MouseAction = MOUSEACTION_NOACTION then
       begin
@@ -3954,6 +3967,7 @@ begin
     // Объект передвинут или изменен в размере:
       if MouseAction in [MOUSEACTION_MOVEOBJ, MOUSEACTION_RESIZE] then
       begin
     // Объект передвинут или изменен в размере:
       if MouseAction in [MOUSEACTION_MOVEOBJ, MOUSEACTION_RESIZE] then
       begin
+        RenderPanel.Cursor := crDefault;
         MouseAction := MOUSEACTION_NONE;
         FillProperty();
         Exit;
         MouseAction := MOUSEACTION_NONE;
         FillProperty();
         Exit;
@@ -4006,6 +4020,12 @@ begin
         SelectObjects(pcObjects.ActivePageIndex+1);
 
       FillProperty();
         SelectObjects(pcObjects.ActivePageIndex+1);
 
       FillProperty();
+    end
+
+  else // Middle Mouse Button
+    begin
+      RenderPanel.Cursor := crDefault;
+      ReleaseCapture();
     end;
 end;
 
     end;
 end;
 
@@ -4086,16 +4106,12 @@ begin
       end
     else
       begin // Кнопки мыши не зажаты
       end
     else
       begin // Кнопки мыши не зажаты
-        MousePos.X := (Round(X/sX)*sX);
-        MousePos.Y := (Round(Y/sY)*sY);
+        MousePos.X := Round((-MapOffset.X + X) / sX) * sX + MapOffset.X;
+        MousePos.Y := Round((-MapOffset.Y + Y) / sY) * sY + MapOffset.Y;
       end;
 
       end;
 
-// Изменение размера закончилось - ставим обычный курсор:
-  if ResizeType = RESIZETYPE_NONE then
-    RenderPanel.Cursor := crDefault;
-
 // Зажата только правая кнопка мыши:
 // Зажата только правая кнопка мыши:
-  if (not MouseLDown) and (MouseRDown) then
+  if (not MouseLDown) and (MouseRDown) and (not MouseMDown) then
   begin
   // Рисуем прямоугольник выделения:
     if MouseAction = MOUSEACTION_NONE then
   begin
   // Рисуем прямоугольник выделения:
     if MouseAction = MOUSEACTION_NONE then
@@ -4144,7 +4160,7 @@ begin
   end;
 
 // Зажата только левая кнопка мыши:
   end;
 
 // Зажата только левая кнопка мыши:
-  if (not MouseRDown) and (MouseLDown) then
+  if (not MouseRDown) and (MouseLDown) and (not MouseMDown) then
   begin
   // Рисуем прямоугольник планирования панели:
     if MouseAction in [MOUSEACTION_DRAWPANEL,
   begin
   // Рисуем прямоугольник планирования панели:
     if MouseAction in [MOUSEACTION_DRAWPANEL,
@@ -4184,6 +4200,18 @@ begin
       end;
   end;
 
       end;
   end;
 
+// Only Middle Mouse Button is pressed
+  if (not MouseLDown) and (not MouseRDown) and (MouseMDown) then
+  begin
+    MapOffset.X := -EnsureRange(-MapOffset.X + MouseMDownPos.X - Mouse.CursorPos.X,
+                                sbHorizontal.Min, sbHorizontal.Max);
+    sbHorizontal.Position := -MapOffset.X;
+    MapOffset.Y := -EnsureRange(-MapOffset.Y + MouseMDownPos.Y - Mouse.CursorPos.Y,
+                                sbVertical.Min, sbVertical.Max);
+    sbVertical.Position := -MapOffset.Y;
+    MouseMDownPos := Mouse.CursorPos;
+  end;
+
 // Клавиши мыши не зажаты:
   if (not MouseRDown) and (not MouseLDown) then
     DrawRect := nil;
 // Клавиши мыши не зажаты:
   if (not MouseRDown) and (not MouseLDown) then
     DrawRect := nil;
@@ -4195,7 +4223,7 @@ end;
 
 procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
 begin
 
 procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
 begin
-  CanClose := MessageBox(0, PChar(_lc[I_MSG_EXIT_PROMT]),
+  CanClose := Application.MessageBox(PChar(_lc[I_MSG_EXIT_PROMT]),
                          PChar(_lc[I_MSG_EXIT]),
                          MB_ICONQUESTION or MB_YESNO or
                          MB_DEFBUTTON1) = idYes;
                          PChar(_lc[I_MSG_EXIT]),
                          MB_ICONQUESTION or MB_YESNO or
                          MB_DEFBUTTON1) = idYes;
@@ -4211,7 +4239,7 @@ var
   config: TConfig;
   i: Integer;
 begin
   config: TConfig;
   i: Integer;
 begin
-  config := TConfig.CreateFile(EditorDir+'Editor.cfg');
+  config := TConfig.CreateFile(CfgFileName);
 
   if WindowState <> wsMaximized then
   begin
 
   if WindowState <> wsMaximized then
   begin
@@ -4250,7 +4278,7 @@ begin
       config.WriteStr('RecentFiles', IntToStr(i+1), '');
   RecentFiles.Free();
 
       config.WriteStr('RecentFiles', IntToStr(i+1), '');
   RecentFiles.Free();
 
-  config.SaveFile(EditorDir+'Editor.cfg');
+  config.SaveFile(CfgFileName);
   config.Free();
 
   slInvalidTextures.Free;
   config.Free();
 
   slInvalidTextures.Free;
@@ -4276,6 +4304,22 @@ begin
   FormResize(Sender);
 end;
 
   FormResize(Sender);
 end;
 
+procedure TMainForm.MapTestCheck(Sender: TObject);
+begin
+  if MapTestProcess <> nil then
+  begin
+    if MapTestProcess.Running = false then
+    begin
+      if MapTestProcess.ExitCode <> 0 then
+        Application.MessageBox(PChar(_lc[I_MSG_EXEC_ERROR]), 'FIXME', MB_OK or MB_ICONERROR);
+      SysUtils.DeleteFile(MapTestFile);
+      MapTestFile := '';
+      FreeAndNil(MapTestProcess);
+      tbTestMap.Enabled := True;
+    end;
+  end;
+end;
+
 procedure TMainForm.aMapOptionsExecute(Sender: TObject);
 var
   ResName: String;
 procedure TMainForm.aMapOptionsExecute(Sender: TObject);
 var
   ResName: String;
@@ -4392,34 +4436,42 @@ begin
       begin
         if Key = Ord('W') then
         begin
       begin
         if Key = Ord('W') then
         begin
-          if (MouseLDown or MouseRDown) and (Position >= DotStep) then
+          dy := Position;
+          if ssShift in Shift then Position := EnsureRange(Position - DotStep * 4, Min, Max)
+          else Position := EnsureRange(Position - DotStep, Min, Max);
+          MapOffset.Y := -Position;
+          dy -= Position;
+
+          if (MouseLDown or MouseRDown) then
           begin
             if DrawRect <> nil then
             begin
           begin
             if DrawRect <> nil then
             begin
-              Inc(MouseLDownPos.y, DotStep);
-              Inc(MouseRDownPos.y, DotStep);
+              Inc(MouseLDownPos.y, dy);
+              Inc(MouseRDownPos.y, dy);
             end;
             end;
-            Inc(LastMovePoint.Y, DotStep);
+            Inc(LastMovePoint.Y, dy);
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
-          Position := IfThen(Position > DotStep, Position-DotStep, 0);
-          MapOffset.Y := -Round(Position/16) * 16;
         end;
 
         if Key = Ord('S') then
         begin
         end;
 
         if Key = Ord('S') then
         begin
-          if (MouseLDown or MouseRDown) and (Position+DotStep <= Max) then
+          dy := Position;
+          if ssShift in Shift then Position := EnsureRange(Position + DotStep * 4, Min, Max)
+          else Position := EnsureRange(Position + DotStep, Min, Max);
+          MapOffset.Y := -Position;
+          dy -= Position;
+
+          if (MouseLDown or MouseRDown) then
           begin
             if DrawRect <> nil then
             begin
           begin
             if DrawRect <> nil then
             begin
-              Dec(MouseLDownPos.y, DotStep);
-              Dec(MouseRDownPos.y, DotStep);
+              Inc(MouseLDownPos.y, dy);
+              Inc(MouseRDownPos.y, dy);
             end;
             end;
-            Dec(LastMovePoint.Y, DotStep);
+            Inc(LastMovePoint.Y, dy);
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
-          Position := IfThen(Position+DotStep < Max, Position+DotStep, Max);
-          MapOffset.Y := -Round(Position/16) * 16;
         end;
       end;
 
         end;
       end;
 
@@ -4428,34 +4480,42 @@ begin
       begin
         if Key = Ord('A') then
         begin
       begin
         if Key = Ord('A') then
         begin
-          if (MouseLDown or MouseRDown) and (Position >= DotStep) then
+          dx := Position;
+          if ssShift in Shift then Position := EnsureRange(Position - DotStep * 4, Min, Max)
+          else Position := EnsureRange(Position - DotStep, Min, Max);
+          MapOffset.X := -Position;
+          dx -= Position;
+
+          if (MouseLDown or MouseRDown) then
           begin
             if DrawRect <> nil then
             begin
           begin
             if DrawRect <> nil then
             begin
-              Inc(MouseLDownPos.x, DotStep);
-              Inc(MouseRDownPos.x, DotStep);
+              Inc(MouseLDownPos.x, dx);
+              Inc(MouseRDownPos.x, dx);
             end;
             end;
-            Inc(LastMovePoint.X, DotStep);
+            Inc(LastMovePoint.X, dx);
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
-          Position := IfThen(Position > DotStep, Position-DotStep, 0);
-          MapOffset.X := -Round(Position/16) * 16;
         end;
 
         if Key = Ord('D') then
         begin
         end;
 
         if Key = Ord('D') then
         begin
-          if (MouseLDown or MouseRDown) and (Position+DotStep <= Max) then
+          dx := Position;
+          if ssShift in Shift then Position := EnsureRange(Position + DotStep * 4, Min, Max)
+          else Position := EnsureRange(Position + DotStep, Min, Max);
+          MapOffset.X := -Position;
+          dx -= Position;
+
+          if (MouseLDown or MouseRDown) then
           begin
             if DrawRect <> nil then
             begin
           begin
             if DrawRect <> nil then
             begin
-              Dec(MouseLDownPos.x, DotStep);
-              Dec(MouseRDownPos.x, DotStep);
+              Inc(MouseLDownPos.x, dx);
+              Inc(MouseRDownPos.x, dx);
             end;
             end;
-            Dec(LastMovePoint.X, DotStep);
+            Inc(LastMovePoint.X, dx);
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
             RenderPanelMouseMove(Sender, Shift, RenderMousePos().X, RenderMousePos().Y);
           end;
-          Position := IfThen(Position+DotStep < Max, Position+DotStep, Max);
-          MapOffset.X := -Round(Position/16) * 16;
         end;
       end;
     end
         end;
       end;
     end
@@ -4681,7 +4741,7 @@ begin
   if OpenedMap = '' then
     Exit;
 
   if OpenedMap = '' then
     Exit;
 
-  if MessageBox(0, PChar(_lc[I_MSG_REOPEN_MAP_PROMT]),
+  if Application.MessageBox(PChar(_lc[I_MSG_REOPEN_MAP_PROMT]),
   PChar(_lc[I_MENU_FILE_REOPEN]), MB_ICONQUESTION or MB_YESNO) <> idYes then
     Exit;
 
   PChar(_lc[I_MENU_FILE_REOPEN]), MB_ICONQUESTION or MB_YESNO) <> idYes then
     Exit;
 
@@ -4765,6 +4825,16 @@ begin
         Values.Add(_lc[I_PROP_TR_SHOT_AIM_2]);
         Values.Add(_lc[I_PROP_TR_SHOT_AIM_3]);
       end
         Values.Add(_lc[I_PROP_TR_SHOT_AIM_2]);
         Values.Add(_lc[I_PROP_TR_SHOT_AIM_3]);
       end
+    else if KeyName = _lc[I_PROP_TR_DAMAGE_KIND] then
+      begin
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_0]);
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_3]);
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_4]);
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_5]);
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_6]);
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_7]);
+        Values.Add(_lc[I_PROP_TR_DAMAGE_KIND_8]);
+      end
     else if (KeyName = _lc[I_PROP_PANEL_BLEND]) or
             (KeyName = _lc[I_PROP_DM_ONLY]) or
             (KeyName = _lc[I_PROP_ITEM_FALLS]) or
     else if (KeyName = _lc[I_PROP_PANEL_BLEND]) or
             (KeyName = _lc[I_PROP_DM_ONLY]) or
             (KeyName = _lc[I_PROP_ITEM_FALLS]) or
@@ -5101,7 +5171,7 @@ begin
                 if vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_ACT]] = _lc[I_PROP_TR_MUSIC_ON] then
                   Data.MusicAction := 1
                 else
                 if vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_ACT]] = _lc[I_PROP_TR_MUSIC_ON] then
                   Data.MusicAction := 1
                 else
-                  Data.MusicAction := 2;
+                  Data.MusicAction := 0;
               end;
 
             TRIGGER_PUSH:
               end;
 
             TRIGGER_PUSH:
@@ -5168,6 +5238,21 @@ begin
                   StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_DAMAGE_VALUE]], 0), 0), 65535);
                 Data.DamageInterval := Min(Max(
                   StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_INTERVAL]], 0), 0), 65535);
                   StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_DAMAGE_VALUE]], 0), 0), 65535);
                 Data.DamageInterval := Min(Max(
                   StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_INTERVAL]], 0), 0), 65535);
+                s := vleObjectProperty.Values[_lc[I_PROP_TR_DAMAGE_KIND]];
+                if s = _lc[I_PROP_TR_DAMAGE_KIND_3] then
+                  Data.DamageKind := 3
+                else if s = _lc[I_PROP_TR_DAMAGE_KIND_4] then
+                  Data.DamageKind := 4
+                else if s = _lc[I_PROP_TR_DAMAGE_KIND_5] then
+                  Data.DamageKind := 5
+                else if s = _lc[I_PROP_TR_DAMAGE_KIND_6] then
+                  Data.DamageKind := 6
+                else if s = _lc[I_PROP_TR_DAMAGE_KIND_7] then
+                  Data.DamageKind := 7
+                else if s = _lc[I_PROP_TR_DAMAGE_KIND_8] then
+                  Data.DamageKind := 8
+                else
+                  Data.DamageKind := 0;
               end;
 
             TRIGGER_HEALTH:
               end;
 
             TRIGGER_HEALTH:
@@ -5286,7 +5371,7 @@ begin
   if i = -1 then
     Exit;
 
   if i = -1 then
     Exit;
 
-  if MessageBox(0, PChar(Format(_lc[I_MSG_DEL_TEXTURE_PROMT],
+  if Application.MessageBox(PChar(Format(_lc[I_MSG_DEL_TEXTURE_PROMT],
                                 [SelectedTexture()])),
                 PChar(_lc[I_MSG_DEL_TEXTURE]),
                 MB_ICONQUESTION or MB_YESNO or
                                 [SelectedTexture()])),
                 PChar(_lc[I_MSG_DEL_TEXTURE]),
                 MB_ICONQUESTION or MB_YESNO or
@@ -5312,10 +5397,7 @@ end;
 
 procedure TMainForm.aNewMapExecute(Sender: TObject);
 begin
 
 procedure TMainForm.aNewMapExecute(Sender: TObject);
 begin
-  if (MessageBox(0, PChar(_lc[I_MSG_CLEAR_MAP_PROMT]),
-                 PChar(_lc[I_MSG_CLEAR_MAP]),
-                 MB_ICONQUESTION or MB_YESNO or
-                 MB_DEFBUTTON1) = mrYes) then
+  if Application.MessageBox(PChar(_lc[I_MSG_CLEAR_MAP_PROMT]), PChar(_lc[I_MSG_CLEAR_MAP]), MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON1) = mrYes then
     FullClear();
 end;
 
     FullClear();
 end;
 
@@ -6159,17 +6241,18 @@ begin
   MainForm.ActiveControl := RenderPanel;
 
 // Язык:
   MainForm.ActiveControl := RenderPanel;
 
 // Язык:
-  if gLanguage = '' then
+  if (gLanguage = '') and not (fsModal in SelectLanguageForm.FormState) then
   begin
     lang := SelectLanguageForm.ShowModal();
     case lang of
       1:   gLanguage := LANGUAGE_ENGLISH;
   begin
     lang := SelectLanguageForm.ShowModal();
     case lang of
       1:   gLanguage := LANGUAGE_ENGLISH;
-      else gLanguage := LANGUAGE_RUSSIAN;
+      2:   gLanguage := LANGUAGE_RUSSIAN;
+      else gLanguage := LANGUAGE_ENGLISH;
     end;
 
     end;
 
-    config := TConfig.CreateFile(EditorDir+'Editor.cfg');
+    config := TConfig.CreateFile(CfgFileName);
     config.WriteStr('Editor', 'Language', gLanguage);
     config.WriteStr('Editor', 'Language', gLanguage);
-    config.SaveFile(EditorDir+'Editor.cfg');
+    config.SaveFile(CfgFileName);
     config.Free();
   end;
 
     config.Free();
   end;
 
@@ -6198,18 +6281,17 @@ begin
     Exit;
 
   MapName := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex];
     Exit;
 
   MapName := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex];
-  if MessageBox(0, PChar(Format(_lc[I_MSG_DELETE_MAP_PROMT], [MapName, OpenDialog.FileName])), PChar(_lc[I_MSG_DELETE_MAP]), MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON2) <> mrYes then
+  if Application.MessageBox(PChar(Format(_lc[I_MSG_DELETE_MAP_PROMT], [MapName, OpenDialog.FileName])), PChar(_lc[I_MSG_DELETE_MAP]), MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON2) <> mrYes then
     Exit;
 
   g_DeleteResource(FileName, '', MapName, res);
   if res <> 0 then
   begin
     Exit;
 
   g_DeleteResource(FileName, '', MapName, res);
   if res <> 0 then
   begin
-    MessageBox(0, PChar('Cant delete map res=' + IntToStr(res)), PChar('Map not deleted!'), MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1);
+    Application.MessageBox(PChar('Cant delete map res=' + IntToStr(res)), PChar('Map not deleted!'), MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1);
     Exit
   end;
 
     Exit
   end;
 
-  MessageBox(
-    0,
+  Application.MessageBox(
     PChar(Format(_lc[I_MSG_MAP_DELETED_PROMT], [MapName])),
     PChar(_lc[I_MSG_MAP_DELETED]),
     MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1
     PChar(Format(_lc[I_MSG_MAP_DELETED_PROMT], [MapName])),
     PChar(_lc[I_MSG_MAP_DELETED]),
     MB_ICONINFORMATION or MB_OK or MB_DEFBUTTON1
@@ -6447,6 +6529,7 @@ begin
 end;
 
 procedure TMainForm.OnIdle(Sender: TObject; var Done: Boolean);
 end;
 
 procedure TMainForm.OnIdle(Sender: TObject; var Done: Boolean);
+  var f: AnsiString;
 begin
   // FIXME: this is a shitty hack
   if not gDataLoaded then
 begin
   // FIXME: this is a shitty hack
   if not gDataLoaded then
@@ -6462,6 +6545,12 @@ begin
     MainForm.FormResize(nil);
   end;
   Draw();
     MainForm.FormResize(nil);
   end;
   Draw();
+  if StartMap <> '' then
+  begin
+    f := StartMap;
+    StartMap := '';
+    OpenMap(f, '');
+  end;
 end;
 
 procedure TMainForm.miMapPreviewClick(Sender: TObject);
 end;
 
 procedure TMainForm.miMapPreviewClick(Sender: TObject);
@@ -6626,35 +6715,73 @@ begin
   MapTestForm.ShowModal();
 end;
 
   MapTestForm.ShowModal();
 end;
 
+type SSArray = array of String;
+
+function ParseString (Str: AnsiString): SSArray;
+  function GetStr (var Str: AnsiString): AnsiString;
+    var a, b: Integer;
+  begin
+    Result := '';
+    if Str[1] = '"' then
+      for b := 1 to Length(Str) do
+        if (b = Length(Str)) or (Str[b + 1] = '"') then
+        begin
+          Result := Copy(Str, 2, b - 1);
+          Delete(Str, 1, b + 1);
+          Str := Trim(Str);
+          Exit;
+        end;
+    for a := 1 to Length(Str) do
+      if (a = Length(Str)) or (Str[a + 1] = ' ') then
+      begin
+        Result := Copy(Str, 1, a);
+        Delete(Str, 1, a + 1);
+        Str := Trim(Str);
+        Exit;
+      end;
+  end;
+begin
+  Result := nil;
+  Str := Trim(Str);
+  while Str <> '' do
+  begin
+    SetLength(Result, Length(Result)+1);
+    Result[High(Result)] := GetStr(Str);
+  end;
+end;
+
 procedure TMainForm.miTestMapClick(Sender: TObject);
 var
 procedure TMainForm.miTestMapClick(Sender: TObject);
 var
-  mapWAD, mapToRun, tempWAD: String;
+  newWAD, oldWAD, tempMap, ext: String;
+  args: SSArray;
   opt: LongWord;
   opt: LongWord;
-  time: Integer;
+  time, i: Integer;
   proc: TProcessUTF8;
   res: Boolean;
 begin
   proc: TProcessUTF8;
   res: Boolean;
 begin
-  mapToRun := '';
-  if OpenedMap <> '' then
-  begin
-    // Указываем текущую карту для теста:
-    g_ProcessResourceStr(OpenedMap, @mapWAD, nil, @mapToRun);
-    mapToRun := mapWAD + ':\' + mapToRun;
-    mapToRun := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps/', mapToRun);
-  end;
+  // Ignore while map testing in progress
+  if MapTestProcess <> nil then
+    Exit;
+
   // Сохраняем временную карту:
   time := 0;
   repeat
   // Сохраняем временную карту:
   time := 0;
   repeat
-    mapWAD := ExtractFilePath(TestD2dExe) + Format('maps/temp%.4d.wad', [time]);
+    newWAD := Format('%s/temp%.4d', [MapsDir, time]);
     Inc(time);
     Inc(time);
-  until not FileExists(mapWAD);
-  tempWAD := mapWAD + ':\' + TEST_MAP_NAME;
-  SaveMap(tempWAD);
-
-  tempWAD := ExtractRelativePath(ExtractFilePath(TestD2dExe) + 'maps/', tempWAD);
-// Если карта не была открыта, указываем временную в качестве текущей:
-  if mapToRun = '' then
-    mapToRun := tempWAD;
+  until not FileExists(newWAD);
+  if OpenedMap <> '' then
+  begin
+    oldWad := g_ExtractWadName(OpenedMap);
+    newWad := newWad + ExtractFileExt(oldWad);
+    if CopyFile(oldWad, newWad) = false then
+      e_WriteLog('MapTest: unable to copy [' + oldWad + '] to [' + newWad + ']', MSG_WARNING)
+  end
+  else
+  begin
+    newWad := newWad + '.wad'
+  end;
+  tempMap := newWAD + ':\' + TEST_MAP_NAME;
+  SaveMap(tempMap);
 
 // Опции игры:
   opt := 32 + 64;
 
 // Опции игры:
   opt := 32 + 64;
@@ -6672,10 +6799,13 @@ begin
 // Запускаем:
   proc := TProcessUTF8.Create(nil);
   proc.Executable := TestD2dExe;
 // Запускаем:
   proc := TProcessUTF8.Create(nil);
   proc.Executable := TestD2dExe;
+  {$IFDEF DARWIN}
+    // TODO: get real executable name from Info.plist
+    if LowerCase(ExtractFileExt(TestD2dExe)) = '.app' then
+      proc.Executable := TestD2dExe + DirectorySeparator + 'Contents' + DirectorySeparator + 'MacOS' + DirectorySeparator + 'Doom2DF';
+  {$ENDIF}
   proc.Parameters.Add('-map');
   proc.Parameters.Add('-map');
-  proc.Parameters.Add(mapToRun);
-  proc.Parameters.Add('-testmap');
-  proc.Parameters.Add(tempWAD);
+  proc.Parameters.Add(tempMap);
   proc.Parameters.Add('-gm');
   proc.Parameters.Add(TestGameMode);
   proc.Parameters.Add('-limt');
   proc.Parameters.Add('-gm');
   proc.Parameters.Add(TestGameMode);
   proc.Parameters.Add('-limt');
@@ -6688,6 +6818,10 @@ begin
   if TestMapOnce then
     proc.Parameters.Add('--close');
 
   if TestMapOnce then
     proc.Parameters.Add('--close');
 
+  args := ParseString(TestD2DArgs);
+  for i := 0 to High(args) do
+    proc.Parameters.Add(args[i]);
+
   res := True;
   try
     proc.Execute();
   res := True;
   try
     proc.Execute();
@@ -6696,31 +6830,28 @@ begin
   end;
   if res then
   begin
   end;
   if res then
   begin
-    Application.Minimize();
-    proc.WaitOnExit();
-  end;
-  if (not res) or (proc.ExitCode < 0) then
+    tbTestMap.Enabled := False;
+    MapTestFile := newWAD;
+    MapTestProcess := proc;
+  end
+  else
   begin
   begin
-    MessageBox(0, 'FIXME',
-               PChar(_lc[I_MSG_EXEC_ERROR]),
-               MB_OK or MB_ICONERROR);
+    Application.MessageBox(PChar(_lc[I_MSG_EXEC_ERROR]), 'FIXME', MB_OK or MB_ICONERROR);
+    SysUtils.DeleteFile(newWAD);
+    proc.Free();
   end;
   end;
-  proc.Free();
-
-  SysUtils.DeleteFile(mapWAD);
-  Application.Restore();
 end;
 
 procedure TMainForm.sbVerticalScroll(Sender: TObject;
   ScrollCode: TScrollCode; var ScrollPos: Integer);
 begin
 end;
 
 procedure TMainForm.sbVerticalScroll(Sender: TObject;
   ScrollCode: TScrollCode; var ScrollPos: Integer);
 begin
-  MapOffset.Y := -Normalize16(sbVertical.Position);
+  MapOffset.Y := -sbVertical.Position;
 end;
 
 procedure TMainForm.sbHorizontalScroll(Sender: TObject;
   ScrollCode: TScrollCode; var ScrollPos: Integer);
 begin
 end;
 
 procedure TMainForm.sbHorizontalScroll(Sender: TObject;
   ScrollCode: TScrollCode; var ScrollPos: Integer);
 begin
-  MapOffset.X := -Normalize16(sbHorizontal.Position);
+  MapOffset.X := -sbHorizontal.Position;
 end;
 
 procedure TMainForm.miOpenWadMapClick(Sender: TObject);
 end;
 
 procedure TMainForm.miOpenWadMapClick(Sender: TObject);