unit uDiffForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, uConfig;

type
  TDiffForm = class(TForm)
    eOrigMap: TLabeledEdit;
    btnBrowseOrigMap: TButton;
    eChangedMap: TLabeledEdit;
    btnBrowseChangedMap: TButton;
    eOrigStaIdx: TLabeledEdit;
    btnBrowseOrigStaIdx: TButton;
    eOrigStatics: TLabeledEdit;
    btnBrowseOrigStatics: TButton;
    eChangedStaIdx: TLabeledEdit;
    eChangedStatics: TLabeledEdit;
    btnBrowseChangedStaIdx: TButton;
    btnBrowseChangedStatics: TButton;
    btnCreateMapDiff: TButton;
    btnApplyMapDiff: TButton;
    btnCreateStaticDiff: TButton;
    btnApplyStaticDiff: TButton;
    btnCopyMap: TButton;
    btnCopyStatic: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnBrowseOrigMapClick(Sender: TObject);
    procedure btnBrowseChangedMapClick(Sender: TObject);
    procedure btnBrowseOrigStaIdxClick(Sender: TObject);
    procedure btnBrowseOrigStaticsClick(Sender: TObject);
    procedure btnBrowseChangedStaIdxClick(Sender: TObject);
    procedure btnBrowseChangedStaticsClick(Sender: TObject);
    procedure btnCreateMapDiffClick(Sender: TObject);
    procedure btnCopyMapClick(Sender: TObject);
    procedure btnApplyMapDiffClick(Sender: TObject);
    procedure btnCreateStaticDiffClick(Sender: TObject);
    procedure btnCopyStaticClick(Sender: TObject);
    procedure btnApplyStaticDiffClick(Sender: TObject);
  private
    procedure LoadPaths;
    function BrowseFile( Filename : String ) : String;
  public
    { Public declarations }
  end;

var
  DiffForm: TDiffForm;

implementation

{$R *.dfm}

uses uUtilities, StrLib, uGaugeForm;

type    TIndexRecord = packed record
                Offset: Integer;
                Length: Integer;
                Extra: Integer
        end;

        TMapCell = packed record
                Id: Word;
                Z: Shortint;
        end;

        TMapBlock = packed record
                Header: Cardinal;
                Cells: Array[0..63] of TMapCell;
        end;

        type TStaticItem = packed record
                ID: Word;
                X: Byte;
                Y: Byte;
                Z: Shortint;
                 Color: Word;
        end;

procedure TDiffForm.LoadPaths;
begin
        eOrigMap.Text := Config.GetString( 'DiffOrigMap0' );
        eChangedMap.Text := Config.GetString( 'DiffChangedMap0' );
        eOrigStaIdx.Text := Config.GetString( 'DiffOrigStaIdx0' );
        eOrigStatics.Text := Config.GetString( 'DiffOrigStatics0' );
        eChangedStaIdx.Text := Config.GetString( 'DiffChangedStaIdx0' );
        eChangedStatics.Text := Config.GetString( 'DiffChangedStatics0' );        
end;

function TDiffForm.BrowseFile( Filename : String ) : String;
var     OpenDialog : TOpenDialog;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := Filename + '|' + Filename;

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                Result := '';
                exit;
        end;

        if not FileExists(OpenDialog.FileName) then begin
                Application.MessageBox( 'Diese Datei ist nicht existent. Bitte wählen sie einen gültigen Dateinamen.', 'Datei nicht gefunden', MB_OK+MB_ICONERROR );
                OpenDialog.Free;
                Result := '';
                Exit;
        end;

        Result := OpenDialog.FileName;
        OpenDialog.Free;
end;

procedure TDiffForm.FormCreate(Sender: TObject);
begin
        LoadPaths;
end;

procedure TDiffForm.btnBrowseOrigMapClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Map0.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'DiffOrigMap0', Newfile );
                eOrigMap.Text := NewFile;
        end;
end;

procedure TDiffForm.btnBrowseChangedMapClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Map0.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'DiffChangedMap0', Newfile );
                eChangedMap.Text := NewFile;
        end;
end;

procedure TDiffForm.btnBrowseOrigStaIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Staidx0.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'DiffOrigStaIdx0', Newfile );
                eOrigStaIdx.Text := NewFile;
        end;
