unit S_G_E;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls, Grids, Spin, StrUtils;

type
  TForm1 = class(TForm)
    Load: TButton;
    L: TOpenDialog;
    Map: TStringGrid;
    Label1: TLabel;
    Skill: TSpinEdit;
    Level: TSpinEdit;
    Lives: TSpinEdit;
    Label2: TLabel;
    OldSc: TSpinEdit;
    CurSc: TSpinEdit;
    BonSc: TSpinEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Health: TSpinEdit;
    Ammo: TSpinEdit;
    Label6: TLabel;
    Keys: TStringGrid;
    Label7: TLabel;
    WBest: TSpinEdit;
    WCurr: TSpinEdit;
    WSel: TSpinEdit;
    Face: TSpinEdit;
    Label8: TLabel;
    TechAF: TSpinEdit;
    TechAC: TSpinEdit;
    TechWF: TSpinEdit;
    Label10: TLabel;
    Epis: TSpinEdit;
    RCS: TSpinEdit;
    RCT: TSpinEdit;
    RCK: TSpinEdit;
    RTS: TSpinEdit;
    RTT: TSpinEdit;
    RTK: TSpinEdit;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    TimeCount: TSpinEdit;
    DCamF: TSpinEdit;
    DCamY: TSpinEdit;
    DCamX: TSpinEdit;
    Label14: TLabel;
    FormatCLevels: TSpinEdit;
    Label15: TLabel;
    HistKill: TSpinEdit;
    HistSecr: TSpinEdit;
    HistTreas: TSpinEdit;
    HistNum: TSpinEdit;
    HistTime: TSpinEdit;
    Label16: TLabel;
    Label17: TLabel;
    DrawWall: TCheckBox;
    DrawNum: TSpinEdit;
    DrawObst: TCheckBox;
    DrawOO: TSpinEdit;
    Obj0Ptr: TSpinEdit;
    Obj0PtrAuto: TCheckBox;
    Label18: TLabel;
    FormatNFloors: TSpinEdit;
    Save: TButton;
    S: TSaveDialog;
    Label9: TLabel;
    Bevel1: TBevel;
    FormatNThings: TSpinEdit;
    Label19: TLabel;
    SetDTrack: TButton;
    SetDoor: TButton;
    T0Ptr: TSpinEdit;
    Label20: TLabel;
    NextFreeSObjPtr: TSpinEdit;
    ThingsAmount: TSpinEdit;
    Label21: TLabel;
    Label22: TLabel;
    Bevel2: TBevel;
    ThingNum: TSpinEdit;
    ThingX: TSpinEdit;
    ThingY: TSpinEdit;
    ThingVisspot: TSpinEdit;
    ThingShapeNum: TSpinEdit;
    ThingFlags: TSpinEdit;
    ThingItemNum: TSpinEdit;
    ThingItemName: TLabel;
    Label23: TLabel;
    Label24: TLabel;
    Vsp0Ptr: TSpinEdit;
    VSp0PtrAuto: TCheckBox;
    ThShootable: TCheckBox;
    ThBonus: TCheckBox;
    ThNevermark: TCheckBox;
    ThVisable: TCheckBox;
    ThAttackMode: TCheckBox;
    ThFirstAttack: TCheckBox;
    ThAmbush: TCheckBox;
    ThNonmark: TCheckBox;
    VisspotAuto: TButton;
    Name: TMemo;
    ObjActive: TSpinEdit;
    ObjTicks: TSpinEdit;
    ObjClass: TSpinEdit;
    ObjFramePtr: TSpinEdit;
    ObjNum: TSpinEdit;
    ObjFlags: TSpinEdit;
    ObjDist: TSpinEdit;
    ObjDir: TSpinEdit;
    ObjX: TSpinEdit;
    ObjY: TSpinEdit;
    ObjTX: TSpinEdit;
    ObjTY: TSpinEdit;
    ObjFloor: TSpinEdit;
    ObjGX: TSpinEdit;
    ObjGY: TSpinEdit;
    ObjViewX: TSpinEdit;
    ObjViewH: TSpinEdit;
    ObjAngle: TSpinEdit;
    ObjHealth: TSpinEdit;
    ObjSpeed: TSpinEdit;
    ObjT1: TSpinEdit;
    ObjT2: TSpinEdit;
    ObjT3: TSpinEdit;
    Bevel3: TBevel;
    FlagsForObj: TBevel;
    FlagsForThings: TBevel;
    FlagsForThings2: TBevel;
    FlagsForObj2: TBevel;
    ObjNext: TSpinEdit;
    ObjPrev: TSpinEdit;
    Label25: TLabel;
    Label26: TLabel;
    Label27: TLabel;
    Label28: TLabel;
    Label29: TLabel;
    DirLabel: TLabel;
    ObjAmount: TSpinEdit;
    ObClassLabel: TLabel;
    ObjCenter: TButton;
    ObjInDrag: TSpinEdit;
    ThingInDrag: TSpinEdit;
    LevPerEpis: TSpinEdit;
    Label30: TLabel;
    Label31: TLabel;
    RefreshUnchangeables: TButton;
    Image1: TImage;
    DoorNum: TSpinEdit;
    DoorInDrag: TSpinEdit;
    Image2: TImage;
    DoorX: TSpinEdit;
    DoorY: TSpinEdit;
    DoorAng: TSpinEdit;
    DoorLock: TSpinEdit;
    DoorMotion: TSpinEdit;
    DoorTicCount: TSpinEdit;
    DoorPosit: TSpinEdit;
    DoorAngLabel: TLabel;
    DoorMotionLabel: TLabel;
    Label32: TLabel;
    Label33: TLabel;
    SoundArea0: TSpinEdit;
    Label34: TLabel;
    Label35: TLabel;
    PWOdo: TSpinEdit;
    PWX: TSpinEdit;
    PWY: TSpinEdit;
    PWDir: TSpinEdit;
    PWPos: TSpinEdit;
    Label36: TLabel;
    HearFloor: TSpinEdit;
    Label37: TLabel;
    Hear: TSpinEdit;
    AreaCon: TStringGrid;
    PWallDirLabel: TLabel;
    procedure LoadClick(Sender: TObject);
    procedure MapSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure KeysSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure HistNumChange(Sender: TObject);
    procedure HistTimeChange(Sender: TObject);
    procedure HistKillChange(Sender: TObject);
    procedure HistSecrChange(Sender: TObject);
    procedure HistTreasChange(Sender: TObject);
    procedure MapDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure SaveClick(Sender: TObject);
    procedure MapMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure DrawNumChange(Sender: TObject);
    procedure DrawOOChange(Sender: TObject);
    procedure MapMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure SetDTrackClick(Sender: TObject);
    procedure SetDoorClick(Sender: TObject);
    procedure T0PtrChange(Sender: TObject);
    procedure NextFreeSObjPtrChange(Sender: TObject);
    procedure ThingsAmountChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ThingNumChange(Sender: TObject);
    procedure WlThingClick(Sender: TObject);
    procedure WlDoorClick(Sender: TObject);
    procedure WlMObjPress(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure WlThingPress(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ThingXChange(Sender: TObject);
    procedure ThingYChange(Sender: TObject);
    procedure ThingVisspotChange(Sender: TObject);
    procedure ThingShapeNumChange(Sender: TObject);
    procedure ThingFlagsChange(Sender: TObject);
    procedure ThingItemNumChange(Sender: TObject);
    procedure VisspotAutoClick(Sender: TObject);
    procedure ThingFlagCheck(Sender: TObject);
    procedure ObjNumChange(Sender: TObject);
    procedure ObjFlagsChange(Sender: TObject);
    procedure ObjActiveChange(Sender: TObject);
    procedure ObjTicksChange(Sender: TObject);
    procedure ObjClassChange(Sender: TObject);
    procedure ObjFramePtrChange(Sender: TObject);
    procedure ObjDistChange(Sender: TObject);
    procedure ObjDirChange(Sender: TObject);
    procedure ObjFloorChange(Sender: TObject);
    procedure ObjTXChange(Sender: TObject);
    procedure ObjTYChange(Sender: TObject);
    procedure ObjXChange(Sender: TObject);
    procedure ObjYChange(Sender: TObject);
    procedure ObjViewXChange(Sender: TObject);
    procedure ObjViewHChange(Sender: TObject);
    procedure ObjGXChange(Sender: TObject);
    procedure ObjGYChange(Sender: TObject);
    procedure ObjAngleChange(Sender: TObject);
    procedure ObjHealthChange(Sender: TObject);
    procedure ObjSpeedChange(Sender: TObject);
    procedure ObjT1Change(Sender: TObject);
    procedure ObjT2Change(Sender: TObject);
    procedure ObjT3Change(Sender: TObject);
    procedure ObjNextChange(Sender: TObject);
    procedure ObjPrevChange(Sender: TObject);
    procedure ObjAmountChange(Sender: TObject);
    procedure Obj0PtrChange(Sender: TObject);
    procedure ObjCenterClick(Sender: TObject);
    procedure ObjInDragChange(Sender: TObject);
    procedure ThingInDragChange(Sender: TObject);
    procedure RefreshUnchangeablesClick(Sender: TObject);
    procedure DoorInDragChange(Sender: TObject);
    procedure DoorNumChange(Sender: TObject);
    procedure DoorXChange(Sender: TObject);
    procedure DoorYChange(Sender: TObject);
    procedure DoorLockChange(Sender: TObject);
    procedure DoorMotionChange(Sender: TObject);
    procedure DoorAngChange(Sender: TObject);
    procedure DoorTicCountChange(Sender: TObject);
    procedure DoorPositChange(Sender: TObject);
    procedure HearFloorChange(Sender: TObject);
    procedure HearChange(Sender: TObject);
    procedure FormatNFloorsChange(Sender: TObject);
    procedure AreaConSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure AreaConSetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure PWDirChange(Sender: TObject);
    procedure PWXChange(Sender: TObject);
    procedure PWYChange(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type wolfobj = record
  active: smallint;
  ticcount,obclass,statetype,flags: word;
  distance: integer;
  dir: word;
  x,y: integer;
  tilex,tiley: smallint;
  areanum,viewx,viewheight: word;
  transx,transy: dword;
  angle, hitpoints: word;
  speed: dword;
  temp1,temp2,temp3,next,prev: word;  //Achtung: next&prev are ignored by the game engine. IDK what to do with them.
  B: TShape;
  Bset: boolean;
end;  //size=60 plus interface;

type thing = record
  x,y: byte;
  visspot: word;
  shapenum: smallint; //-1 means "dead" (removed, picked up) thing
  flags, itemnum: byte;
  B: TPanel;
  Bset: boolean;
end; //size=8 plus interface;

type door = record
  x,y: byte;
  vertflag: byte;
  lock: byte;
  motion: word;
  ticcount: dword;
  B: TImage;
end;

const WOLFPAL: array[0..255] of integer = ($0,$a80000,$a800,$a8a800,$a8,$a800a8,$54a8,$a8a8a8,$545454,$fc5454,$54fc54,$fcfc54,$5454fc,$fc54fc,$54fcfc,$fcfcfc,$ececec,$dcdcdc,$d0d0d0,$c0c0c0,$b4b4b4,$a8a8a8,$989898,$8c8c8c,$7c7c7c,$707070,$646464,$545454,$484848,$383838,$2c2c2c,$202020,$fc,$ec,$e0,$d4,$c8,$bc,$b0,$a4,$98,$88,$7c,$70,$64,$58,$4c,$40,$d8d8fc,$b8b8fc,$9c9cfc,$7c7cfc,$5c5cfc,$4040fc,$2020fc,$fc,$5ca8fc,$4098fc,$2088fc,$78fc,$6ce4,$60cc,$54b4,$4c9c,
$d8fcfc,$b8fcfc,$9cfcfc,$7cfcfc,$5cf8fc,$40f4fc,$20f4fc,$f4fc,$d8e4,$c4cc,$acb4,$9c9c,$8484,$6c70,$5458,$4040,$5cfcd0,$40fcc4,$20fcb4,$fca0,$e490,$cc80,$b474,$9c60,$d8fcd8,$b8fcbc,$9cfc9c,$7cfc80,$5cfc60,$40fc40,$20fc20,$fc00,$fc00,$ec00,$e000,$d400,$c804,$bc04,$b004,$a404,$9804,$8804,$7c04,$7004,$6404,$5804,$4c04,$4004,$fcfcd8,$fcfcb8,$fcfc9c,$f8fc7c,$fcfc5c,$fcfc40,$fcfc20,$fcfc00,$e4e400,$cccc00,$b4b400,$9c9c00,$848400,$707000,$585800,$404000,
$fcbc5c,$fcb040,$fca820,$fc9c00,$e48c00,$cc7c00,$b46c00,$9c5c00,$fcd8d8,$fcbcb8,$fc9c9c,$fc807c,$fc605c,$fc4040,$fc2420,$fc0400,$fc0000,$ec0000,$e00000,$d40000,$c80000,$bc0000,$b00000,$a40000,$980000,$880000,$7c0000,$700000,$640000,$580000,$4c0000,$400000,$282828,$34e0fc,$24d4fc,$18ccfc,$8c0fc,$b4fc,$fc20b4,$fc00a8,$e40098,$cc0080,$b40074,$9c0060,$840050,$700044,$580034,$400028,$fcd8fc,$fcb8fc,$fc9cfc,$fc7cfc,$fc5cfc,$fc40fc,$fc20fc,$fc00fc,$e400e0,$cc00c8,$b400b4,$9c009c,$840084,$70006c,$580058,$400040,
$dce8fc,$d0e0fc,$c4d8fc,$bcd4fc,$b0ccfc,$a4c4fc,$9cbcfc,$90b8fc,$80b0fc,$70a4fc,$609cfc,$5c94f0,$588ce8,$5488dc,$5080d0,$4c7cc8,$4878bc,$4470b4,$4068a8,$3c64a0,$38609c,$345c90,$305888,$2c5080,$284c74,$24486c,$20405c,$1c3c54,$183848,$183040,$142c38,$c2028,$640060,$646400,$606000,$1c0000,$2c0000,$102430,$480048,$500050,$340000,$1c1c1c,$4c4c4c,$5c5c5c,$404040,$303030,$343434,$f4f4d8,$e8e8b8,$dcdc9c,$c8c874,$c0c048,$b4b420,$b0b020,$a4a400,$989800,$8c8c00,$848400,$7c7c00,$787800,$747400,$707000,$6c6c00,$880098);

var
  Form1: TForm1;
  rawdata: array [0..65535] of byte;
  oldKSTTi: array[0..3,0..255] of dword;
  SndLnks: array [0..127,0..127] of byte;
  SndZone: array [0..127] of word;
  MObj: array [0..511] of wolfobj;
  NumOfMObj: integer;
  SObj: array [0..1023] of thing;
  DoorPos: array [0..63] of word;
  DoorStat: array [0..63] of door;
  unchangeables: array [0..1,0..63,0..63] of byte;
  csum: dword;
  ThingNeedsRepaint: word;
  MObjNeedsRepaint: word;
  PrevFloorForRepaint: integer;
  PWRepaintX,PWRepaintY: byte;

implementation

{$R *.dfm}

procedure LoadUnchangeables; //Achtung: corrupts RawDATA!!!
var f: file of byte;
i,j,k,rlewtag,aIn,aOut,Ch,Count: word;
pos,compressed,plane: integer;
maptype: array [0..37] of byte;
buff: array [0..65535] of byte;
origmap: array [0..1,0..63,0..63] of word;
begin
    //Xранить те тайлы, которые в контакте с дверью дают черт-те что с минусом.

  //Now we must load turning points and floor numbers from the original map.
// orig: void CAL_SetupMapFile (void)
// load maphead.ext (offsets and tileinfo for map file)
    for i:=0 to 63 do for j:=0 to 63 do unchangeables[0,j,i]:=0;
    for i:=0 to 63 do for j:=0 to 63 do unchangeables[1,j,i]:=0;
    assignfile (f,'MAPHEAD'+RightStr(Form1.L.FileName,4));
 {$I-}
    reset (f);
    if IOResult<>0 then begin MessageBox(0, 'Achtung: original MAPHEAD.??? not present. Floor areas, secrets, turning and exit points are not loaded', 'Achtung!', MB_OK); Form1.Caption:='SaveGam?.* Editor: MAPHEAD.??? not found'; exit end;
 {$I+}
    read (f,maptype[0]);read (f,maptype[1]);rlewtag:=maptype[1]*256+maptype[0];
    i:=Form1.Epis.Value*Form1.LevPerEpis.Value+Form1.Level.Value-1;
// struct unsigned RLEWtag, long headeroffsets[100], byte tileinfo[] is mapfiletype;
    seek (f,i*4+2);
    for i:=0 to 3 do read (f,maptype[i]);//uses as temp;
    pos:=maptype[0]+(maptype[1] shl 8)+(maptype[2] shl 16)+(maptype[3] shl 24);
    closefile (f);
// open the data file
    assignfile (f,'GAMEMAPS'+RightStr(Form1.L.FileName,4));
 {$I-}
    reset (f);
    if IOResult<>0 then begin MessageBox(0, 'Achtung: original GAMEMAPS.??? not present. Floor areas, secrets, turning and exit points are not loaded', 'Achtung!', MB_OK); Form1.Caption:='SaveGam?.* Editor: GAMEMAPS.??? not found'; exit end;
 {$I+}
// load map header
    seek (f,pos);
// struct long planestart[3], unsigned planelength[3], unsigned width,height, char name[16] is maptype;
    for i:=0 to 37 do read (f,maptype[i]);
// Orig: void SetupGameLevel (void)
// load the level
//Inline. Orig: void CA_CacheMap (int mapnum)
   for plane := 0 to 1 do begin
      pos :=maptype[plane*4]+(maptype[plane*4+1] shl 8)+(maptype[plane*4+2] shl 16)+(maptype[plane*4+3] shl 24);
      compressed := maptype[plane*2+12]+(maptype[plane*2+13] shl 8);
      seek (f,pos);
      for i:=0 to compressed-1 do read (f,rawdata[i]);
      // unhuffman, then unRLEW. The huffman'd chunk has a two byte expanded length first. The resulting RLEW chunk also does, even though it's not really needed.
//Inline. Orig: void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length)
   i:=(rawdata[0]+rawdata[1]*256) shr 1;
   aIn:=2;
   aOut:=0;
   while i>0 do begin
      Ch := rawdata[aIn]+rawdata[aIn+1]*256;aIn:=aIn+2;
      if ((Ch and $ff00) = $a700) then begin
         Count := Ch and 255;
         if (Count=0) then begin // have to insert a word containing the tag byte
            Ch := Ch or rawdata [aIn]; aIn:=aIn+1;
            buff[aOut]:=Ch and 255; buff[aOut+1]:=Ch shr 8; aOut:=aOut+2;
            i:=i-1;
         end else begin
              for j:=aOut to aOut+Count*2-1 do Buff[j]:=buff[j-rawdata[aIn]*2];
              aIn:=aIn+1;
              aOut:=aOut+Count*2;
              i:=i-Count;
         end;
      end
      else if ((Ch and $ff00) = $a800) then begin
         Count := Ch and 255;
         if (Count=0) then begin // have to insert a word containing the tag byte
            Ch := Ch or rawdata [aIn]; aIn:=aIn+1;
            buff[aOut]:=Ch and 255; buff[aOut+1]:=Ch shr 8; aOut:=aOut+2;
            i:=i-1;
         end else begin
              for j:=0 to Count*2-1 do Buff[aOut+j]:=buff[rawdata[aIn]*2+rawdata[aIn+1]*512+j];
              aIn:=aIn+2;
              aOut:=aOut+Count*2;
              i:=i-Count;
         end;
      end
      else begin
         buff[aOut]:=Ch and 255; buff[aOut+1]:=Ch shr 8; aOut:=aOut+2;
         i:=i-1;
      end;
   end;
//inline end
//Inline. Orig: void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length, unsigned rlewtag)
  aIn:=2; aOut:=0;
  repeat
   i := Buff[aIn]+Buff[aIn+1]*256; aIn:=aIn+2;
   if i<>rlewtag then begin
   // uncompressed
     origmap[plane,aOut div 64,aOut mod 64]:=i;
     aOut:=aOut+1;
   end else begin
   // compressed string
     j := Buff[aIn]+Buff[aIn+1]*256; aIn:=aIn+2;
     i := Buff[aIn]+Buff[aIn+1]*256; aIn:=aIn+2;
     for k:=1 to j do begin
       origmap[plane,aOut div 64,aOut mod 64]:=i;
       aOut:=aOut+1;
     end;
   end;
  until aOut>=64*64;
// Inline end;
   end;
//Inline end;
   closefile (f);
//Something inspired by original code
   if (maptype[18]<>64) or (maptype[19]<>0) or (maptype[20]<>64) or (maptype[21]<>0) then begin MessageBox(0, 'Achtung: map header is invalid (size not 64x64)', 'Achtung!', MB_OK); Form1.Caption:='SaveGam?.* Editor: map header is invalid' end;
   for i:=0 to 63 do for j:=0 to 63 do if origmap[0,i,j]>=Form1.SoundArea0.Value then unchangeables[0,j,i]:=origmap[0,i,j] else unchangeables[0,j,i]:=0; //area numbers;
   for i:=0 to 63 do for j:=0 to 63 do if (origmap[1,i,j]>=90) {and (origmap[1,i,j]<=97)} then unchangeables[1,j,i]:=origmap[1,i,j] else unchangeables[1,j,i]:=0; //turning/exit points;
end;

procedure TForm1.LoadClick(Sender: TObject);
var f: file of byte;
i: word;
begin
  if (L.Execute) then begin
    assignfile (f,L.FileName);
    reset (F);
    i:=0;
    while not (eof(f)) do begin read (f,rawdata[i]);i:=i+1; end;
    closefile (f);

    Name.Text:='';
    for i:=0 to 31 do if rawdata[i]>0 then Name.Text:=Name.Text+chr(rawdata[i]) else break;
    Skill.Value:=rawdata[32]+rawdata[33]*256;
    Level.Value:=rawdata[34]+rawdata[35]*256+1;
    OldSc.Value:=rawdata[36]+rawdata[37]*256+rawdata[38]*65536+rawdata[39]*16777216;
    CurSc.Value:=rawdata[40]+rawdata[41]*256+rawdata[42]*65536+rawdata[43]*16777216;
    BonSc.Value:=rawdata[44]+rawdata[45]*256+rawdata[46]*65536+rawdata[47]*16777216;
    Lives.Value:=rawdata[48]+rawdata[49]*256;
    Health.Value:=rawdata[50]+rawdata[51]*256;
    Ammo.Value:=rawdata[52]+rawdata[53]*256;
    if rawdata[54] and 1 > 0 then Keys.Cells[0,0]:='G' else Keys.Cells[0,0]:='';
    if rawdata[54] and 2 > 0 then Keys.Cells[0,1]:='S' else Keys.Cells[0,1]:='';
    for i:=2 to 15 do if (rawdata[54]+rawdata[55]*256) and (1 shl i) > 0 then Keys.Cells[i div 2,i mod 2]:=inttostr(i+1) else Keys.Cells[i div 2,i mod 2]:='';
    WBest.Value:=rawdata[56]+rawdata[57]*256;
    WCurr.Value:=rawdata[58]+rawdata[59]*256;
    WSel.Value:=rawdata[60]+rawdata[61]*256;
    Face.Value:=rawdata[62]+rawdata[63]*256;
    TechAF.Value:=rawdata[64]+rawdata[65]*256;
    TechAC.Value:=rawdata[66]+rawdata[67]*256;
    TechWF.Value:=rawdata[68]+rawdata[69]*256;
    Epis.Value:=rawdata[70]+rawdata[71]*256;
    RCS.Value:=rawdata[72]+rawdata[73]*256;
    RCT.Value:=rawdata[74]+rawdata[75]*256;
    RCK.Value:=rawdata[76]+rawdata[77]*256;
    RTS.Value:=rawdata[78]+rawdata[79]*256;
    RTT.Value:=rawdata[80]+rawdata[81]*256;
    RTK.Value:=rawdata[82]+rawdata[83]*256;
    TimeCount.Value:=rawdata[84]+rawdata[85]*256+rawdata[86]*65536+rawdata[87]*16777216;
    DCamX.Value:=rawdata[88]+rawdata[89]*256+rawdata[90]*65536+rawdata[91]*16777216;
    DCamY.Value:=rawdata[92]+rawdata[93]*256+rawdata[94]*65536+rawdata[95]*16777216;
    DCamF.Value:=rawdata[96]+rawdata[97]*256;
    if FormatCLevels.Value>0 then for i:=0 to FormatCLevels.Value-1 do begin
      oldKSTTi[0,i]:=rawdata[98 +i*10]+rawdata[99 +i*10]*256;
      oldKSTTi[1,i]:=rawdata[100+i*10]+rawdata[101+i*10]*256;
      oldKSTTi[2,i]:=rawdata[102+i*10]+rawdata[103+i*10]*256;
      oldKSTTi[3,i]:=rawdata[104+i*10]+rawdata[105+i*10]*256+rawdata[106+i*10]*65536+rawdata[107+i*10]*16777216;
    end;
    HistNum.Value:=2;HistNum.Value:=1;//Refresh value force-calling TForm1.HistNumChange
    if Obj0PtrAuto.Checked then begin
      Obj0Ptr.Value:=$7FFFFFFF;
      for i:=0 to 4095 do if (rawdata[4195+FormatCLevels.Value*10+i*2]>0) and (rawdata[4194+FormatCLevels.Value*10+i*2]+rawdata[4195+FormatCLevels.Value*10+i*2]*256<Obj0Ptr.Value) then Obj0Ptr.Value:=rawdata[4194+FormatCLevels.Value*10+i*2]+rawdata[4195+FormatCLevels.Value*10+i*2]*256;
      Obj0Ptr.Value:=Obj0Ptr.Value-60;//Player is not on map :)
    end;
    for i:=0 to 4095 do Map.Cells[i div 64,i mod 64]:=inttostr(rawdata[98+FormatCLevels.Value*10+i]+rawdata[4194+FormatCLevels.Value*10+i*2]*256+rawdata[4195+FormatCLevels.Value*10+i*2]*65536);
    for i:=0 to FormatNFloors.Value*FormatNFloors.Value-1 do SndLnks[i div FormatNFloors.Value][i mod FormatNFloors.Value]:=rawdata[12386+FormatCLevels.Value*10+i];
    for i:=0 to FormatNFloors.Value-1 do SndZone[i]:=rawdata[12386+FormatNFloors.Value*FormatNFloors.Value+FormatCLevels.Value*10+i*2]+rawdata[12386+FormatNFloors.Value*FormatNFloors.Value+FormatCLevels.Value*10+i*2+1]*256;
    HearFloor.Value:=1;HearFloor.Value:=0;//Refresh value force-calling TForm1.HearFloorChange
    ObjAmount.Value:=1;ObjAmount.Value:=0;
    i:=$FFFF; repeat
      i:=i+1;
      MObj[i].active:=   rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+1] shl 8);
      MObj[i].ticcount:= rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+2]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+3]*256;
      MObj[i].obclass:=  rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+4]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+5]*256;
      MObj[i].statetype:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+6]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+7]*256;
      MObj[i].flags:=    rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+8]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+9]*256;
      MObj[i].distance:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+10] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+11] shl 8) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+12] shl 16) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+13] shl 24);
      MObj[i].dir:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+14]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+15]*256;
      MObj[i].x:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+16] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+17] shl 8) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+18] shl 16) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+19] shl 24);
      MObj[i].y:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+20] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+21] shl 8) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+22] shl 16) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+23] shl 24);
      MObj[i].tilex     :=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+24]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+25]*256;
      MObj[i].tiley     :=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+26]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+27]*256;
      MObj[i].areanum   :=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+28]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+29]*256;
      MObj[i].viewx     :=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+30]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+31]*256;
      MObj[i].viewheight:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+32]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+33]*256;
      MObj[i].transx:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+34] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+35] shl 8) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+36] shl 16) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+37] shl 24);
      MObj[i].transy:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+38] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+39] shl 8) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+40] shl 16) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+41] shl 24);
      MObj[i].angle:=    rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+42]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+43]*256;
      MObj[i].hitpoints:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+44]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+45]*256;
      MObj[i].speed:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+46] or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+47] shl 8) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+48] shl 16) or (rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+49] shl 24);
      MObj[i].temp1:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+50]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+51]*256;
      MObj[i].temp2:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+52]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+53]*256;
      MObj[i].temp3:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+54]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+55]*256;
      MObj[i].next :=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+56]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+57]*256;
      MObj[i].prev :=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+58]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+59]*256;
    until MObj[i].active=-1;ObjAmount.Value:=i;ObjNum.Value:=1;ObjNum.Value:=0;
    NextFreeSObjPtr.Value:=T0Ptr.Value;
    for i:= 0 to FormatNThings.Value-1 do begin
      SObj[i].x:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8];
      SObj[i].y:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+1];
      SObj[i].visspot:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+2]+rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+3]*256;
      SObj[i].shapenum:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+4] or (rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+5] shl 8);
      SObj[i].flags:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+6];
      SObj[i].itemnum:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+7];
    end;  //Must be loaded prior to NextFreeSObjPtr to provide data for immediate displaying;
    ThingNum.Value:=1;ThingNum.Value:=0;
    NextFreeSObjPtr.Value:=rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60]+rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+1]*256;
    if Vsp0PtrAuto.Checked then Vsp0Ptr.Value:=SObj[0].visspot-SObj[0].y-SObj[0].x*64;
    for i:= 0 to 63 do DoorPos[i]:=rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*2]+rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*2+1]*256;
    for i:= 0 to 63 do begin
      DoorStat[i].x:=rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10];
      DoorStat[i].y:=rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+1];
      DoorStat[i].B.Left:=(DoorStat[i].x mod 64)*11+8;
      DoorStat[i].B.Top :=(DoorStat[i].y mod 64)*11+2;
      DoorStat[i].vertflag:=rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+2]+rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+3]*256;
      DoorStat[i].lock:=rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+4]+rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+5]; //that's a byte, but it is 2-byte-aligned and HI may be used in some TCs.
      DoorStat[i].motion:=rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+6]+rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+7]*256;
      DoorStat[i].ticcount:=rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+8]+rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+9]*256;
    end;
    DoorNum.Value:=1;DoorNum.Value:=0;
    PWOdo.Value:=rawdata[13156+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]+rawdata[13156+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]*256;
    PWX.Value  :=rawdata[13158+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]+rawdata[13158+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]*256;
    PWY.Value  :=rawdata[13160+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]+rawdata[13160+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]*256;
    PWDir.Value:=rawdata[13162+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]+rawdata[13162+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]*256;
    PWPos.Value:=rawdata[13164+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]+rawdata[13164+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]*256;
    csum:=rawdata[13166+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]+rawdata[13167+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]*256+rawdata[13168+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]*65536+rawdata[13169+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]*16777216;
    LoadUnchangeables;
  end;