end;

procedure TDiffForm.btnBrowseOrigStaticsClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Statics0.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'DiffOrigStatics0', Newfile );
                eOrigStatics.Text := NewFile;
        end;
end;

procedure TDiffForm.btnBrowseChangedStaIdxClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Staidx0.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'DiffChangedStaIdx0', Newfile );
                eChangedStaIdx.Text := NewFile;
        end;
end;

procedure TDiffForm.btnBrowseChangedStaticsClick(Sender: TObject);
var     NewFile : String;
begin
        NewFile := BrowseFile( 'Statics0.mul' );
        if NewFile <> '' then begin
                Config.SetString( 'DiffChangedStatics0', Newfile );
                eChangedStatics.Text := NewFile;
        end;
end;

procedure TDiffForm.btnCreateMapDiffClick(Sender: TObject);
var     OrigFile, ChangedFile : TFileStream;
        SaveDialog : TSaveDialog;
        MapDiff, MapDiffIndex : TFileStream;
        MapBlockOrig, MapBlockChanged : TMapBlock;
        MapDiffPath, MapDiffIndexPath : String;
        Id, I, PatchCount : Integer;
        Identisch : Boolean;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := 'Mapdifl0.mul|Mapdifl0.mul';
        SaveDialog.Title := 'Choose Mapdifl0.mul';
        SaveDialog.DefaultExt := 'mul';        

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        MapDiffIndexPath := SaveDialog.FileName;

        SaveDialog.Filter := 'Mapdif0.mul|Mapdif0.mul';
        SaveDialog.Title := 'Choose Mapdif0.mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        MapDiffPath := SaveDialog.FileName;
        SaveDialog.Free;

        if FileExists( MapDiffIndexPath ) then
                DeleteFile( MapDiffIndexPath );
        if FileExists( MapDiffPath ) then
                DeleteFile( MapDiffPath );

        MapDiffIndex := TFileStream.Create( MapDiffIndexPath, fmCreate );
        MapDiffIndex.Seek( 0, soFromBeginning );
        MapDiff := TFileStream.Create( MapDiffPath, fmCreate );
        MapDiff.Seek( 0, soFromBeginning );

        OrigFile := TFileStream.Create( eOrigMap.Text, fmOpenRead );
        ChangedFile := TFileStream.Create( eChangedMap.Text, fmOpenRead );

        OrigFile.Seek( 0, soFromBeginning );
        ChangedFile.Seek( 0, soFromBeginning );

        PatchCount := 0;
        GaugeForm.Activate;
        for Id := 0 to 393215 do begin
                GaugeForm.SetBalken( trunc( 100*Id/393215 ) );
                OrigFile.Read( MapBlockOrig, sizeof( TMapBlock ) );
                ChangedFile.Read( MapBlockChanged, sizeof( TMapBlock ) );
                Identisch := True;

                for I := 0 to 63 do
                        if ( MapBlockOrig.Cells[I].Id <> MapBlockChanged.Cells[I].Id ) or
                                ( MapBlockOrig.Cells[I].Z <> MapBlockChanged.Cells[I].Z ) then begin
                                Identisch := False;
                                break;
                        end;

                if not Identisch then begin
                        MapDiffIndex.Write( Id, 4 );
                        MapDiff.Write( MapBlockChanged, sizeof( TMapBlock ) );
                        inc( PatchCount );
                end;
        end;
        GaugeForm.Deactivate;

        MapDiffIndex.Free;
        MapDiff.Free;
        OrigFile.Free;
        ChangedFile.Free;
        showmessage( Format( '%d Mapblocks patched.', [PatchCount] ) );
end;