end;

procedure TForm1.MapSelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean);
  label nezatemprishel;
  var v: integer;
begin
  if ThingInDrag.Value=1 then goto nezatemprishel;
  if ObjInDrag.Value=1 then goto nezatemprishel;
  if DoorInDrag.Value=1 then goto nezatemprishel;
  trystrtoint(Map.Cells[ACol,ARow],v);
  if DrawWall.Checked then v:=(v and $FFFF00) or DrawNum.Value;
  if DrawObst.Checked then v:=(v and $FF) or DrawOO.Value*256;
  Map.Cells[ACol,ARow]:=inttostr(v);
nezatemprishel:
  ThingInDrag.Value:=0;
  ObjInDrag.Value:=0;
  DoorInDrag.Value:=0;
end;

procedure TForm1.KeysSelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
  if Keys.Cells[ACol,ARow]<>'' then Keys.Cells[ACol,ARow]:='' else begin
    if (ACol=0) and (ARow=0) then Keys.Cells[0,0]:='G';
    if (ACol=0) and (ARow=1) then Keys.Cells[0,1]:='S';
    if ACol>0 then Keys.Cells[ACol,ARow]:=inttostr(ACol*2+ARow+1);
  end;
end;

procedure TForm1.HistNumChange(Sender: TObject);
begin
  HistTime.Value:=oldKSTTi[3,HistNum.Value-1];
  HistKill.Value:=oldKSTTi[0,HistNum.Value-1];
  HistSecr.Value:=oldKSTTi[1,HistNum.Value-1];
  HistTreas.Value:=oldKSTTi[2,HistNum.Value-1];