procedure TDiffForm.btnCopyMapClick(Sender: TObject);
var     ChangedFile : TFileStream;
        SaveDialog : TSaveDialog;
        MapDiff, MapDiffIndex : TFileStream;
        MapBlockChanged : TMapBlock;
        MapDiffPath, MapDiffIndexPath : String;
        Id, I, PatchCount : Integer;
        Identisch : Boolean;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := 'Mapdifl0.mul|Mapdifl0.mul';
        SaveDialog.Title := 'Choose Mapdifl0.mul';
        SaveDialog.DefaultExt := 'mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        MapDiffIndexPath := SaveDialog.FileName;

        SaveDialog.Filter := 'Mapdif0.mul|Mapdif0.mul';
        SaveDialog.Title := 'Choose Mapdif0.mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        MapDiffPath := SaveDialog.FileName;
        SaveDialog.Free;

        if FileExists( MapDiffIndexPath ) then
                DeleteFile( MapDiffIndexPath );
        if FileExists( MapDiffPath ) then
                DeleteFile( MapDiffPath );

        MapDiffIndex := TFileStream.Create( MapDiffIndexPath, fmCreate );
        MapDiffIndex.Seek( 0, soFromBeginning );
        MapDiff := TFileStream.Create( MapDiffPath, fmCreate );
        MapDiff.Seek( 0, soFromBeginning );

        ChangedFile := TFileStream.Create( eChangedMap.Text, fmOpenRead );

        ChangedFile.Seek( 0, soFromBeginning );

        PatchCount := 0;
        GaugeForm.Activate;
        for Id := 0 to 393215 do begin
                GaugeForm.SetBalken( trunc( 100*Id/393215 ) );
                ChangedFile.Read( MapBlockChanged, sizeof( TMapBlock ) );

                Identisch := True;
                for I := 0 to 63 do
                        if (MapBlockChanged.Cells[I].Id <> $1) and (MapBlockChanged.Cells[I].Id <> $244) then begin
                                Identisch := False;
                                break;
                        end;

                if not Identisch then begin
                        MapDiffIndex.Write( Id, 4 );
                        MapDiff.Write( MapBlockChanged, sizeof( TMapBlock ) );
                        inc( PatchCount );
                end;
        end;
        GaugeForm.Deactivate;

        MapDiffIndex.Free;
        MapDiff.Free;
        ChangedFile.Free;
        showmessage( Format( '%d Mapblocks patched.', [PatchCount] ) );
end;

procedure TDiffForm.btnApplyMapDiffClick(Sender: TObject);
var     OrigFile : TFileStream;
        OpenDialog : TOpenDialog;
        MapDiff, MapDiffIndex : TFileStream;
        MapBlock : TMapBlock;
        MapDiffPath, MapDiffIndexPath : String;
        I, Count, Id : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := 'Mapdifl0.mul|Mapdifl0.mul';
        OpenDialog.Title := 'Choose Mapdifl0.mul';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;
        MapDiffIndexPath := OpenDialog.FileName;

        OpenDialog.Filter := 'Mapdif0.mul|Mapdif0.mul';
        OpenDialog.Title := 'Choose Mapdif0.mul';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;
        MapDiffPath := OpenDialog.FileName;
        OpenDialog.Free;

        MapDiffIndex := TFileStream.Create( MapDiffIndexPath, fmOpenRead );
        MapDiffIndex.Seek( 0, soFromBeginning );
        MapDiff := TFileStream.Create( MapDiffPath, fmOpenRead );
        MapDiff.Seek( 0, soFromBeginning );

        OrigFile := TFileStream.Create( eOrigMap.Text, fmOpenReadWrite );

        GaugeForm.Activate;
        Count := MapDiffIndex.Size div 4;
        for I := 0 to ( MapDiffIndex.Size div 4 )-1 do begin
                GaugeForm.SetBalken( trunc( 100*I /(MapDiffIndex.Size/4) ) );
                MapDiffIndex.Read( Id, 4 );
                MapDiff.Read( MapBlock, sizeof( TMapBlock ) );

                OrigFile.Seek( Id*sizeof( TMapBlock ), soFromBeginning );
                OrigFile.Write( MapBlock, sizeof( TMapBlock ) );
        end;
        GaugeForm.Deactivate;

        MapDiffIndex.Free;
        MapDiff.Free;
        OrigFile.Free;
        showmessage( Format( '%d Mapblocks patched.', [Count] ) );
end;

procedure TDiffForm.btnCreateStaticDiffClick(Sender: TObject);
var     OrigFile, OrigIdxFile, ChangedFile, ChangedIdxFile : TFileStream;
        OrigIndexRecord, ChangedIndexRecord, NewIndexRecord : TIndexRecord;
        SaveDialog : TSaveDialog;
        StaticDiffIdx, StaticDiffMul, DiffIndex : TFileStream;
        Buf : PByteArray;
        StaticDiffIdxPath, StaticDiffMulPath, StaticDiffIndexPath : String;
        Id, ItemCount, PatchCount : Integer;
        Identisch : Boolean;
        OrigItem, ChangedItem : TStaticItem;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := 'Stadifl0.mul|Stadifl0.mul';
        SaveDialog.Title := 'Choose Stadifl0.mul';
        SaveDialog.DefaultExt := 'mul';        

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        StaticDiffIndexPath := SaveDialog.FileName;

        SaveDialog.Filter := 'Stadifi0.mul|Stadifi0.mul';
        SaveDialog.Title := 'Choose Stadifi0.mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        StaticDiffIdxPath := SaveDialog.FileName;

        SaveDialog.Filter := 'Stadif0.mul|Stadif0.mul';
        SaveDialog.Title := 'Choose Stadif0.mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        StaticDiffMulPath := SaveDialog.FileName;
        SaveDialog.Free;

        if FileExists( StaticDiffIndexPath ) then
                DeleteFile( StaticDiffIndexPath );
        if FileExists( StaticDiffIdxPath ) then
                DeleteFile( StaticDiffIdxPath );
        if FileExists( StaticDiffMulPath ) then
                DeleteFile( StaticDiffMulPath );

        DiffIndex := TFileStream.Create( StaticDiffIndexPath, fmCreate );
        DiffIndex.Seek( 0, soFromBeginning );
        StaticDiffIdx := TFileStream.Create( StaticDiffIdxPath, fmCreate );
        StaticDiffIdx.Seek( 0, soFromBeginning );
        StaticDiffMul := TFileStream.Create( StaticDiffMulPath, fmCreate );
        StaticDiffMul.Seek( 0, soFromBeginning );

        OrigFile := TFileStream.Create( eOrigStatics.Text, fmOpenRead );
        OrigIdxFile := TFileStream.Create( eOrigStaIdx.Text, fmOpenRead );
        ChangedFile := TFileStream.Create( eChangedStatics.Text, fmOpenRead );
        ChangedIdxFile := TFileStream.Create( eChangedStaIdx.Text, fmOpenRead );

        OrigIdxFile.Seek( 0, soFromBeginning );
        ChangedIdxFile.Seek( 0, soFromBeginning );

        PatchCount := 0;
        GaugeForm.Activate;
        for Id := 0 to 393215 do begin
                GaugeForm.SetBalken( trunc( 100*Id/393215 ) );
                OrigIdxFile.Read( OrigIndexRecord, 12 );
                ChangedIdxFile.Read( ChangedIndexRecord, 12 );

                Identisch := True;
                if ( OrigIndexRecord.Offset = ChangedIndexRecord.Offset ) and
                        ( OrigIndexRecord.Length = OrigIndexRecord.Length ) and
                        ( OrigIndexRecord.Extra = OrigIndexRecord.Extra ) then begin
                        OrigFile.Seek( OrigIndexRecord.Offset, soFromBeginning );
                        ChangedFile.Seek( ChangedIndexRecord.Offset, soFromBeginning );
                        for ItemCount := 0 to ( OrigIndexRecord.Length div sizeof( TStaticItem ) )-1 do begin
                                OrigFile.Read( OrigItem, sizeof( TStaticItem ) );
                                ChangedFile.Read( ChangedItem, sizeof( TStaticItem ) );
                                if ( OrigItem.ID <> ChangedItem.ID ) or ( OrigItem.X <> ChangedItem.X ) or ( OrigItem.Y <> ChangedItem.Y ) or ( OrigItem.Z <> ChangedItem.Z ) or ( OrigItem.Color <> ChangedItem.Color ) then begin
                                        Identisch := False;
                                        break;
                                end;
                        end;
                end
                else begin
                        Identisch := False;
                end;

                if not Identisch then begin
                        DiffIndex.Write( Id, 4 );
                        ChangedFile.Seek( ChangedIndexRecord.Offset, soFromBeginning );
                        NewIndexRecord.Offset := StaticDiffMul.Position;
                        NewIndexRecord.Length := ChangedIndexRecord.Length;
                        NewIndexRecord.Extra := ChangedIndexRecord.Extra;

                        GetMem( buf, ChangedIndexRecord.Length );
                        ChangedFile.Read( buf^, ChangedIndexRecord.Length );
                        StaticDiffMul.Write( buf^, NewIndexRecord.Length );
                        FreeMem( buf, ChangedIndexRecord.Length );

                        StaticDiffIdx.Write( NewIndexRecord, 12 );
                        inc( PatchCount );
                end;
        end;
        GaugeForm.Deactivate;

        DiffIndex.Free;
        StaticDiffIdx.Free;
        StaticDiffMul.Free;
        OrigFile.Free;
        OrigIdxFile.Free;
        ChangedFile.Free;
        ChangedIdxFile.Free;
        showmessage( Format( '%d Staticblocks patched.', [PatchCount] ) );