end;

procedure TForm1.HistTimeChange(Sender: TObject);
begin
  oldKSTTi[3,HistNum.Value-1]:=HistTime.Value;
end;

procedure TForm1.HistKillChange(Sender: TObject);
begin
  oldKSTTi[0,HistNum.Value-1]:=HistKill.Value;
end;

procedure TForm1.HistSecrChange(Sender: TObject);
begin
  oldKSTTi[1,HistNum.Value-1]:=HistSecr.Value;
end;

procedure TForm1.HistTreasChange(Sender: TObject);
begin
  oldKSTTi[2,HistNum.Value-1]:=HistTreas.Value;
end;

procedure TForm1.MapDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
  var vl,o:integer;
  tx: string;
begin
  o:=-1;
  if not (trystrtoint(Map.Cells[ACol,ARow],vl)) then vl:=0;
  vl:=vl mod 256;
  if       vl=0   then tx:=''
   else if vl<64  then tx:=chr(65+(vl   ) div 26)+chr(65+(vl   ) mod 26)
   else if vl<128 then tx:=chr(97+(vl-64) div 26)+chr(97+(vl-64) mod 26)
   else                tx:=inttostr(vl-128);

  if not (trystrtoint(Map.Cells[ACol,ARow],vl)) then vl:=0;
  vl:=vl div 256;
  if vl>255 then begin
    o:=(vl-Obj0Ptr.Value) div 60;
    vl:=(vl-Obj0Ptr.Value) mod 60;
    if vl>0 then Obj0Ptr.Color:=clRed else Obj0Ptr.Color:=clWindow;
    if vl>0 then vl:=248 else vl:=o mod 256;
  end;
  Map.Canvas.Brush.Color:=(7 - vl mod 8)*36+(5 - vl div 8 mod 4)*51*256+(7 - vl div 32)*36*256*256;
  Map.Canvas.Brush.Style:=bsSolid;
  Map.Canvas.FillRect(Rect);
  Map.Canvas.Font.Assign(Map.Font);
  Map.Canvas.TextRect(Rect,Rect.Left-1,Rect.Top,tx);

  if unchangeables [0, ACol, ARow]>90 then begin
    vl:=unchangeables [0, ACol, ARow];
    Map.Canvas.Pen.Color:=(3 - vl mod 4)*85+(7 - vl div 4 mod 8)*36*256+(7 - vl div 32)*36*256*256;
    Map.Canvas.Pen.Style:=psSolid;
    Map.Canvas.MoveTo(Rect.Left,Rect.Top);
    Map.Canvas.LineTo(Rect.Right,Rect.Top);
    Map.Canvas.LineTo(Rect.Right,Rect.Bottom);
    Map.Canvas.LineTo(Rect.Left,Rect.Bottom);
    Map.Canvas.LineTo(Rect.Left,Rect.Top);
  end;

  if o>=0 then begin
    Map.Canvas.Pen.Color:=0;
    Map.Canvas.Pen.Style:=psSolid;  //Must be drawn after Map.Refresh because cells over-draws lines :(
    Map.Canvas.MoveTo(Rect.Left,Rect.Top);
    if (MObj[o].Bset) then begin
      Map.Canvas.LineTo(round((MObj[o].x and $3fffff + MObj[o].y and $ffffffffffc00000 div 64)/5957.8181818),round((MObj[o].y and $3fffff)/5957.8181818));
      Map.Canvas.MoveTo(Rect.Right,Rect.Top);
      Map.Canvas.LineTo(round((MObj[o].x and $3fffff + MObj[o].y and $ffffffffffc00000 div 64)/5957.8181818),round((MObj[o].y and $3fffff)/5957.8181818));
      Map.Canvas.MoveTo(Rect.Left,Rect.Bottom);
      Map.Canvas.LineTo(round((MObj[o].x and $3fffff + MObj[o].y and $ffffffffffc00000 div 64)/5957.8181818),round((MObj[o].y and $3fffff)/5957.8181818));
      Map.Canvas.MoveTo(Rect.Right,Rect.Bottom);
      Map.Canvas.LineTo(round((MObj[o].x and $3fffff + MObj[o].y and $ffffffffffc00000 div 64)/5957.8181818),round((MObj[o].y and $3fffff)/5957.8181818));
    end else begin
      Map.Canvas.LineTo(Rect.Right,Rect.Bottom);
      Map.Canvas.MoveTo(Rect.Left,Rect.Bottom);
      Map.Canvas.LineTo(Rect.Right,Rect.Top);
    end;
  end;

  Map.Canvas.Pen.Color:=clBlue;
  Map.Canvas.Pen.Style:=psSolid;
  case unchangeables [1, ACol, ARow] of
    0:;
    90: begin
      Map.Canvas.MoveTo(Rect.Left,(Rect.Bottom+Rect.Top) div 2);
      Map.Canvas.LineTo(Rect.Right,(Rect.Bottom+Rect.Top) div 2);
      Map.Canvas.LineTo(Rect.Right-4,(Rect.Bottom+Rect.Top) div 2+2);
    end;
    91: begin
      Map.Canvas.MoveTo(Rect.Left,Rect.Bottom);
      Map.Canvas.LineTo(Rect.Right,Rect.Top);
      Map.Canvas.LineTo(Rect.Right-2,Rect.Top+4);
    end;
    92: begin
      Map.Canvas.MoveTo((Rect.Left+Rect.Right) div 2,Rect.Bottom);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2,Rect.Top);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2+2,Rect.Top+4);
    end;
    93: begin
      Map.Canvas.MoveTo(Rect.Right,Rect.Bottom);
      Map.Canvas.LineTo(Rect.Left,Rect.Top);
      Map.Canvas.LineTo(Rect.Left+4,Rect.Top+2);
    end;
    94: begin
      Map.Canvas.MoveTo(Rect.Right,(Rect.Bottom+Rect.Top) div 2);
      Map.Canvas.LineTo(Rect.Left,(Rect.Bottom+Rect.Top) div 2);
      Map.Canvas.LineTo(Rect.Left+4,(Rect.Bottom+Rect.Top) div 2-2);
    end;
    95: begin
      Map.Canvas.MoveTo(Rect.Right,Rect.Top);
      Map.Canvas.LineTo(Rect.Left,Rect.Bottom);
      Map.Canvas.LineTo(Rect.Left+2,Rect.Bottom-4);
    end;
    96: begin
      Map.Canvas.MoveTo((Rect.Left+Rect.Right) div 2,Rect.Top);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2,Rect.Bottom);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2-2,Rect.Bottom-4);
    end;
    97: begin
      Map.Canvas.MoveTo(Rect.Left,Rect.Top);
      Map.Canvas.LineTo(Rect.Right,Rect.Bottom);
      Map.Canvas.LineTo(Rect.Right-4,Rect.Bottom-2);
    end;
    98: begin
      Map.Canvas.Pen.Color:=$000000FF;
      Map.Canvas.MoveTo(Rect.Left,Rect.Top+1);
      Map.Canvas.LineTo(Rect.Right,Rect.Top+1);
      Map.Canvas.MoveTo(Rect.Left,Rect.Bottom-1);
      Map.Canvas.LineTo(Rect.Right,Rect.Bottom-1);
    end;
    99: begin
      Map.Canvas.MoveTo(Rect.Left,Rect.Top);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2,Rect.Bottom);
      Map.Canvas.LineTo(Rect.Right,Rect.Top);
    end;
{    else begin
      Map.Canvas.MoveTo(Rect.Left+1,Rect.Top+4);
      Map.Canvas.LineTo(Rect.Left+1,Rect.Top+1);
      Map.Canvas.LineTo(Rect.Right-1,Rect.Top+1);
      Map.Canvas.LineTo(Rect.Right-1,Rect.Top+4);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2,Rect.Bottom-3);
      Map.Canvas.MoveTo((Rect.Left+Rect.Right) div 2-1,Rect.Bottom-1);
      Map.Canvas.LineTo((Rect.Left+Rect.Right) div 2+1,Rect.Bottom-1);
    end;}
  end;