end;

procedure TDiffForm.btnCopyStaticClick(Sender: TObject);
var     ChangedFile, ChangedIdxFile : TFileStream;
        ChangedIndexRecord, NewIndexRecord : TIndexRecord;
        SaveDialog : TSaveDialog;
        StaticDiffIdx, StaticDiffMul, DiffIndex : TFileStream;
        Buf : PByteArray;
        StaticDiffIdxPath, StaticDiffMulPath, StaticDiffIndexPath : String;
        Id, PatchCount : Integer;
        Identisch : Boolean;
begin
        SaveDialog := TSaveDialog.Create( nil );
        SaveDialog.Filter := 'Stadifl0.mul|Stadifl0.mul';
        SaveDialog.Title := 'Choose Stadifl0.mul';
        SaveDialog.DefaultExt := 'mul';        

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        StaticDiffIndexPath := SaveDialog.FileName;

        SaveDialog.Filter := 'Stadifi0.mul|Stadifi0.mul';
        SaveDialog.Title := 'Choose Stadifi0.mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        StaticDiffIdxPath := SaveDialog.FileName;

        SaveDialog.Filter := 'Stadif0.mul|Stadif0.mul';
        SaveDialog.Title := 'Choose Stadif0.mul';

        if not SaveDialog.Execute then begin
                SaveDialog.Free;
                exit;
        end;
        StaticDiffMulPath := SaveDialog.FileName;
        SaveDialog.Free;

        if FileExists( StaticDiffIndexPath ) then
                DeleteFile( StaticDiffIndexPath );
        if FileExists( StaticDiffIdxPath ) then
                DeleteFile( StaticDiffIdxPath );
        if FileExists( StaticDiffMulPath ) then
                DeleteFile( StaticDiffMulPath );

        DiffIndex := TFileStream.Create( StaticDiffIndexPath, fmCreate );
        DiffIndex.Seek( 0, soFromBeginning );
        StaticDiffIdx := TFileStream.Create( StaticDiffIdxPath, fmCreate );
        StaticDiffIdx.Seek( 0, soFromBeginning );
        StaticDiffMul := TFileStream.Create( StaticDiffMulPath, fmCreate );
        StaticDiffMul.Seek( 0, soFromBeginning );

        ChangedFile := TFileStream.Create( eChangedStatics.Text, fmOpenRead );
        ChangedIdxFile := TFileStream.Create( eChangedStaIdx.Text, fmOpenRead );

        ChangedIdxFile.Seek( 0, soFromBeginning );

        PatchCount := 0;
        GaugeForm.Activate;
        for Id := 0 to 393215 do begin
                GaugeForm.SetBalken( trunc( 100*Id/393215 ) );
                ChangedIdxFile.Read( ChangedIndexRecord, 12 );

                Identisch := False;
                if not Identisch then begin
                        DiffIndex.Write( Id, 4 );
                        ChangedFile.Seek( ChangedIndexRecord.Offset, soFromBeginning );
                        NewIndexRecord.Offset := StaticDiffMul.Position;
                        NewIndexRecord.Length := ChangedIndexRecord.Length;
                        NewIndexRecord.Extra := ChangedIndexRecord.Extra;

                        GetMem( buf, ChangedIndexRecord.Length );
                        ChangedFile.Read( buf^, ChangedIndexRecord.Length );
                        StaticDiffMul.Write( buf^, NewIndexRecord.Length );
                        FreeMem( buf, ChangedIndexRecord.Length );

                        StaticDiffIdx.Write( NewIndexRecord, 12 );
                        inc( PatchCount );
                end;
        end;
        GaugeForm.Deactivate;

        DiffIndex.Free;
        StaticDiffIdx.Free;
        StaticDiffMul.Free;
        ChangedFile.Free;
        ChangedIdxFile.Free;
        showmessage( Format( '%d Staticblocks patched.', [PatchCount] ) );