end;

procedure TForm1.SaveClick(Sender: TObject);
var F: file of byte;
    i: word;
begin
  if S.Execute then begin
    for i:=0 to 13169+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8 do rawdata[i]:=0;
    for i:=0 to 31 do if i<length(Name.Text) then rawdata[i]:=ord (Name.Text[i+1]) else rawdata[i]:=0;
    rawdata[32]:=Skill.Value; rawdata[33]:=Skill.Value shr 8;
    rawdata[34]:=(Level.Value-1); rawdata[35]:=(Level.Value-1)shr 8;
    rawdata[36]:=OldSc.Value; rawdata[37]:=OldSc.Value shr 8; rawdata[38]:=OldSc.Value shr 16; rawdata[39]:=OldSc.Value shr 24;
    rawdata[40]:=CurSc.Value; rawdata[41]:=CurSc.Value shr 8; rawdata[42]:=CurSc.Value shr 16; rawdata[43]:=CurSc.Value shr 24;
    rawdata[44]:=BonSc.Value; rawdata[45]:=BonSc.Value shr 8; rawdata[46]:=BonSc.Value shr 16; rawdata[47]:=BonSc.Value shr 24;
    rawdata[48]:=Lives.Value; rawdata[49]:=Lives.Value shr 8;
    rawdata[50]:=Health.Value; rawdata[51]:=Health.Value shr 8;
    rawdata[52]:=Ammo.Value; rawdata[53]:=Ammo.Value shr 8;
    rawdata[54]:=0;rawdata[55]:=0;
    for i:=0 to 7  do if Keys.Cells[i div 2,i mod 2]<>'' then rawdata[54]:=rawdata[54] or (1 shl i);
    for i:=8 to 15 do if Keys.Cells[i div 2,i mod 2]<>'' then rawdata[55]:=rawdata[55] or (1 shl (i-8));
    rawdata[56]:=WBest.Value;rawdata[57]:=WBest.Value shr 8;
    rawdata[58]:=WCurr.Value;rawdata[59]:=WCurr.Value shr 8;
    rawdata[60]:=WSel.Value; rawdata[61]:=WSel.Value  shr 8;
    rawdata[62]:=Face.Value; rawdata[63]:=Face.Value shr 8;
    rawdata[64]:=TechAF.Value; rawdata[65]:=TechAF.Value shr 8;
    rawdata[66]:=TechAC.Value; rawdata[67]:=TechAC.Value shr 8;
    rawdata[68]:=TechWF.Value; rawdata[69]:=TechWF.Value shr 8;
    rawdata[70]:=Epis.Value; rawdata[71]:=Epis.Value shr 8;
    rawdata[72]:=RCS.Value; rawdata[73]:=RCS.Value shr 8;
    rawdata[74]:=RCT.Value; rawdata[75]:=RCT.Value shr 8;
    rawdata[76]:=RCK.Value; rawdata[77]:=RCK.Value shr 8;
    rawdata[78]:=RTS.Value; rawdata[79]:=RTS.Value shr 8;
    rawdata[80]:=RTT.Value; rawdata[81]:=RTT.Value shr 8;
    rawdata[82]:=RTK.Value; rawdata[83]:=RTK.Value shr 8;
    rawdata[84]:=TimeCount.Value;rawdata[85]:=TimeCount.Value shr 8;rawdata[86]:=TimeCount.Value shr 16;rawdata[87]:=TimeCount.Value shr 24;
    rawdata[88]:=DCamX.Value;rawdata[89]:=DCamX.Value shr 8;rawdata[90]:=DCamX.Value shr 16;rawdata[91]:=DCamX.Value shr 24;
    rawdata[92]:=DCamY.Value;rawdata[93]:=DCamY.Value shr 8;rawdata[94]:=DCamY.Value shr 16;rawdata[95]:=DCamY.Value shr 24;
    rawdata[96]:=DCamF.Value;rawdata[97]:=DCamF.Value shr 8;
    if FormatCLevels.Value>0 then for i:=0 to FormatCLevels.Value-1 do begin
      rawdata[98 +i*10]:=oldKSTTi[0,i];rawdata[99 +i*10]:=oldKSTTi[0,i] div 256;
      rawdata[100+i*10]:=oldKSTTi[1,i];rawdata[101+i*10]:=oldKSTTi[1,i] div 256;
      rawdata[102+i*10]:=oldKSTTi[2,i];rawdata[103+i*10]:=oldKSTTi[2,i] div 256;
      rawdata[104+i*10]:=oldKSTTi[3,i];rawdata[105+i*10]:=oldKSTTi[3,i] div 256; rawdata[106+i*10]:=oldKSTTi[3,i] div 65536; rawdata[107+i*10]:=oldKSTTi[3,i] div 16777216;
    end;
    for i:=0 to 4095 do begin
      rawdata[98+FormatCLevels.Value*10+i]:=strtoint(Map.Cells[i div 64,i mod 64]);
      rawdata[4194+FormatCLevels.Value*10+i*2]:=strtoint(Map.Cells[i div 64,i mod 64]) div 256;
      rawdata[4195+FormatCLevels.Value*10+i*2]:=strtoint(Map.Cells[i div 64,i mod 64]) div 65536;
    end;
    for i:=0 to FormatNFloors.Value*FormatNFloors.Value-1 do rawdata[12386+FormatCLevels.Value*10+i]:=SndLnks[i div FormatNFloors.Value][i mod FormatNFloors.Value];
    for i:=0 to FormatNFloors.Value-1 do begin
      rawdata[12386+FormatNFloors.Value*FormatNFloors.Value+FormatCLevels.Value*10+i*2]:=SndZone[i];
      rawdata[12386+FormatNFloors.Value*FormatNFloors.Value+FormatCLevels.Value*10+i*2+1]:=SndZone[i] div 256;
    end;
    for i:= 0 to NumOfMobj-1 do begin
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60]:=MObj[i].active and $FF; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+1]:=MObj[i].active shr 8;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+2]:=MObj[i].ticcount; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+3]:=MObj[i].ticcount div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+4]:=MObj[i].obclass; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+5]:=MObj[i].obclass div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+6]:=MObj[i].statetype; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+7]:=MObj[i].statetype div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+8]:=MObj[i].flags; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+9]:=MObj[i].flags div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+10]:=MObj[i].distance and $FF; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+11]:=(MObj[i].distance shr 8) and $FF; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+12]:= (MObj[i].distance shr 16) and $FF; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+13]:=MObj[i].distance shr 24;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+14]:=MObj[i].dir; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+15]:=MObj[i].dir div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+16]:=MObj[i].x; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+17]:=MObj[i].x shr 8; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+18]:=MObj[i].x shr 16; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+19]:=MObj[i].x shr 24;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+20]:=MObj[i].y; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+21]:=MObj[i].y shr 8; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+22]:=MObj[i].y shr 16; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+23]:=MObj[i].y shr 24;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+24]:=MObj[i].tilex; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+25]:=MObj[i].tilex div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+26]:=MObj[i].tiley; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+27]:=MObj[i].tiley div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+28]:=MObj[i].areanum; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+29]:=MObj[i].areanum div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+30]:=MObj[i].viewx; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+31]:=MObj[i].viewx div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+32]:=MObj[i].viewheight; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+33]:=MObj[i].viewheight div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+34]:=MObj[i].transx; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+35]:= MObj[i].transx shr 8; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+36]:=MObj[i].transx shr 16; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+37]:= MObj[i].transx shr 24;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+38]:=MObj[i].transy; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+39]:= MObj[i].transy shr 8; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+40]:=MObj[i].transy shr 16; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+41]:= MObj[i].transy shr 24;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+42]:=MObj[i].angle; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+43]:=MObj[i].angle div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+44]:=MObj[i].hitpoints; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+45]:=MObj[i].hitpoints div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+46]:=MObj[i].speed; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+47]:=MObj[i].speed shr 8; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+48]:=MObj[i].speed shr 16; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+49]:=MObj[i].speed shr 24;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+50]:=MObj[i].temp1; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+51]:=MObj[i].temp1 div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+52]:=MObj[i].temp2; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+53]:=MObj[i].temp2 div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+54]:=MObj[i].temp3; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+55]:=MObj[i].temp3 div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+56]:=MObj[i].next; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+57]:=MObj[i].next div 256;
      rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+58]:=MObj[i].prev; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+i*60+59]:=MObj[i].prev div 256;
    end; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+NumOfMObj*60]:=$FF; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+NumOfMObj*60+1]:=$FF;
    rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60]:=NextFreeSObjPtr.Value; rawdata[12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+1]:=NextFreeSObjPtr.Value div 256;
    for i:= 0 to FormatNThings.Value-1 do begin
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8]:=SObj[i].x;
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+1]:=SObj[i].y;
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+2]:=SObj[i].visspot; rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+3]:=SObj[i].visspot div 256;
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+4]:=SObj[i].shapenum and $FF; rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+5]:=SObj[i].shapenum shr 8;
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+6]:=SObj[i].flags;
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+i*8+7]:=SObj[i].itemnum;
    end;
    for i:= 0 to 63 do begin
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*2]:=DoorPos[i];
      rawdata[12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*2+1]:=DoorPos[i] div 256;
    end;
    for i:= 0 to 63 do begin
      rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10]:=DoorStat[i].x;
      rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+1]:=DoorStat[i].y;
      rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+2]:=DoorStat[i].vertflag; rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+3]:=DoorStat[i].vertflag div 256;
      rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+4]:=DoorStat[i].lock; rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+5]:=DoorStat[i].lock div 256;
      rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+6]:=DoorStat[i].motion; rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+7]:=DoorStat[i].motion div 256;
      rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+8]:=DoorStat[i].ticcount; rawdata[12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+i*10+9]:=DoorStat[i].ticcount div 256;
    end;
    rawdata[13156+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=PWOdo.Value;rawdata[13156+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]:=PWOdo.Value div 256;
    rawdata[13158+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=PWX.Value  ;rawdata[13158+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]:=PWX.Value   div 256;
    rawdata[13160+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=PWY.Value  ;rawdata[13160+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]:=PWY.Value   div 256;
    rawdata[13162+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=PWDir.Value;rawdata[13162+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]:=PWDir.Value div 256;
    rawdata[13164+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=PWPos.Value;rawdata[13164+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8+1]:=PWPos.Value div 256;

    csum:=0;
    for i:=32                          to 96                           do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    for i:=98                          to 96   +FormatCLevels.Value*10 do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    for i:=98  +FormatCLevels.Value*10 to 4192 +FormatCLevels.Value*10 do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    for i:=4194+FormatCLevels.Value*10 to 12384+FormatCLevels.Value*10 do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    i:=12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60; csum:=csum + (rawdata[i] xor rawdata[i+1]);
    for i:=12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60
        to 12386+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8 do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    for i:=12388+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8
        to 12514+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8 do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    for i:=12516+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8
        to 13154+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8 do csum:=csum + (rawdata[i] xor rawdata[i+1]);
    i:=13156+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8; csum:=csum + (rawdata[i] xor rawdata[i+1]);
    i:=13158+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8; csum:=csum + (rawdata[i] xor rawdata[i+1]);
    i:=13160+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8; csum:=csum + (rawdata[i] xor rawdata[i+1]);
    i:=13162+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8; csum:=csum + (rawdata[i] xor rawdata[i+1]);
    i:=13164+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8; csum:=csum + (rawdata[i] xor rawdata[i+1]);
    rawdata[13166+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=csum;rawdata[13167+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=csum div 256; rawdata[13168+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=csum div 65536; rawdata[13169+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8]:=csum div 16777216;

    assignfile (F,S.FileName);
    rewrite (F);
    for i:= 0 to 13169+FormatNFloors.Value*(FormatNFloors.Value+2)+FormatCLevels.Value*10+(NumOfMobj+1)*60+FormatNThings.Value*8 do write (f,rawdata[i]);
    closefile (F);
  end;
end;

procedure TForm1.MapMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var C,R,N: integer;
begin
  if Button=mbRight then begin
    Map.MouseToCell(X,Y,C,R);
    DrawNum.Value:=strtoint(Map.Cells[C,R]) mod 256;
    DrawOO.Value:=strtoint(Map.Cells[C,R]) div 256;
  end;
  if (Button=mbMiddle) AND FlagsForThings.Visible then begin
    ThingInDrag.Value:=0;
    Map.MouseToCell(X,Y,C,R);
    N:=                    ThingsAmount.Value;
    SObj[ThingsAmount.Value].x:=C;
    SObj[ThingsAmount.Value].y:=R;
    SObj[ThingsAmount.Value].visspot:=Vsp0Ptr.Value+SObj[ThingsAmount.Value].x*64+SObj[ThingsAmount.Value].y;
    SObj[ThingsAmount.Value].shapenum:=ThingShapeNum.Value;
    SObj[ThingsAmount.Value].flags:=ThingFlags.Value;
    SObj[ThingsAmount.Value].itemnum:=ThingItemNum.Value;
    NextFreeSObjPtr.Value:=NextFreeSObjPtr.Value+8;
    Form1.ThingNum.Value:=N;
  end;
  if (Button=mbMiddle) AND FlagsForObj.Visible then begin
    ObjInDrag.Value:=0;
    Map.MouseToCell(X,Y,C,R);
    N:=ObjAmount.Value;
    MObj[ObjAmount.Value].active:=ObjActive.Value;
    MObj[ObjAmount.Value].ticcount:=ObjTicks.Value;
    MObj[ObjAmount.Value].obclass:=ObjClass.Value;
    MObj[ObjAmount.Value].statetype:=ObjFramePtr.Value;
    MObj[ObjAmount.Value].flags:=ObjFlags.Value;
    MObj[ObjAmount.Value].distance:=0;      //If centered, AFAIK, must be 0.
    MObj[ObjAmount.Value].dir:=ObjDir.Value;
    MObj[ObjAmount.Value].x:=C*65536+32768;
    MObj[ObjAmount.Value].y:=R*65536+32768;
    MObj[ObjAmount.Value].tilex:=C;
    MObj[ObjAmount.Value].tiley:=R;
    if unchangeables[0,C,R]>0 then MObj[ObjAmount.Value].areanum:=unchangeables[0,C,R]-SoundArea0.Value
    else MObj[ObjAmount.Value].areanum:=ObjFloor.Value;
    MObj[ObjAmount.Value].viewx:=0;         //IDK what to put
    MObj[ObjAmount.Value].viewheight:=0;    //IDK what to put
    MObj[ObjAmount.Value].transx:=0;        //IDK what to put
    MObj[ObjAmount.Value].transy:=0;        //IDK what to put
    MObj[ObjAmount.Value].angle:=ObjAngle.Value;
    MObj[ObjAmount.Value].hitpoints:=ObjHealth.Value;
    MObj[ObjAmount.Value].speed:=ObjSpeed.Value;
    Map.Cells[C,R]:=inttostr((strtoint(Map.Cells[C,R]) mod 256) or (Obj0Ptr.Value+ObjAmount.Value*60)*256);
    ObjAmount.Value:=ObjAmount.Value+1; //ObjAmountChange will set new end-object-list marker;
    Form1.ObjNum.Value:=N;
  end;
end;

procedure ShowTile (Tile: integer; IsSprite: boolean);
  var f: file of byte;
  cl,SY,EY: byte;
  img: array[0..63,0..63] of byte;
  chunk: array[0..10000] of byte;
  size,SHP,DP: word;
  N:String;
  SpOff: dword;
  i,x,y:word;

begin
    N:='VSWAP'+RightStr(Form1.L.FileName,4);
    assignfile (F,N);
 {$I-}
    reset (F);
    if IOResult<>0 then begin Form1.Caption:='SaveGam?.* Editor: VSWAP.??? not found'; exit end;
 {$I+}
    if IsSprite then begin
      read (f,cl);size:=cl;
      read (f,cl);size:=size+cl*256;  //size == total size (number of chunks);
      read (f,cl);i:=cl;
      read (f,cl);i:=i+cl*256;  //i == number of wall tiles;
      seek (F,(Tile+i)*4+6);
      read (f,cl);SpOff:=cl;
      read (f,cl);SpOff:=SpOff+cl*256;
      read (f,cl);SpOff:=SpOff+cl*65536;
      read (f,cl);SpOff:=SpOff+cl*16777216; //SpOff == sprite offset;
      seek (F,(Tile+i)*2+size*4+6);
      read (f,cl);size:=cl;
      read (f,cl);size:=size+cl*256;  //size == chunk size;
      if size<1 then begin closefile (f); exit end;
      seek (F,SpOff);
      for i:= 0 to size-1 do read (F,chunk[i]);
      for x:=0 to 63 do
       for y:=0 to  63 do
        img[y][x]:=255;

      DP:=4; //Back-calculating Data start Position;
      SHP:=chunk[4]+256*chunk[5]; // String Header Position;
      while SHP<size do begin
        if (chunk[SHP] or chunk[SHP+1])=0 then begin
          SHP:=SHP+2;
          DP:=DP+2;
        end else SHP:=SHP+6;
      end;
      SHP:=chunk[4]+256*chunk[5];
       x:=0;
      while SHP<size do begin
        if (chunk[SHP] or chunk[SHP+1])=0 then begin
          SHP:=SHP+2;
          x:=x+1;
        end else begin
          EY:=chunk[SHP] div 2;SY:=chunk[SHP+4] div 2;  //Start and End Y;
          for y:=SY to EY-1 do begin
            img[y][x]:=chunk[DP];
            DP:=DP+1;
          end;
          SHP:=SHP+6;
        end;
      end;
      size:=x;

      for x:=0 to size-1 do begin
       for y:=0 to  63 do begin
        Form1.Map.Canvas.Pixels[x*2  ,y*2  ]:=WOLFPAL[img [y,x]];
        Form1.Map.Canvas.Pixels[x*2+1,y*2  ]:=WOLFPAL[img [y,x]];
        Form1.Map.Canvas.Pixels[x*2  ,y*2+1]:=WOLFPAL[img [y,x]];
        Form1.Map.Canvas.Pixels[x*2+1,y*2+1]:=WOLFPAL[img [y,x]];
       end;
      end;

    end else begin
      read (f,cl);size:=cl;
      read (f,cl);size:=size+cl*256;  //size == total size (number of chunks);
      seek (F,Tile*8-2);              //Reading only 1st of a pair, Tile1=Pos0
      read (f,cl);SpOff:=cl;
      read (f,cl);SpOff:=SpOff+cl*256;
      read (f,cl);SpOff:=SpOff+cl*65536;
      read (f,cl);SpOff:=SpOff+cl*16777216; //SpOff == wall offset;
      seek (F,Tile*4+size*4+2);
      read (f,cl);size:=cl;
      read (f,cl);size:=size+cl*256;  //size == wall size (4k or sparse);
      if size<1 then begin closefile (f); exit end;
      seek (F,SpOff);
      for x:=0 to 127 do begin
       for y:=0 to  63 do begin
        read (f,cl);
        Form1.Map.Canvas.Pixels[x*2  ,y*2  ]:=WOLFPAL[cl];
        Form1.Map.Canvas.Pixels[x*2+1,y*2  ]:=WOLFPAL[cl];
        Form1.Map.Canvas.Pixels[x*2  ,y*2+1]:=WOLFPAL[cl];
        Form1.Map.Canvas.Pixels[x*2+1,y*2+1]:=WOLFPAL[cl];
       end;
      end;
    end;
    closefile (f);
    Form1.Map.Tag:=1;
end;

procedure TForm1.DrawNumChange(Sender: TObject);
begin
  if ((DrawNum.Value mod 64)>0) and ((DrawNum.Value<128) or (DrawNum.Value>192)) and (DrawNum.Value<256) then ShowTile(DrawNum.Value mod 64, FALSE);

  if (DrawNum.Value>63) and (DrawNum.Value<128) then SetDTrack.Caption:='...is a doortrack #'+inttostr(DrawNum.Value mod 64 ) else SetDTrack.Caption:='...doortrack?';
  if  DrawNum.Value>127                         then SetDoor.Caption  :='...is a door #'     +inttostr(DrawNum.Value mod 128) else SetDoor.Caption  :='...door?'     ;
  if  DrawNum.Value>191                         then SetDoor.Caption  :='...is a scrt door #'+inttostr(DrawNum.Value mod 64 );

  if (DrawNum.Value>127) and (DrawNum.Value<192) then DrawOO.Value:=DrawNum.Value else DrawOO.Value:=DrawNum.Value mod 64;
end;

procedure TForm1.DrawOOChange(Sender: TObject);
begin
  if ((DrawOO.Value  mod 64)>0) and (DrawOO.Value <128) then ShowTile(DrawOO.Value  mod 64, FALSE);
end;

procedure TForm1.MapMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if Map.Tag=1 then begin Map.Refresh; Map.Tag:=0; end;
  if ThingInDrag.Value=1 then begin ThingX.Value:=X div 11;ThingY.Value:=Y div 11;ThingVisspot.Value:=Vsp0Ptr.Value+ThingX.Value*64+ThingY.Value end;
  if ObjInDrag.Value=1 then begin ObjX.Value:=round(X*5957.8181818-30000);ObjY.Value:=round(Y*5957.8181818-30000); ObjTX.Value:=ObjX.Value div 65536; ObjTY.Value:=ObjY.Value div 65536 end;
  if DoorInDrag.Value=1 then begin DoorX.Value:=X div 11;DoorY.Value:=Y div 11; end;
end;

procedure TForm1.SetDTrackClick(Sender: TObject);
begin
  if (DrawNum.Value>63) and (DrawNum.Value<128) then DrawNum.Value:=DrawNum.Value mod 64 else DrawNum.Value:=DrawNum.Value mod 64+64;
end;

procedure TForm1.SetDoorClick(Sender: TObject);
begin
  if DrawNum.Value>191 then DrawNum.Value:=DrawNum.Value mod 64 else
   if DrawNum.Value>127 then DrawNum.Value:=DrawNum.Value mod 64 + 192 else
    begin DrawNum.Value:=DrawNum.Value mod 64+128{; DrawOO.Value:=DrawNum.Value }end;
end;

procedure TForm1.T0PtrChange(Sender: TObject);
begin
  ThingsAmount.Value:=(NextFreeSObjPtr.Value - T0Ptr.Value) div 8;
  if ThingsAmount.Value<0                   then begin T0Ptr.Color:=clRed; NextFreeSObjPtr.Color:=clRed; ThingsAmount.Value:=0; end;
  if ThingsAmount.Value>FormatNThings.Value then begin T0Ptr.Color:=clRed; NextFreeSObjPtr.Color:=clRed; ThingsAmount.Value:=FormatNThings.Value; end;
  if (NextFreeSObjPtr.Value - T0Ptr.Value) mod 8 = 0 then begin T0Ptr.Color:=clWindow; NextFreeSObjPtr.Color:=clWindow; end else begin T0Ptr.Color:=clRed; NextFreeSObjPtr.Color:=clRed; end;
end;

procedure TForm1.NextFreeSObjPtrChange(Sender: TObject);
begin
  ThingsAmount.Value:=(NextFreeSObjPtr.Value - T0Ptr.Value) div 8;;
  if ThingsAmount.Value<0                   then begin T0Ptr.Color:=clRed; NextFreeSObjPtr.Color:=clRed; ThingsAmount.Value:=0; end;
  if ThingsAmount.Value>FormatNThings.Value then begin T0Ptr.Color:=clRed; NextFreeSObjPtr.Color:=clRed; ThingsAmount.Value:=FormatNThings.Value; end;
  if (NextFreeSObjPtr.Value - T0Ptr.Value) mod 8 = 0 then begin T0Ptr.Color:=clWindow; NextFreeSObjPtr.Color:=clWindow; end else begin T0Ptr.Color:=clRed; NextFreeSObjPtr.Color:=clRed; end;
end;

procedure TForm1.ThingsAmountChange(Sender: TObject);
var i:word;
begin
  if ThingsAmount.Value>0 then for i:=0 to ThingsAmount.Value-1 do begin
    if not SObj[i].Bset then begin
      SObj[i].B:=TPanel.Create(Form1);
      SObj[i].Bset:=TRUE;
      with SObj[i].B do begin
        Color:=((SObj[i].shapenum) mod 8)*36 + ((SObj[i].shapenum) div 8 mod 8)*36*256 + ((SObj[i].shapenum) div 64)*36*65536;
        Parent:=Form1.Map; //was Form, but it causes misplacing of the Things when Form window is bigger than the screen resolution and needs to be scrolled
        Width:=6;
        Height:=6;
        Left:=(SObj[i].x mod 64)*11+2;
        Top:=(SObj[i].y mod 64)*11+2;
        Tag:=i;
        onClick:=WlThingClick;
        onMouseDown:=WlThingPress;
      end;
    end;
  end;
  if ThingsAmount.Value<FormatNThings.Value then for i:=ThingsAmount.Value to FormatNThings.Value-1 do if SObj[i].Bset then begin
    SObj[i].B.Free;
    SObj[i].Bset:=FALSE;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: word;
begin
  for i:=0 to 1023 do SObj[i].Bset:=FALSE;
  for i:=0 to 511 do MObj[i].Bset:=FALSE;
  PrevFloorForRepaint:=-1000;
  for i:=0 to 63 do begin
    doorstat[i].B:=TImage.Create(Form1);
    with doorstat[i].B do begin
      Parent:=Form1.Map;
      Width:=Form1.Image1.Width;
      Height:=Form1.Image1.Height;
      Picture:=Form1.Image1.Picture;
      Left:=0;
      Top:=0;
      Tag:=i;
      onClick:=WlDoorClick;
//      onMouseDown:=WlDoorPress;
    end;
  end;
end;

procedure TForm1.ThingNumChange(Sender: TObject);
begin
  FlagsForThings.Visible:=TRUE;
  FlagsForThings2.Visible:=TRUE;
  FlagsForObj.Visible:=FALSE;
  FlagsForObj2.Visible:=FALSE;
  ThingFlags.Value:=SObj[ThingNum.Value].flags;
  if (ThingFlags.Value and  1 ) > 0 then ThShootable.Checked  :=TRUE else ThShootable.Checked  :=FALSE;
  if (ThingFlags.Value and  2 ) > 0 then ThBonus.Checked      :=TRUE else ThBonus.Checked      :=FALSE;
  if (ThingFlags.Value and  4 ) > 0 then ThNevermark.Checked  :=TRUE else ThNevermark.Checked  :=FALSE;
  if (ThingFlags.Value and  8 ) > 0 then ThVisable.Checked    :=TRUE else ThVisable.Checked    :=FALSE;
  if (ThingFlags.Value and 16 ) > 0 then ThAttackMode.Checked :=TRUE else ThAttackMode.Checked :=FALSE;
  if (ThingFlags.Value and 32 ) > 0 then ThFirstAttack.Checked:=TRUE else ThFirstAttack.Checked:=FALSE;
  if (ThingFlags.Value and 64 ) > 0 then ThAmbush.Checked     :=TRUE else ThAmbush.Checked     :=FALSE;
  if (ThingFlags.Value and 128) > 0 then ThNonmark.Checked    :=TRUE else ThNonmark.Checked    :=FALSE;
  ThingX.Value:=SObj[ThingNum.Value].x;
  ThingY.Value:=SObj[ThingNum.Value].y;
  ThingVisspot.Value:=SObj[ThingNum.Value].visspot;
  ThingShapeNum.Value:=SObj[ThingNum.Value].shapenum;
  ThingItemNum.Value:=SObj[ThingNum.Value].itemnum;
  if SObj[ThingNeedsRepaint].Bset then begin
    SObj[ThingNeedsRepaint].B.Color:=((SObj[ThingNeedsRepaint].shapenum) mod 8)*36 + ((SObj[ThingNeedsRepaint].shapenum) div 8 mod 8)*36*256 + ((SObj[ThingNeedsRepaint].shapenum) div 64)*36*65536;
  end;
  if SObj[ThingNum.Value].Bset then begin
    SObj[ThingNum.Value].B.Color:=$FFFFFF;
  end;
  ThingNeedsRepaint:=ThingNum.Value;
end;

procedure TForm1.WLThingClick(Sender:TObject);
begin
  with (Sender as TPanel) do begin
    if Form1.ThingNum.Value=Tag then Form1.ThingInDrag.Value:=1-Form1.ThingInDrag.Value else Form1.ThingInDrag.Value:=0;
    Form1.ThingNum.Value:=Tag;
  end;
end;

procedure TForm1.WLDoorClick(Sender:TObject);
begin
  with (Sender as TImage) do begin
    if Form1.DoorNum.Value=Tag then Form1.DoorInDrag.Value:=1-Form1.DoorInDrag.Value else Form1.DoorInDrag.Value:=0;
    Form1.DoorNum.Value:=Tag;
  end;
end;

procedure TForm1.WLThingPress(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
var kill,i: word;
begin
  if Button=mbMiddle then with (Sender as TPanel) do begin
    ThingInDrag.Value:=0;
    kill:=Tag;
    if SObj[kill].Bset then SObj[kill].B.Free;
    for i:=kill to FormatNThings.Value-2 do begin
      SObj[i].x:=SObj[i+1].x;
      SObj[i].y:=SObj[i+1].y;
      SObj[i].visspot:=SObj[i+1].visspot;
      SObj[i].shapenum:=SObj[i+1].shapenum;
      SObj[i].flags:=SObj[i+1].flags;
      SObj[i].itemnum:=SObj[i+1].itemnum;
      SObj[i].Bset:=SObj[i+1].Bset;
      SObj[i].B:=SObj[i+1].B;
      if SObj[i].Bset then SObj[i].B.Tag:=i;
    end;
    NextFreeSObjPtr.Value:=NextFreeSObjPtr.Value-8;
    if ThingNum.Value=0 then begin  //Force-refresh;
      ThingNum.Value:=1;ThingNum.Value:=0;
    end else begin
      ThingNum.Value:=ThingNum.Value-1;
      if ThingNum.Value<ThingsAmount.Value-1 then ThingNum.Value:=ThingNum.Value+1;
    end;
  end;
end;

procedure TForm1.ThingXChange(Sender: TObject);
begin
  SObj[ThingNum.Value].x:=ThingX.Value;
  if SObj[ThingNum.Value].Bset then SObj[ThingNum.Value].B.Left:=(ThingX.Value mod 64 + ThingY.Value div 64)*11+2;
end;

procedure TForm1.ThingYChange(Sender: TObject);
begin
  SObj[ThingNum.Value].y:=ThingY.Value;
  if SObj[ThingNum.Value].Bset then SObj[ThingNum.Value].B.Top:=(ThingY.Value mod 64)*11+2;
  if SObj[ThingNum.Value].Bset then SObj[ThingNum.Value].B.Left:=(ThingX.Value mod 64 + ThingY.Value div 64)*11+2;
end;

procedure TForm1.ThingVisspotChange(Sender: TObject);
begin
  SObj[ThingNum.Value].visspot:=ThingVisspot.Value;
end;

procedure TForm1.ThingShapeNumChange(Sender: TObject);
begin
  SObj[ThingNum.Value].shapenum:=ThingShapeNum.Value;
  if (ThingShapeNum.Value>=0) and (ThingShapeNum.Value<1000) then   ShowTile  (ThingShapeNum.Value,TRUE);
end;

procedure TForm1.ThingFlagsChange(Sender: TObject);
begin
  FlagsForThings.Visible:=TRUE;
  FlagsForThings2.Visible:=TRUE;
  FlagsForObj.Visible:=FALSE;
  FlagsForObj2.Visible:=FALSE;
  if (ThingFlags.Value and  1 ) > 0 then ThShootable.Checked  :=TRUE else ThShootable.Checked  :=FALSE;
  if (ThingFlags.Value and  2 ) > 0 then ThBonus.Checked      :=TRUE else ThBonus.Checked      :=FALSE;
  if (ThingFlags.Value and  4 ) > 0 then ThNevermark.Checked  :=TRUE else ThNevermark.Checked  :=FALSE;
  if (ThingFlags.Value and  8 ) > 0 then ThVisable.Checked    :=TRUE else ThVisable.Checked    :=FALSE;
  if (ThingFlags.Value and 16 ) > 0 then ThAttackMode.Checked :=TRUE else ThAttackMode.Checked :=FALSE;
  if (ThingFlags.Value and 32 ) > 0 then ThFirstAttack.Checked:=TRUE else ThFirstAttack.Checked:=FALSE;
  if (ThingFlags.Value and 64 ) > 0 then ThAmbush.Checked     :=TRUE else ThAmbush.Checked     :=FALSE;
  if (ThingFlags.Value and 128) > 0 then ThNonmark.Checked    :=TRUE else ThNonmark.Checked    :=FALSE;
  SObj[ThingNum.Value].flags:=ThingFlags.Value;
end;

procedure TForm1.ThingItemNumChange(Sender: TObject);
begin
  SObj[ThingNum.Value].itemnum:=ThingItemNum.Value;
  case ThingItemNum.Value of
    2: ThingItemName.Caption:='Blood (+1 health)';
    3: ThingItemName.Caption:='Dog food (+4, bark bark!)';
    4: ThingItemName.Caption:='Medikit (+25)';
    5: ThingItemName.Caption:='Golden Key';
    6: ThingItemName.Caption:='Silver Key';
    7: ThingItemName.Caption:='3rd Secret Key';
    8: ThingItemName.Caption:='4th Secret Key';
    9: ThingItemName.Caption:='Cross';
    10: ThingItemName.Caption:='Chalice';
    11: ThingItemName.Caption:='Jewels';
    12: ThingItemName.Caption:='Crown';
    13: ThingItemName.Caption:='8x9mm para clip';
    14: ThingItemName.Caption:='4x9mm para clip';
    15: ThingItemName.Caption:='Machinenpistole';
    16: ThingItemName.Caption:='Meat-grinder gun';
    17: ThingItemName.Caption:='Meat with vegetables';
    18: ThingItemName.Caption:='Life';
    19: ThingItemName.Caption:='25x9mm para';
    20: ThingItemName.Caption:='Spear (go to final level)';
    else ThingItemName.Caption:='Nothing (just disappears)';
  end;
end;

procedure TForm1.VisspotAutoClick(Sender: TObject);
begin
  ThingVisspot.Value:=Vsp0Ptr.Value+ThingX.Value*64+ThingY.Value;
end;

procedure TForm1.ThingFlagCheck(Sender: TObject);
begin
  if FlagsForThings.Visible then with Sender as TCheckbox do if Checked then ThingFlags.Value:=ThingFlags.Value or Tag else ThingFlags.Value:=ThingFlags.Value and not Tag;
  if FlagsForObj.Visible    then with Sender as TCheckbox do if Checked then   ObjFlags.Value:=  ObjFlags.Value or Tag else   ObjFlags.Value:=  ObjFlags.Value and not Tag;
end;

procedure TForm1.ObjNumChange(Sender: TObject);
begin
  FlagsForThings.Visible:=FALSE;
  FlagsForThings2.Visible:=FALSE;
  FlagsForObj.Visible:=TRUE;
  FlagsForObj2.Visible:=TRUE;
  ObjFlags.Value:=MObj[ObjNum.Value].flags;
  if (ObjFlags.Value and  1 ) > 0 then ThShootable.Checked  :=TRUE else ThShootable.Checked  :=FALSE;
  if (ObjFlags.Value and  2 ) > 0 then ThBonus.Checked      :=TRUE else ThBonus.Checked      :=FALSE;
  if (ObjFlags.Value and  4 ) > 0 then ThNevermark.Checked  :=TRUE else ThNevermark.Checked  :=FALSE;
  if (ObjFlags.Value and  8 ) > 0 then ThVisable.Checked    :=TRUE else ThVisable.Checked    :=FALSE;
  if (ObjFlags.Value and 16 ) > 0 then ThAttackMode.Checked :=TRUE else ThAttackMode.Checked :=FALSE;
  if (ObjFlags.Value and 32 ) > 0 then ThFirstAttack.Checked:=TRUE else ThFirstAttack.Checked:=FALSE;
  if (ObjFlags.Value and 64 ) > 0 then ThAmbush.Checked     :=TRUE else ThAmbush.Checked     :=FALSE;
  if (ObjFlags.Value and 128) > 0 then ThNonmark.Checked    :=TRUE else ThNonmark.Checked    :=FALSE;
  ObjActive.Value:=MObj[ObjNum.Value].active;
  ObjTicks.Value:=MObj[ObjNum.Value].ticcount;
  ObjClass.Value:=MObj[ObjNum.Value].obclass;
  ObjFramePtr.Value:=MObj[ObjNum.Value].statetype;
  ObjDist.Value:=MObj[ObjNum.Value].distance;
  ObjDir.Value:=MObj[ObjNum.Value].dir;
  ObjFloor.Value:=MObj[ObjNum.Value].areanum;
  ObjTx.Value:=MObj[ObjNum.Value].tilex;
  ObjTy.Value:=MObj[ObjNum.Value].tiley;
  ObjX.Value:=MObj[ObjNum.Value].x;
  ObjY.Value:=MObj[ObjNum.Value].y;
  ObjViewX.Value:=MObj[ObjNum.Value].viewx;
  ObjViewH.Value:=MObj[ObjNum.Value].viewheight;
  ObjGx.Value:=MObj[ObjNum.Value].transx;
  ObjGy.Value:=MObj[ObjNum.Value].transy;
  ObjAngle.Value:=MObj[ObjNum.Value].angle;
  ObjHealth.Value:=MObj[ObjNum.Value].hitpoints;
  ObjSpeed.Value:=MObj[ObjNum.Value].speed;
  ObjT1.Value:=MObj[ObjNum.Value].temp1;
  ObjT2.Value:=MObj[ObjNum.Value].temp2;
  ObjT3.Value:=MObj[ObjNum.Value].temp3;
  ObjNext.Value:=MObj[ObjNum.Value].next;
  ObjPrev.Value:=MObj[ObjNum.Value].prev;
  if MObj[MObjNeedsRepaint].Bset then begin
    MObj[MObjNeedsRepaint].B.Brush.Color:=127*(MObj[MObjNeedsRepaint].obclass mod 3)*256+127*(MObj[MObjNeedsRepaint].obclass div 3 mod 3)+85*(MObj[MObjNeedsRepaint].obclass div 9)*65536;
  end;
  if MObj[ObjNum.Value].Bset then begin
    MObj[ObjNum.Value].B.Brush.Color:=$FFFFFF;
  end;
  MObjNeedsRepaint:=ObjNum.Value;
end;

procedure TForm1.ObjFlagsChange(Sender: TObject);
begin
  FlagsForThings.Visible:=FALSE;
  FlagsForThings2.Visible:=FALSE;
  FlagsForObj.Visible:=TRUE;
  FlagsForObj2.Visible:=TRUE;
  if (ObjFlags.Value and  1 ) > 0 then ThShootable.Checked  :=TRUE else ThShootable.Checked  :=FALSE;
  if (ObjFlags.Value and  2 ) > 0 then ThBonus.Checked      :=TRUE else ThBonus.Checked      :=FALSE;
  if (ObjFlags.Value and  4 ) > 0 then ThNevermark.Checked  :=TRUE else ThNevermark.Checked  :=FALSE;
  if (ObjFlags.Value and  8 ) > 0 then ThVisable.Checked    :=TRUE else ThVisable.Checked    :=FALSE;
  if (ObjFlags.Value and 16 ) > 0 then ThAttackMode.Checked :=TRUE else ThAttackMode.Checked :=FALSE;
  if (ObjFlags.Value and 32 ) > 0 then ThFirstAttack.Checked:=TRUE else ThFirstAttack.Checked:=FALSE;
  if (ObjFlags.Value and 64 ) > 0 then ThAmbush.Checked     :=TRUE else ThAmbush.Checked     :=FALSE;
  if (ObjFlags.Value and 128) > 0 then ThNonmark.Checked    :=TRUE else ThNonmark.Checked    :=FALSE;
  MObj[ObjNum.Value].flags:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjActiveChange(Sender: TObject);
var i: word;
begin
  MObj[ObjNum.Value].active:=(sender as tspinedit).Value;
  for i:=0 to 511 do if MObj[i].active=-1 then begin ObjAmount.Value:=i; break end;
end;

procedure TForm1.ObjTicksChange(Sender: TObject);
begin
  MObj[ObjNum.Value].ticcount:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjClassChange(Sender: TObject);
begin
  MObj[ObjNum.Value].obclass:=(sender as tspinedit).Value;
  case (sender as tspinedit).Value of
  0: ObClassLabel.Caption:='nothing';
  1: ObClassLabel.Caption:='playerobj';
  2: ObClassLabel.Caption:='inertobj';
  3: ObClassLabel.Caption:='guardobj';
  4: ObClassLabel.Caption:='officerobj';
  5: ObClassLabel.Caption:='ssobj';
  6: ObClassLabel.Caption:='dogobj';
  7: ObClassLabel.Caption:='bossobj';
  8: ObClassLabel.Caption:='schabbobj';
  9: ObClassLabel.Caption:='fakeobj';
  10: ObClassLabel.Caption:='mechahitlerobj';
  11: ObClassLabel.Caption:='mutantobj';
  12: ObClassLabel.Caption:='needleobj';
  13: ObClassLabel.Caption:='fireobj';
  14: ObClassLabel.Caption:='bjobj';
  15: ObClassLabel.Caption:='ghostobj';
  16: ObClassLabel.Caption:='realhitlerobj';
  17: ObClassLabel.Caption:='gretelobj';
  18: ObClassLabel.Caption:='giftobj';
  19: ObClassLabel.Caption:='fatobj';
  20: ObClassLabel.Caption:='rocketobj';
// S.O.D.
  21: ObClassLabel.Caption:='spectreobj';
  22: ObClassLabel.Caption:='angelobj';
  23: ObClassLabel.Caption:='transobj';
  24: ObClassLabel.Caption:='uberobj';
  25: ObClassLabel.Caption:='willobj';
  26: ObClassLabel.Caption:='deathobj';
  27: ObClassLabel.Caption:='hrocketobj';
  28: ObClassLabel.Caption:='sparkobj';

  else ObClassLabel.Caption:='?????';
  end;
end;

procedure TForm1.ObjFramePtrChange(Sender: TObject);
begin
  MObj[ObjNum.Value].statetype:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjDistChange(Sender: TObject);
begin
  MObj[ObjNum.Value].distance:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjDirChange(Sender: TObject);
begin
  MObj[ObjNum.Value].dir:=(sender as tspinedit).Value;
  DirLabel.Caption:='x';                                      //X
  if (sender as tspinedit).Value=0 then DirLabel.Caption:='и';//R
  if (sender as tspinedit).Value=1 then DirLabel.Caption:='м';//UR
  if (sender as tspinedit).Value=2 then DirLabel.Caption:='й';//U
  if (sender as tspinedit).Value=3 then DirLabel.Caption:='л';//UL
  if (sender as tspinedit).Value=4 then DirLabel.Caption:='з';//L
  if (sender as tspinedit).Value=5 then DirLabel.Caption:='н';//DL
  if (sender as tspinedit).Value=6 then DirLabel.Caption:='к';//D
  if (sender as tspinedit).Value=7 then DirLabel.Caption:='о';//DR
  if (sender as tspinedit).Value=8 then DirLabel.Caption:='Ў';//O
end;

procedure ShowFloor (Floor: integer);
var x,y:integer;
Rect: TRect;
begin
  Form1.Map.Canvas.Pen.Color:=clWhite;
  Form1.Map.Canvas.Pen.Style:=psSolid;
  for x:=0 to 63 do
   for y:=0 to 63 do
    if unchangeables[0,x,y]=Floor+Form1.SoundArea0.Value then begin
      Rect:=Form1.Map.CellRect(x,y);
      Form1.Map.Tag:=1;
      Form1.Map.Canvas.MoveTo(Rect.Left,Rect.Top);
      Form1.Map.Canvas.LineTo(Rect.Right,Rect.Top);
      Form1.Map.Canvas.LineTo(Rect.Right,Rect.Bottom);
      Form1.Map.Canvas.LineTo(Rect.Left,Rect.Bottom);
      Form1.Map.Canvas.LineTo(Rect.Left,Rect.Top);
    end;
  Form1.Map.Canvas.Pen.Color:=(3 - PrevFloorForRepaint mod 4)*85+(7 - PrevFloorForRepaint div 4 mod 8)*36*256+(7 - PrevFloorForRepaint div 32)*36*256*256;
  for x:=0 to 63 do
   for y:=0 to 63 do
    if unchangeables[0,x,y]=PrevFloorForRepaint then begin
      Rect:=Form1.Map.CellRect(x,y);
      Form1.Map.Tag:=1;
      Form1.Map.Canvas.MoveTo(Rect.Left,Rect.Top);
      Form1.Map.Canvas.LineTo(Rect.Right,Rect.Top);
      Form1.Map.Canvas.LineTo(Rect.Right,Rect.Bottom);
      Form1.Map.Canvas.LineTo(Rect.Left,Rect.Bottom);
      Form1.Map.Canvas.LineTo(Rect.Left,Rect.Top);
    end;
  PrevFloorForRepaint:=Floor+Form1.SoundArea0.Value;
end;

procedure TForm1.ObjFloorChange(Sender: TObject);
begin
  MObj[ObjNum.Value].areanum:=(sender as tspinedit).Value;
  Form1.Label31.Color:=(3 - ((sender as tspinedit).Value+SoundArea0.Value) mod 4)*85+(7 - ((sender as tspinedit).Value+SoundArea0.Value) div 4 mod 8)*36*256+(7 - ((sender as tspinedit).Value+SoundArea0.Value) div 32)*36*256*256;
  ShowFloor ((sender as tspinedit).Value);
end;

procedure TForm1.ObjTXChange(Sender: TObject);
begin
  MObj[ObjNum.Value].tilex:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjTYChange(Sender: TObject);
begin
  MObj[ObjNum.Value].tiley:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjXChange(Sender: TObject);
begin
  MObj[ObjNum.Value].x:=ObjX.Value;
  if MObj[ObjNum.Value].Bset then MObj[ObjNum.Value].B.Left:=round((ObjX.Value and $3fffff + ObjY.Value and $ffffffffffc00000 div 64 - 32768)/5957.8181818);
end;

procedure TForm1.ObjYChange(Sender: TObject);
begin
  MObj[ObjNum.Value].y:=ObjY.Value;
  if MObj[ObjNum.Value].Bset then MObj[ObjNum.Value].B.Top :=round((ObjY.Value and $3fffff                                   - 32768)/5957.8181818);
  if MObj[ObjNum.Value].Bset then MObj[ObjNum.Value].B.Left:=round((ObjX.Value and $3fffff + ObjY.Value and $ffffffffffc00000 div 64 - 32768)/5957.8181818);
end;

procedure TForm1.ObjViewXChange(Sender: TObject);
begin
  MObj[ObjNum.Value].viewx:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjViewHChange(Sender: TObject);
begin
  MObj[ObjNum.Value].viewheight:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjGXChange(Sender: TObject);
begin
  MObj[ObjNum.Value].transx:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjGYChange(Sender: TObject);
begin
  MObj[ObjNum.Value].transy:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjAngleChange(Sender: TObject);
begin
  MObj[ObjNum.Value].angle:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjHealthChange(Sender: TObject);
begin
  MObj[ObjNum.Value].hitpoints:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjSpeedChange(Sender: TObject);
begin
  MObj[ObjNum.Value].speed:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjT1Change(Sender: TObject);
begin
  MObj[ObjNum.Value].temp1:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjT2Change(Sender: TObject);
begin
  MObj[ObjNum.Value].temp2:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjT3Change(Sender: TObject);
begin
  MObj[ObjNum.Value].temp3:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjNextChange(Sender: TObject);
begin
  MObj[ObjNum.Value].next:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjPrevChange(Sender: TObject);
begin
  MObj[ObjNum.Value].prev:=(sender as tspinedit).Value;
end;

procedure TForm1.ObjAmountChange(Sender: TObject);
var i: integer;
exist:boolean;
begin
  MObj[ObjAmount.Value].active:=-1; //New end-of-object-list marker;
  if ObjAmount.Value>0 then for i:=0 to ObjAmount.Value-1 do if MObj[i].active=-1 then MessageBox(0, 'Achtung: End Of MObj marker and ObjAmount shows different values!', 'Achtung!', MB_OK); 
  NumOfMObj:=ObjAmount.Value;
  ObjNum.Value:=ObjNum.Value+1;ObjNum.Value:=ObjNum.Value-1; //force refresh;
  exist:=TRUE;
  for i:=0 to 511 do begin
    if MObj[i].active=-1 then exist:=FALSE;
    if exist then begin
      if not MObj[i].Bset then begin
        MObj[i].B:=TShape.Create(Map);
        MObj[i].Bset:=TRUE;
        with MObj[i].B do begin
          Shape:=stEllipse;
          Brush.Color:=127*(MObj[i].obclass mod 3)*256+127*(MObj[i].obclass div 3 mod 3)+85*(MObj[i].obclass div 9)*65536;
          Brush.Style:=bsSolid;
          Parent:=Map;
          Width:=10;
          Height:=10;
          Left:=round((MObj[i].x and $3fffff + MObj[i].y and $ffffffffffc00000 div 64 - 32768)/5957.8181818);
          Top :=round((MObj[i].y and $3fffff                                  - 32768)/5957.8181818);
          Tag:=i;
          onMouseDown:=WlMObjPress;
        end;
      end;
    end else begin
      if MObj[i].Bset then begin
        MObj[i].B.Free;
        MObj[i].Bset:=FALSE;
      end;
    end;
  end;
end;

procedure TForm1.WlMObjPress(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
var kill,i: word;
begin
  if Button=mbMiddle then with (Sender as TShape) do begin
    ObjInDrag.Value:=0;
    kill:=Tag;
    if MObj[kill].Bset then MObj[kill].B.Free;
    for i:=kill to 510 do begin
      MObj[i].active:=MObj[i+1].active;
      MObj[i].ticcount:=MObj[i+1].ticcount;
      MObj[i].obclass:=MObj[i+1].obclass;
      MObj[i].statetype:=MObj[i+1].statetype;
      MObj[i].flags:=MObj[i+1].flags;
      MObj[i].distance:=MObj[i+1].distance;
      MObj[i].dir:=MObj[i+1].dir;
      MObj[i].x:=MObj[i+1].x;
      MObj[i].y:=MObj[i+1].y;
      MObj[i].tilex:=MObj[i+1].tilex;
      MObj[i].tiley:=MObj[i+1].tiley;
      MObj[i].areanum:=MObj[i+1].areanum;
      MObj[i].viewx:=MObj[i+1].viewx;
      MObj[i].viewheight:=MObj[i+1].viewheight;
      MObj[i].transx:=MObj[i+1].transx;
      MObj[i].transy:=MObj[i+1].transy;
      MObj[i].angle:=MObj[i+1].angle;
      MObj[i].hitpoints:=MObj[i+1].hitpoints;
      MObj[i].speed:=MObj[i+1].speed;
      MObj[i].temp1:=MObj[i+1].temp1;
      MObj[i].temp2:=MObj[i+1].temp2;
      MObj[i].temp3:=MObj[i+1].temp3;
      MObj[i].next:=MObj[i+1].next;
      MObj[i].prev:=MObj[i+1].prev;
      MObj[i].Bset:=MObj[i+1].Bset;
      MObj[i].B:=MObj[i+1].B;
      if MObj[i].Bset then MObj[i].B.Tag:=i;
    end;
    for i:= 0 to 4095 do if strtoint (Map.Cells[i mod 64,i div 64]) div 256 > kill*60+Obj0Ptr.Value then Map.Cells[i mod 64,i div 64]:= inttostr (strtoint(Map.Cells[i mod 64,i div 64]) - 60*256) else if strtoint (Map.Cells[i mod 64,i div 64]) div 256 = kill*60+Obj0Ptr.Value then Map.Cells[i mod 64,i div 64]:=inttostr (strtoint(Map.Cells[i mod 64,i div 64]) and $FF);
    for i:=0 to 511 do if MObj[i].active=-1 then begin ObjAmount.Value:=i; break end;
    if ObjNum.Value=0 then begin  //Force-refresh;
      ObjNum.Value:=1;ObjNum.Value:=0;
    end else begin
      ObjNum.Value:=ObjNum.Value-1;
      if ObjNum.Value<ObjAmount.Value-1 then ObjNum.Value:=ObjNum.Value+1;
    end;
  end;
  if Button=mbLeft then with (Sender as TShape) do begin
    if Form1.ObjNum.Value=Tag then ObjInDrag.Value:=1-ObjInDrag.Value else ObjInDrag.Value:=0;
    Form1.ObjNum.Value:=Tag;
  end;
end;

procedure TForm1.Obj0PtrChange(Sender: TObject);
begin
  Map.Refresh;
end;

procedure TForm1.ObjCenterClick(Sender: TObject);
begin
  ObjX.Value:=ObjTX.Value*65536+32768;
  ObjY.Value:=ObjTY.Value*65536+32768;
end;

procedure TForm1.ObjInDragChange(Sender: TObject);
begin
  if Form1.ObjInDrag.Value=1 then MObj[ObjNum.Value].B.Brush.Color:=$FF2020 else MObj[ObjNum.Value].B.Brush.Color:=$FFFFFF;
end;

procedure TForm1.ThingInDragChange(Sender: TObject);
begin
  if Form1.ThingInDrag.Value=1 then SObj[ThingNum.Value].B.Color:=$FF2020 else SObj[ThingNum.Value].B.Color:=$FFFFFF;
end;

procedure TForm1.RefreshUnchangeablesClick(Sender: TObject);
begin
  LoadUnchangeables;
  Map.Tag:=1;
end;

procedure TForm1.DoorInDragChange(Sender: TObject);
begin
  if Form1.DoorInDrag.Value=1 then doorstat[DoorNum.Value].B.Picture:=Form1.Image2.Picture else doorstat[DoorNum.Value].B.Picture:=Form1.Image1.Picture;
end;

procedure TForm1.DoorNumChange(Sender: TObject);
begin
  DoorX.Value:=doorstat[DoorNum.Value].x;
  DoorY.Value:=doorstat[DoorNum.Value].y;
  DoorAng.Value:=doorstat[DoorNum.Value].vertflag;
  DoorLock.Value:=doorstat[DoorNum.Value].lock;
  DoorMotion.Value:=doorstat[DoorNum.Value].motion;
  DoorTicCount.Value:=doorstat[DoorNum.Value].ticcount;
  DoorPosit.Value:=doorpos[DoorNum.Value];
end;

procedure TForm1.DoorXChange(Sender: TObject);
begin
  doorstat[DoorNum.Value].x:=DoorX.Value;
  doorstat[DoorNum.Value].B.Left:=(DoorX.Value mod 64)*11+8;
end;

procedure TForm1.DoorYChange(Sender: TObject);
begin
  doorstat[DoorNum.Value].y:=DoorY.Value;
  doorstat[DoorNum.Value].B.Top:=(DoorY.Value mod 64)*11+3;
end;

procedure TForm1.DoorLockChange(Sender: TObject);
begin
  doorstat[DoorNum.Value].lock:=DoorLock.Value;
end;

procedure TForm1.DoorMotionChange(Sender: TObject);
begin
  doorstat[DoorNum.Value].motion:=DoorMotion.Value;
  case DoorMotion.Value of
    0: DoorMotionLabel.Caption:='Open';
    1: DoorMotionLabel.Caption:='Closed';
    2: DoorMotionLabel.Caption:='Opening';
    3: DoorMotionLabel.Caption:='Closing';
    else DoorMotionLabel.Caption:='?????';
  end;
end;

procedure TForm1.DoorAngChange(Sender: TObject);
begin
  doorstat[DoorNum.Value].vertflag:=DoorAng.Value;
  case DoorAng.Value of
    0: DoorAngLabel.Caption:='—';
    1: DoorAngLabel.Caption:='|';
    else DoorAngLabel.Caption:='X';
  end;
end;

procedure TForm1.DoorTicCountChange(Sender: TObject);
begin
  doorstat[DoorNum.Value].ticcount:=DoorTicCount.Value;
end;

procedure TForm1.DoorPositChange(Sender: TObject);
begin
  doorpos[DoorNum.Value]:=DoorPosit.Value;
end;

procedure TForm1.HearFloorChange(Sender: TObject);
var i: integer;
begin
  Hear.Value:=SndZone[HearFloor.Value];
  Form1.Label36.Color:=(3 - ((sender as tspinedit).Value+SoundArea0.Value) mod 4)*85+(7 - ((sender as tspinedit).Value+SoundArea0.Value) div 4 mod 8)*36*256+(7 - ((sender as tspinedit).Value+SoundArea0.Value) div 32)*36*256*256;
  ShowFloor ((sender as tspinedit).Value);
  AreaCon.Cells[AreaCon.ColCount-1,1]:='-';
  for i:=0 to FormatNFloors.Value-1 do AreaCon.Cells[i mod AreaCon.ColCount, i div AreaCon.ColCount]:=inttostr(SndLnks[HearFloor.Value,i]);
end;

procedure TForm1.HearChange(Sender: TObject);
begin
  SndZone[HearFloor.Value]:=Hear.Value;
end;

procedure TForm1.FormatNFloorsChange(Sender: TObject);
begin
  AreaCon.DefaultColWidth:=1;
  AreaCon.ColCount:=(FormatNFloors.Value+1) div 2;
  AreaCon.DefaultColWidth:=AreaCon.Width div (AreaCon.ColCount+1) - 1;
end;

procedure TForm1.AreaConSelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
  ShowFloor (ARow*AreaCon.ColCount+ACol);
end;

procedure TForm1.AreaConSetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: String);
begin
  SndLnks[HearFloor.Value,ARow*AreaCon.ColCount+ACol]:=strtoint(Value);
end;

procedure TForm1.PWDirChange(Sender: TObject);
begin
  case PWDir.Value of
    0: PWallDirLabel.Caption:='й';
    1: PWallDirLabel.Caption:='и';
    2: PWallDirLabel.Caption:='к';
    3: PWallDirLabel.Caption:='з';
    else PWallDirLabel.Caption:='x';
  end;
end;

procedure TForm1.PWXChange(Sender: TObject);
begin
  Map.Canvas.Brush.Style:=bsSolid;
  Map.Canvas.Brush.Color:=clWhite;
  Map.Canvas.FillRect(Map.CellRect(PWRepaintX,PWRepaintY));
  Map.Canvas.Brush.Color:=clBlack;
  Map.Canvas.FillRect(Map.CellRect(PWX.Value,PWY.Value));
  Form1.Map.Tag:=1;
  PWRepaintX:=PWX.Value;
end;

procedure TForm1.PWYChange(Sender: TObject);
begin
  Map.Canvas.Brush.Style:=bsSolid;
  Map.Canvas.Brush.Color:=clWhite;
  Map.Canvas.FillRect(Map.CellRect(PWRepaintX,PWRepaintY));
  Map.Canvas.Brush.Color:=clBlack;
  Map.Canvas.FillRect(Map.CellRect(PWX.Value,PWY.Value));
  Form1.Map.Tag:=1;
  PWRepaintY:=PWY.Value;
end;

end.