end;

procedure TDiffForm.btnApplyStaticDiffClick(Sender: TObject);
var     OrigFile, OrigIdxFile : TFileStream;
        OrigIndexRecord, NewIndexRecord : TIndexRecord;
        OpenDialog : TOpenDialog;
        StaticDiffIdx, StaticDiffMul, DiffIndex : TFileStream;
        Buf : PByteArray;
        StaticDiffIdxPath, StaticDiffMulPath, StaticDiffIndexPath : String;
        Id, I, PatchCount : Integer;
begin
        OpenDialog := TOpenDialog.Create( nil );
        OpenDialog.Filter := 'Stadifl0.mul|Stadifl0.mul';
        OpenDialog.Title := 'Choose Stadifl0.mul';
        OpenDialog.DefaultExt := 'mul';        

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;
        StaticDiffIndexPath := OpenDialog.FileName;

        OpenDialog.Filter := 'Stadifi0.mul|Stadifi0.mul';
        OpenDialog.Title := 'Choose Stadifi0.mul';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;
        StaticDiffIdxPath := OpenDialog.FileName;

        OpenDialog.Filter := 'Stadif0.mul|Stadif0.mul';
        OpenDialog.Title := 'Choose Stadif0.mul';

        if not OpenDialog.Execute then begin
                OpenDialog.Free;
                exit;
        end;
        StaticDiffMulPath := OpenDialog.FileName;
        OpenDialog.Free;

        DiffIndex := TFileStream.Create( StaticDiffIndexPath, fmOpenRead );
        DiffIndex.Seek( 0, soFromBeginning );
        StaticDiffIdx := TFileStream.Create( StaticDiffIdxPath, fmOpenRead );
        StaticDiffIdx.Seek( 0, soFromBeginning );
        StaticDiffMul := TFileStream.Create( StaticDiffMulPath, fmOpenRead );
        StaticDiffMul.Seek( 0, soFromBeginning );

        OrigFile := TFileStream.Create( eOrigStatics.Text, fmOpenReadWrite );
        OrigFile.Seek( 0, soFromEnd );
        OrigIdxFile := TFileStream.Create( eOrigStaIdx.Text, fmOpenReadWrite );

        PatchCount := DiffIndex.Size div 4;
        GaugeForm.Activate;
        for I := 0 to ( DiffIndex.Size div 4 )-1 do begin
                GaugeForm.SetBalken( trunc( 100*I /(DiffIndex.Size/4) ) );

                DiffIndex.Read( Id, 4 );
                StaticDiffIdx.Read( NewIndexRecord, 12 );
                StaticDiffMul.Seek( NewIndexRecord.Offset, soFromBeginning );

                OrigIndexRecord.Offset := OrigFile.Position;
                OrigIndexRecord.Length := NewIndexRecord.Length;
                OrigIndexRecord.Extra := NewIndexRecord.Extra;

                GetMem( buf, OrigIndexRecord.Length );
                StaticDiffMul.Read( buf^, OrigIndexRecord.Length );
                OrigFile.Write( buf^, OrigIndexRecord.Length );
                FreeMem( buf, OrigIndexRecord.Length );

                OrigIdxFile.Seek( Id*12, soFromBeginning );
                OrigIdxFile.Write( OrigIndexRecord, 12 );
                inc( PatchCount );
        end;
        GaugeForm.Deactivate;

        DiffIndex.Free;
        StaticDiffIdx.Free;
        StaticDiffMul.Free;
        OrigFile.Free;
        OrigIdxFile.Free;
        showmessage( Format( '%d Staticblocks patched.', [PatchCount] ) );
end;

end.
