VPatch 2.0 final
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2798 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
2449fbc6bd
commit
6dd280b24f
22 changed files with 3566 additions and 14 deletions
Binary file not shown.
|
@ -141,23 +141,43 @@ file.</p>
|
||||||
patch from file A version 1 to file A version 2 and a patch from file B version 1 to
|
patch from file A version 1 to file A version 2 and a patch from file B version 1 to
|
||||||
file B version 2. Just call the plug-in multiple times with the same patch file. It
|
file B version 2. Just call the plug-in multiple times with the same patch file. It
|
||||||
will automatically select the right patch (based on the file CRC).</p>
|
will automatically select the right patch (based on the file CRC).</p>
|
||||||
|
<p class="header">Source code</p>
|
||||||
|
<p class="subheader">NSIS plug-in (C++)</p>
|
||||||
|
<p class="text">The source of the NSIS plug-in that applies patches can be found in the
|
||||||
|
Source\Plugin folder.</p>
|
||||||
|
<p class="subheader">Patch Generator (Delphi)</p>
|
||||||
|
<p class="text">The most interesting part of VPatch, the actual patch generation algoritm,
|
||||||
|
can be found in Source\GenPat\PatchGenerator.pas. The header of that file contains a brief
|
||||||
|
explanation of the algoritm as well.</p>
|
||||||
|
<p class="subheader">User interface (Delphi)</p>
|
||||||
|
<p class="text">A user interface is included as well, which you will have to build yourself
|
||||||
|
because the GUI executable was too large to include. Besides Borland Delphi 6 or higher,
|
||||||
|
you will also need to install the <a href="http://www.delphi-gems.com">VirtualTreeView</a>
|
||||||
|
component by Mike Lischke.</p>
|
||||||
<p class="header">Version history</p>
|
<p class="header">Version history</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>2.0 beta 2
|
<li>2.0 final
|
||||||
<ul>
|
<ul>
|
||||||
<li>All new algorithm used in the patch generator: much faster (up to
|
<li>Cleaned up source code for the patch generator, which is now included (this code is
|
||||||
90%) while using smaller block sizes (higher compression)</li>
|
written in Borland Delphi 6 and compiles with the freely available Personal edition).</li>
|
||||||
<li>Created a NSIS 2 plugin</li>
|
</ul>
|
||||||
<li>Works with small files</li>
|
</li>
|
||||||
<li>Replaces existing patch in file if original file CRC is identical</li>
|
<li>2.0 beta 2
|
||||||
</ul></li>
|
<ul>
|
||||||
|
<li>All new algorithm used in the patch generator: much faster (up to 90%) while using
|
||||||
|
smaller block sizes (higher compression)</li>
|
||||||
|
<li>Created a NSIS 2 plugin</li>
|
||||||
|
<li>Works with small files</li>
|
||||||
|
<li>Replaces existing patch in file if original file CRC is identical</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="header">Credits</p>
|
<p class="header">Credits</p>
|
||||||
<p class="text">Written by Koen van de Sande<br />
|
<p class="text">Written by Koen van de Sande<br />
|
||||||
C plug-in by Edgewize<br />
|
C plug-in by Edgewize<br />
|
||||||
New documentation and example by Joost Verburg</p>
|
New documentation and example by Joost Verburg</p>
|
||||||
<p class="header">License</p>
|
<p class="header">License</p>
|
||||||
<pre class="margin">Copyright (C) 2001-2002 Koen van de Sande
|
<pre class="margin">Copyright (C) 2001-2003 Koen van de Sande
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
@ -174,9 +194,6 @@ it freely, subject to the following restrictions:
|
||||||
2. Altered versions must be plainly marked as such,
|
2. Altered versions must be plainly marked as such,
|
||||||
and must not be misrepresented as being the original software.
|
and must not be misrepresented as being the original software.
|
||||||
3. This notice may not be removed or altered from any distribution.
|
3. This notice may not be removed or altered from any distribution.
|
||||||
|
|
||||||
Please note that this version contains the plug-in source only,
|
|
||||||
not the source of the patch generator.
|
|
||||||
</pre>
|
</pre>
|
||||||
</div></td>
|
</div></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
BIN
Contrib/VPatch/Source/GUI/AboutForm.dfm
Normal file
BIN
Contrib/VPatch/Source/GUI/AboutForm.dfm
Normal file
Binary file not shown.
31
Contrib/VPatch/Source/GUI/AboutForm.pas
Normal file
31
Contrib/VPatch/Source/GUI/AboutForm.pas
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
unit AboutForm;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
|
||||||
|
Buttons, ExtCtrls;
|
||||||
|
|
||||||
|
type
|
||||||
|
TfrmAbout = class(TForm)
|
||||||
|
Panel1: TPanel;
|
||||||
|
ProgramIcon: TImage;
|
||||||
|
ProductName: TLabel;
|
||||||
|
Version: TLabel;
|
||||||
|
Copyright: TLabel;
|
||||||
|
Comments: TLabel;
|
||||||
|
OKButton: TButton;
|
||||||
|
private
|
||||||
|
{ Private declarations }
|
||||||
|
public
|
||||||
|
{ Public declarations }
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
frmAbout: TfrmAbout;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{$R *.dfm}
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
53
Contrib/VPatch/Source/GUI/DLLWrapper.pas
Normal file
53
Contrib/VPatch/Source/GUI/DLLWrapper.pas
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
unit DLLWrapper;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses Classes, SysUtils;
|
||||||
|
|
||||||
|
function DoGenerate(const Source, Target: String; Stream: TStream; Config: String): Integer; forward;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses PatchGenerator;
|
||||||
|
|
||||||
|
function DoGenerate(const Source, Target: String; Stream: TStream; Config: String): Integer;
|
||||||
|
var
|
||||||
|
PG: TPatchGenerator;
|
||||||
|
a: Integer;
|
||||||
|
begin
|
||||||
|
WriteLn('Generating '+ExtractFileName(Source)+' to '+ExtractFileName(Target)+'...');
|
||||||
|
|
||||||
|
PG:=TPatchGenerator.Create;
|
||||||
|
PG.StartBlockSize:=512;
|
||||||
|
PG.MinimumBlockSize:=512;
|
||||||
|
PG.BlockDivider:=2;
|
||||||
|
PG.StepSize:=256;
|
||||||
|
try
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
PG.StartBlockSize:=StrToInt(Copy(Config,1,a-1));
|
||||||
|
Config:=Copy(Config,a+1,Length(Config));
|
||||||
|
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
PG.MinimumBlockSize:=StrToInt(Copy(Config,1,a-1));
|
||||||
|
Config:=Copy(Config,a+1,Length(Config));
|
||||||
|
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
PG.BlockDivider:=StrToInt(Copy(Config,1,a-1));
|
||||||
|
Config:=Copy(Config,a+1,Length(Config));
|
||||||
|
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
PG.StepSize:=StrToInt(Copy(Config,1,a-1));
|
||||||
|
finally
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result:=PG.CreatePatch(Source,Target);
|
||||||
|
PG.WriteToStream(Stream);
|
||||||
|
PG.Free;
|
||||||
|
WriteLn(ExtractFileName(Source)+' -> '+ExtractFileName(Target)+': '+IntToStr(Result)+' bytes');
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
903
Contrib/VPatch/Source/GUI/MainForm.dfm
Normal file
903
Contrib/VPatch/Source/GUI/MainForm.dfm
Normal file
|
@ -0,0 +1,903 @@
|
||||||
|
object frmMain: TfrmMain
|
||||||
|
Left = 195
|
||||||
|
Top = 93
|
||||||
|
BorderIcons = [biSystemMenu, biMinimize]
|
||||||
|
BorderStyle = bsSingle
|
||||||
|
Caption = 'VG - VPatch GUI'
|
||||||
|
ClientHeight = 361
|
||||||
|
ClientWidth = 689
|
||||||
|
Color = clBtnFace
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'MS Sans Serif'
|
||||||
|
Font.Style = []
|
||||||
|
Menu = MainMenu
|
||||||
|
OldCreateOrder = False
|
||||||
|
Position = poScreenCenter
|
||||||
|
ShowHint = True
|
||||||
|
OnCreate = FormCreate
|
||||||
|
OnDestroy = FormDestroy
|
||||||
|
PixelsPerInch = 96
|
||||||
|
TextHeight = 13
|
||||||
|
object Label1: TLabel
|
||||||
|
Left = 8
|
||||||
|
Top = 32
|
||||||
|
Width = 77
|
||||||
|
Height = 13
|
||||||
|
Caption = 'New versions'
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'MS Sans Serif'
|
||||||
|
Font.Style = [fsBold]
|
||||||
|
ParentFont = False
|
||||||
|
end
|
||||||
|
object butAdd: TSpeedButton
|
||||||
|
Left = 24
|
||||||
|
Top = 328
|
||||||
|
Width = 89
|
||||||
|
Height = 25
|
||||||
|
Caption = 'Add &new version'
|
||||||
|
Flat = True
|
||||||
|
OnClick = butAddClick
|
||||||
|
end
|
||||||
|
object grpConfig: TGroupBox
|
||||||
|
Left = 232
|
||||||
|
Top = 43
|
||||||
|
Width = 441
|
||||||
|
Height = 278
|
||||||
|
Enabled = False
|
||||||
|
TabOrder = 0
|
||||||
|
object Label2: TLabel
|
||||||
|
Left = 16
|
||||||
|
Top = 24
|
||||||
|
Width = 71
|
||||||
|
Height = 13
|
||||||
|
Caption = 'New version'
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'MS Sans Serif'
|
||||||
|
Font.Style = [fsBold]
|
||||||
|
ParentFont = False
|
||||||
|
end
|
||||||
|
object Label3: TLabel
|
||||||
|
Left = 16
|
||||||
|
Top = 80
|
||||||
|
Width = 71
|
||||||
|
Height = 13
|
||||||
|
Caption = 'Old versions'
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'MS Sans Serif'
|
||||||
|
Font.Style = [fsBold]
|
||||||
|
ParentFont = False
|
||||||
|
end
|
||||||
|
object butOldAdd: TSpeedButton
|
||||||
|
Left = 368
|
||||||
|
Top = 96
|
||||||
|
Width = 49
|
||||||
|
Height = 25
|
||||||
|
Caption = '&Add'
|
||||||
|
Flat = True
|
||||||
|
OnClick = butOldAddClick
|
||||||
|
end
|
||||||
|
object butOldRemove: TSpeedButton
|
||||||
|
Left = 368
|
||||||
|
Top = 160
|
||||||
|
Width = 49
|
||||||
|
Height = 25
|
||||||
|
Caption = '&Remove'
|
||||||
|
Flat = True
|
||||||
|
OnClick = butOldRemoveClick
|
||||||
|
end
|
||||||
|
object butNewEdit: TSpeedButton
|
||||||
|
Left = 368
|
||||||
|
Top = 40
|
||||||
|
Width = 49
|
||||||
|
Height = 25
|
||||||
|
Caption = '&Edit'
|
||||||
|
Flat = True
|
||||||
|
OnClick = butNewEditClick
|
||||||
|
end
|
||||||
|
object Label4: TLabel
|
||||||
|
Left = 16
|
||||||
|
Top = 200
|
||||||
|
Width = 176
|
||||||
|
Height = 13
|
||||||
|
Caption = 'Patch generation configuration'
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'MS Sans Serif'
|
||||||
|
Font.Style = [fsBold]
|
||||||
|
ParentFont = False
|
||||||
|
end
|
||||||
|
object Label5: TLabel
|
||||||
|
Left = 32
|
||||||
|
Top = 224
|
||||||
|
Width = 48
|
||||||
|
Height = 13
|
||||||
|
Hint = 'Smaller gives smaller patch files, but decreased speed'
|
||||||
|
Caption = 'Block size'
|
||||||
|
end
|
||||||
|
object Label6: TLabel
|
||||||
|
Left = 32
|
||||||
|
Top = 248
|
||||||
|
Width = 91
|
||||||
|
Height = 13
|
||||||
|
Caption = 'Minimum block size'
|
||||||
|
Visible = False
|
||||||
|
end
|
||||||
|
object Label7: TLabel
|
||||||
|
Left = 232
|
||||||
|
Top = 224
|
||||||
|
Width = 61
|
||||||
|
Height = 13
|
||||||
|
Caption = 'Block divider'
|
||||||
|
Visible = False
|
||||||
|
end
|
||||||
|
object Label8: TLabel
|
||||||
|
Left = 232
|
||||||
|
Top = 248
|
||||||
|
Width = 43
|
||||||
|
Height = 13
|
||||||
|
Caption = 'Step size'
|
||||||
|
Visible = False
|
||||||
|
end
|
||||||
|
object txtStartBlockSize: TLabel
|
||||||
|
Left = 136
|
||||||
|
Top = 224
|
||||||
|
Width = 65
|
||||||
|
Height = 17
|
||||||
|
Alignment = taCenter
|
||||||
|
AutoSize = False
|
||||||
|
end
|
||||||
|
object txtNew: TEdit
|
||||||
|
Left = 32
|
||||||
|
Top = 42
|
||||||
|
Width = 321
|
||||||
|
Height = 21
|
||||||
|
ReadOnly = True
|
||||||
|
TabOrder = 0
|
||||||
|
end
|
||||||
|
object lstOld: TListBox
|
||||||
|
Left = 32
|
||||||
|
Top = 96
|
||||||
|
Width = 321
|
||||||
|
Height = 89
|
||||||
|
ItemHeight = 13
|
||||||
|
TabOrder = 1
|
||||||
|
end
|
||||||
|
object txtMinimumBlockSize: TEdit
|
||||||
|
Left = 136
|
||||||
|
Top = 248
|
||||||
|
Width = 65
|
||||||
|
Height = 21
|
||||||
|
TabOrder = 2
|
||||||
|
Text = '16'
|
||||||
|
Visible = False
|
||||||
|
OnChange = txtMinimumBlockSizeChange
|
||||||
|
end
|
||||||
|
object UDMinimumBlockSize: TUpDown
|
||||||
|
Left = 201
|
||||||
|
Top = 248
|
||||||
|
Width = 15
|
||||||
|
Height = 21
|
||||||
|
Associate = txtMinimumBlockSize
|
||||||
|
Min = 16
|
||||||
|
Max = 4096
|
||||||
|
Increment = 16
|
||||||
|
Position = 16
|
||||||
|
TabOrder = 3
|
||||||
|
Visible = False
|
||||||
|
Wrap = False
|
||||||
|
end
|
||||||
|
object UDBlockDivider: TUpDown
|
||||||
|
Left = 401
|
||||||
|
Top = 224
|
||||||
|
Width = 15
|
||||||
|
Height = 21
|
||||||
|
Associate = txtBlockDivider
|
||||||
|
Min = 2
|
||||||
|
Max = 512
|
||||||
|
Increment = 2
|
||||||
|
Position = 16
|
||||||
|
TabOrder = 4
|
||||||
|
Visible = False
|
||||||
|
Wrap = False
|
||||||
|
end
|
||||||
|
object txtBlockDivider: TEdit
|
||||||
|
Left = 336
|
||||||
|
Top = 224
|
||||||
|
Width = 65
|
||||||
|
Height = 21
|
||||||
|
TabOrder = 5
|
||||||
|
Text = '16'
|
||||||
|
Visible = False
|
||||||
|
OnChange = txtBlockDividerChange
|
||||||
|
end
|
||||||
|
object UDStepSize: TUpDown
|
||||||
|
Left = 401
|
||||||
|
Top = 248
|
||||||
|
Width = 15
|
||||||
|
Height = 21
|
||||||
|
Associate = txtStepSize
|
||||||
|
Min = 16
|
||||||
|
Max = 4096
|
||||||
|
Increment = 16
|
||||||
|
Position = 16
|
||||||
|
TabOrder = 6
|
||||||
|
Visible = False
|
||||||
|
Wrap = False
|
||||||
|
end
|
||||||
|
object txtStepSize: TEdit
|
||||||
|
Left = 336
|
||||||
|
Top = 248
|
||||||
|
Width = 65
|
||||||
|
Height = 21
|
||||||
|
TabOrder = 7
|
||||||
|
Text = '16'
|
||||||
|
Visible = False
|
||||||
|
OnChange = txtStepSizeChange
|
||||||
|
end
|
||||||
|
object tbBlockSize: TTrackBar
|
||||||
|
Left = 200
|
||||||
|
Top = 224
|
||||||
|
Width = 161
|
||||||
|
Height = 25
|
||||||
|
Max = 12
|
||||||
|
Min = 4
|
||||||
|
Orientation = trHorizontal
|
||||||
|
Frequency = 1
|
||||||
|
Position = 6
|
||||||
|
SelEnd = 0
|
||||||
|
SelStart = 0
|
||||||
|
TabOrder = 8
|
||||||
|
TickMarks = tmBottomRight
|
||||||
|
TickStyle = tsAuto
|
||||||
|
OnChange = tbBlockSizeChange
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object lstNew: TVirtualStringTree
|
||||||
|
Left = 24
|
||||||
|
Top = 48
|
||||||
|
Width = 193
|
||||||
|
Height = 273
|
||||||
|
Header.AutoSizeIndex = 0
|
||||||
|
Header.Font.Charset = DEFAULT_CHARSET
|
||||||
|
Header.Font.Color = clWindowText
|
||||||
|
Header.Font.Height = -11
|
||||||
|
Header.Font.Name = 'MS Sans Serif'
|
||||||
|
Header.Font.Style = []
|
||||||
|
Header.MainColumn = -1
|
||||||
|
Header.Options = [hoColumnResize, hoDrag]
|
||||||
|
HintAnimation = hatNone
|
||||||
|
Indent = 0
|
||||||
|
TabOrder = 1
|
||||||
|
TreeOptions.PaintOptions = [toHotTrack, toShowBackground, toShowButtons, toShowDropmark, toShowRoot, toThemeAware, toUseBlendedImages]
|
||||||
|
TreeOptions.SelectionOptions = [toFullRowSelect]
|
||||||
|
OnChange = lstNewChange
|
||||||
|
OnGetText = lstNewGetText
|
||||||
|
Columns = <>
|
||||||
|
end
|
||||||
|
object barCool: TCoolBar
|
||||||
|
Left = 0
|
||||||
|
Top = 0
|
||||||
|
Width = 689
|
||||||
|
Height = 44
|
||||||
|
AutoSize = True
|
||||||
|
Bands = <
|
||||||
|
item
|
||||||
|
BorderStyle = bsSingle
|
||||||
|
Control = barTool
|
||||||
|
ImageIndex = -1
|
||||||
|
MinHeight = 36
|
||||||
|
Width = 689
|
||||||
|
end>
|
||||||
|
EdgeBorders = [ebTop, ebBottom]
|
||||||
|
object barTool: TToolBar
|
||||||
|
Left = 9
|
||||||
|
Top = 2
|
||||||
|
Width = 676
|
||||||
|
Height = 36
|
||||||
|
AutoSize = True
|
||||||
|
ButtonHeight = 36
|
||||||
|
ButtonWidth = 90
|
||||||
|
Caption = 'barTool'
|
||||||
|
EdgeBorders = []
|
||||||
|
Flat = True
|
||||||
|
Images = IL
|
||||||
|
ShowCaptions = True
|
||||||
|
TabOrder = 0
|
||||||
|
object toolNew: TToolButton
|
||||||
|
Left = 0
|
||||||
|
Top = 0
|
||||||
|
Caption = '&New'
|
||||||
|
ImageIndex = 0
|
||||||
|
MenuItem = mnuNew
|
||||||
|
end
|
||||||
|
object toolOpen: TToolButton
|
||||||
|
Left = 90
|
||||||
|
Top = 0
|
||||||
|
Caption = '&Open'
|
||||||
|
ImageIndex = 1
|
||||||
|
MenuItem = mnuOpen
|
||||||
|
end
|
||||||
|
object toolSave: TToolButton
|
||||||
|
Left = 180
|
||||||
|
Top = 0
|
||||||
|
Caption = '&Save'
|
||||||
|
ImageIndex = 2
|
||||||
|
MenuItem = mnuSave
|
||||||
|
end
|
||||||
|
object ToolButton1: TToolButton
|
||||||
|
Left = 270
|
||||||
|
Top = 0
|
||||||
|
Width = 8
|
||||||
|
Caption = 'ToolButton1'
|
||||||
|
ImageIndex = 7
|
||||||
|
Style = tbsSeparator
|
||||||
|
end
|
||||||
|
object toolGenGo: TToolButton
|
||||||
|
Left = 278
|
||||||
|
Top = 0
|
||||||
|
Caption = '&Generate'
|
||||||
|
ImageIndex = 3
|
||||||
|
MenuItem = mnuGenGo
|
||||||
|
end
|
||||||
|
object toolCreateEXE: TToolButton
|
||||||
|
Left = 368
|
||||||
|
Top = 0
|
||||||
|
Caption = 'Create &EXE'
|
||||||
|
ImageIndex = 5
|
||||||
|
MenuItem = mnuCreateEXE
|
||||||
|
end
|
||||||
|
object toolCreateDLL: TToolButton
|
||||||
|
Left = 458
|
||||||
|
Top = 0
|
||||||
|
Caption = 'Create &DLL'
|
||||||
|
ImageIndex = 6
|
||||||
|
MenuItem = mnuCreateDLL
|
||||||
|
end
|
||||||
|
object toolCreatePAT: TToolButton
|
||||||
|
Left = 548
|
||||||
|
Top = 0
|
||||||
|
Caption = 'Create &patch file'
|
||||||
|
ImageIndex = 7
|
||||||
|
MenuItem = mnuCreatePAT
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object chkDebug: TCheckBox
|
||||||
|
Left = 232
|
||||||
|
Top = 336
|
||||||
|
Width = 289
|
||||||
|
Height = 17
|
||||||
|
Caption = 'Show extended information during patch generation'
|
||||||
|
TabOrder = 3
|
||||||
|
OnClick = chkDebugClick
|
||||||
|
end
|
||||||
|
object MainMenu: TMainMenu
|
||||||
|
Images = IL
|
||||||
|
Left = 160
|
||||||
|
Top = 328
|
||||||
|
object mnuFile: TMenuItem
|
||||||
|
Caption = '&File'
|
||||||
|
object mnuNew: TMenuItem
|
||||||
|
Caption = '&New'
|
||||||
|
ImageIndex = 0
|
||||||
|
ShortCut = 16462
|
||||||
|
OnClick = mnuNewClick
|
||||||
|
end
|
||||||
|
object mnuOpen: TMenuItem
|
||||||
|
Caption = '&Open'
|
||||||
|
ImageIndex = 1
|
||||||
|
ShortCut = 16463
|
||||||
|
OnClick = mnuOpenClick
|
||||||
|
end
|
||||||
|
object mnuSave: TMenuItem
|
||||||
|
Caption = '&Save'
|
||||||
|
ImageIndex = 2
|
||||||
|
ShortCut = 16467
|
||||||
|
OnClick = mnuSaveClick
|
||||||
|
end
|
||||||
|
object mnuSaveas: TMenuItem
|
||||||
|
Caption = 'Save &as...'
|
||||||
|
OnClick = mnuSaveasClick
|
||||||
|
end
|
||||||
|
object N1: TMenuItem
|
||||||
|
Caption = '-'
|
||||||
|
end
|
||||||
|
object mnuExit: TMenuItem
|
||||||
|
Caption = 'E&xit'
|
||||||
|
OnClick = mnuExitClick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object mnuAction: TMenuItem
|
||||||
|
Caption = '&Action'
|
||||||
|
object mnuClearcachedpatches: TMenuItem
|
||||||
|
Caption = 'Empty &cache'
|
||||||
|
ImageIndex = 4
|
||||||
|
OnClick = mnuClearcachedpatchesClick
|
||||||
|
end
|
||||||
|
object mnuGenGo: TMenuItem
|
||||||
|
Caption = '&Generate'
|
||||||
|
ImageIndex = 3
|
||||||
|
OnClick = mnuGenGoClick
|
||||||
|
end
|
||||||
|
object mnuCreateEXE: TMenuItem
|
||||||
|
Caption = 'Create &EXE'
|
||||||
|
ImageIndex = 5
|
||||||
|
OnClick = mnuCreateEXEClick
|
||||||
|
end
|
||||||
|
object mnuCreateDLL: TMenuItem
|
||||||
|
Caption = 'Create &DLL'
|
||||||
|
ImageIndex = 6
|
||||||
|
OnClick = mnuCreateDLLClick
|
||||||
|
end
|
||||||
|
object mnuCreatePAT: TMenuItem
|
||||||
|
Caption = 'Create &patch file'
|
||||||
|
ImageIndex = 7
|
||||||
|
OnClick = mnuCreatePATClick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object mnuHelp: TMenuItem
|
||||||
|
Caption = '&Help'
|
||||||
|
object mnuAbout: TMenuItem
|
||||||
|
Caption = '&About'
|
||||||
|
OnClick = mnuAboutClick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
object OD: TOpenDialog
|
||||||
|
Filter = 'All files (*.*)|*.*'
|
||||||
|
Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing, ofDontAddToRecent]
|
||||||
|
Left = 128
|
||||||
|
Top = 328
|
||||||
|
end
|
||||||
|
object dlgOpen: TOpenDialog
|
||||||
|
DefaultExt = '.vpj'
|
||||||
|
Filter = 'VPatch ProJects (*.vpj)|*.vpj|All files (*.*)|*.*'
|
||||||
|
Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing]
|
||||||
|
Left = 104
|
||||||
|
Top = 24
|
||||||
|
end
|
||||||
|
object dlgSave: TSaveDialog
|
||||||
|
DefaultExt = '.vpj'
|
||||||
|
Filter = 'VPatch ProJects (*.vpj)|*.vpj|All files (*.*)|*.*'
|
||||||
|
Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofNoReadOnlyReturn, ofNoDereferenceLinks, ofEnableSizing]
|
||||||
|
Left = 136
|
||||||
|
Top = 24
|
||||||
|
end
|
||||||
|
object IL: TImageList
|
||||||
|
Left = 168
|
||||||
|
Top = 24
|
||||||
|
Bitmap = {
|
||||||
|
494C010108000900040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
|
||||||
|
0000000000003600000028000000400000003000000001002000000000000030
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000000000FF
|
||||||
|
FF00000000000000000000000000000000000000000000000000000000000000
|
||||||
|
000000FFFF000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
000000000000000000000000000000000000000000000000000000FFFF0000FF
|
||||||
|
FF0000FFFF0000000000000000000000000000000000000000000000000000FF
|
||||||
|
FF0000FFFF0000FFFF0000000000000000000000000000000000FF000000FF00
|
||||||
|
0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00
|
||||||
|
0000FF000000FF000000FF00000000000000000000000000FF000000FF000000
|
||||||
|
FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
|
||||||
|
FF000000FF000000FF000000FF00000000000000000000000000008000000080
|
||||||
|
0000008000000080000000800000008000000080000000800000008000000080
|
||||||
|
00000080000000800000008000000000000000000000007F7F0000FFFF0000FF
|
||||||
|
FF0000FFFF0000FFFF000000000000000000000000000000000000FFFF0000FF
|
||||||
|
FF0000FFFF0000FFFF00007F7F00000000000000000000000000FF000000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FF000000FFFFFF00FF000000FFFFFF00FF000000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FF00000000000000000000000000FF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000FF000000FF00FFFFFF00FFFFFF00FFFFFF000000FF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF000000FF0000000000000000000000000000800000FFFF
|
||||||
|
FF00008000000080000000800000FFFFFF0000800000FFFFFF00008000000080
|
||||||
|
0000FFFFFF000080000000800000000000000000000000FFFF0000FFFF0000FF
|
||||||
|
FF0000FFFF0000FFFF00007F7F000000000000000000007F7F0000FFFF0000FF
|
||||||
|
FF0000FFFF0000FFFF0000FFFF00000000000000000000000000FF000000FFFF
|
||||||
|
FF00FF000000FF000000FF000000FFFFFF00FF000000FFFFFF00FF000000FFFF
|
||||||
|
FF00FF000000FF000000FF00000000000000000000000000FF00FFFFFF000000
|
||||||
|
FF000000FF00FFFFFF000000FF00FFFFFF000000FF000000FF000000FF00FFFF
|
||||||
|
FF000000FF000000FF000000FF0000000000000000000000000000800000FFFF
|
||||||
|
FF00008000000080000000800000FFFFFF0000800000FFFFFF00008000000080
|
||||||
|
0000FFFFFF000080000000800000000000000000000000FFFF0000FFFF0000FF
|
||||||
|
FF0000FFFF0000FFFF0000FFFF00000000000000000000FFFF0000FFFF0000FF
|
||||||
|
FF0000FFFF0000FFFF0000FFFF00000000000000000000000000FF000000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FF000000FF000000FFFFFF00FF000000FF000000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FF00000000000000000000000000FF00FFFFFF000000
|
||||||
|
FF000000FF00FFFFFF000000FF00FFFFFF000000FF000000FF000000FF00FFFF
|
||||||
|
FF000000FF000000FF000000FF0000000000000000000000000000800000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF0000800000FFFFFF00FFFFFF00FFFFFF00008000000080
|
||||||
|
0000FFFFFF000080000000800000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000FF000000FFFF
|
||||||
|
FF00FF000000FF000000FF000000FFFFFF00FF000000FFFFFF00FF000000FFFF
|
||||||
|
FF00FF000000FF000000FF00000000000000000000000000FF00FFFFFF000000
|
||||||
|
FF000000FF00FFFFFF000000FF00FFFFFF000000FF000000FF000000FF00FFFF
|
||||||
|
FF000000FF000000FF000000FF0000000000000000000000000000800000FFFF
|
||||||
|
FF0000800000FFFFFF0000800000FFFFFF0000800000FFFFFF00008000000080
|
||||||
|
0000FFFFFF000080000000800000000000000000000000000000000000000000
|
||||||
|
000000000000000000000000000000FFFF0000FFFF0000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000FF000000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FF000000FFFFFF00FF000000FFFFFF00FF000000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FF00000000000000000000000000FF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000FF000000FF00FFFFFF000000FF000000FF000000FF00FFFF
|
||||||
|
FF000000FF000000FF000000FF0000000000000000000000000000800000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF0000800000FFFFFF00FFFFFF00FFFFFF0000800000FFFF
|
||||||
|
FF00FFFFFF00FFFFFF0000800000000000000000000000000000000000000000
|
||||||
|
000000000000000000000000000000FFFF0000FFFF0000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000FF000000FF00
|
||||||
|
0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00
|
||||||
|
0000FF000000FF000000FF00000000000000000000000000FF000000FF000000
|
||||||
|
FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000
|
||||||
|
FF000000FF000000FF000000FF00000000000000000000000000008000000080
|
||||||
|
0000008000000080000000800000008000000080000000800000008000000080
|
||||||
|
0000008000000080000000800000000000000000000000000000000000000000
|
||||||
|
00000000000000000000007F7F0000FFFF0000FFFF00007F7F00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000FFFF0000FFFF0000FFFF0000FFFF00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF00FFFFFF00FFFFFF00000000000000000000000000000000000000
|
||||||
|
00000000000000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000000000000000000000
|
||||||
|
000000000000007F7F0000FFFF0000FFFF0000FFFF0000FFFF00007F7F000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF0000000000C0C0C000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF0000000000C0C0C000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF0000000000C0C0C000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000080
|
||||||
|
8000000000000000000000000000000000000000000000000000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000000000008080000080
|
||||||
|
8000008080000080800000808000008080000080800000808000008080000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000080
|
||||||
|
8000000000000000000000000000000000000000000000000000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000FFFF00000000000080
|
||||||
|
8000008080000080800000808000008080000080800000808000008080000080
|
||||||
|
8000000000000000000000000000000000000000000000000000008080000080
|
||||||
|
8000000000000000000000000000000000000000000000000000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF0000000000000000000000000000000000FFFFFF0000FFFF000000
|
||||||
|
0000008080000080800000808000008080000080800000808000008080000080
|
||||||
|
8000008080000000000000000000000000000000000000000000008080000080
|
||||||
|
8000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000FFFF00FFFFFF0000FF
|
||||||
|
FF00000000000080800000808000008080000080800000808000008080000080
|
||||||
|
8000008080000080800000000000000000000000000000000000008080000080
|
||||||
|
8000008080000080800000808000008080000080800000808000008080000080
|
||||||
|
8000008080000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF0000000000000000000000000000000000FFFFFF0000FFFF00FFFF
|
||||||
|
FF0000FFFF000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000080
|
||||||
|
8000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000008080000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000FFFF00FFFFFF0000FF
|
||||||
|
FF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000000
|
||||||
|
0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF0000000000000000000000000000000000FFFFFF0000FFFF00FFFF
|
||||||
|
FF0000FFFF00FFFFFF0000FFFF00FFFFFF0000FFFF00FFFFFF00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000000
|
||||||
|
0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||||
|
FF00FFFFFF000000000000000000000000000000000000FFFF00FFFFFF0000FF
|
||||||
|
FF00000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000000
|
||||||
|
0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000000
|
||||||
|
0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0
|
||||||
|
C000000000000080800000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000000000FFFF
|
||||||
|
FF00000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000000
|
||||||
|
0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0
|
||||||
|
C000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000008080000000
|
||||||
|
0000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0C000C0C0
|
||||||
|
C00000000000C0C0C00000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
000000000000000000000000000000000000424D3E000000000000003E000000
|
||||||
|
2800000040000000300000000100010000000000800100000000000000000000
|
||||||
|
000000000000000000000000FFFFFF0000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
00000000000000000000000000000000F81FE000E000E000E007E000E000E000
|
||||||
|
C003E000E000E000800180000000800080018000000080000000800000008000
|
||||||
|
0000800000008000000080000000800000008000000080000000800000008000
|
||||||
|
000080000000800080018000000080008001E000E000E000C003E000E000E000
|
||||||
|
E007E001E001E001F81FE003E003E003FFFFFFFFFFFFFFFFFFFFFFFFC001FFFF
|
||||||
|
E003001F8001FFFFE003000F8001FFFFE00300078001FDFFE00300038001FCFF
|
||||||
|
E00300018001FC7FE00300008001FC3FE003001F8001FC1FE003001F8001FC3F
|
||||||
|
E003001F8001FC7FE0038FF18001FCFFE007FFF98001FDFFE00FFF758001FFFF
|
||||||
|
E01FFF8F8001FFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000
|
||||||
|
000000000000}
|
||||||
|
end
|
||||||
|
object dlgSaveExe: TSaveDialog
|
||||||
|
DefaultExt = '.exe'
|
||||||
|
Filter = 'Executable files (*.exe)|*.exe|All files (*.*)|*.*'
|
||||||
|
Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofNoReadOnlyReturn, ofNoDereferenceLinks, ofEnableSizing, ofDontAddToRecent]
|
||||||
|
Left = 384
|
||||||
|
Top = 56
|
||||||
|
end
|
||||||
|
object dlgSaveDLL: TSaveDialog
|
||||||
|
DefaultExt = '.dll'
|
||||||
|
Filter = 'DLL files (*.dll)|*.dll|All files (*.*)|*.*'
|
||||||
|
Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofNoReadOnlyReturn, ofNoDereferenceLinks, ofEnableSizing, ofDontAddToRecent]
|
||||||
|
Left = 416
|
||||||
|
Top = 56
|
||||||
|
end
|
||||||
|
object dlgSavePAT: TSaveDialog
|
||||||
|
DefaultExt = '.pat'
|
||||||
|
Filter = 'Patch files (*.pat)|*.pat|All files (*.*)|*.*'
|
||||||
|
Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofNoReadOnlyReturn, ofNoDereferenceLinks, ofEnableSizing, ofDontAddToRecent]
|
||||||
|
Left = 448
|
||||||
|
Top = 56
|
||||||
|
end
|
||||||
|
end
|
539
Contrib/VPatch/Source/GUI/MainForm.pas
Normal file
539
Contrib/VPatch/Source/GUI/MainForm.pas
Normal file
|
@ -0,0 +1,539 @@
|
||||||
|
unit MainForm;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||||
|
Dialogs, Buttons, StdCtrls, Menus, PatchClasses, VirtualTrees, VDSP_CRC,
|
||||||
|
ToolWin, ComCtrls, ImgList, ExtCtrls, PatchGenerator, Math;
|
||||||
|
|
||||||
|
const
|
||||||
|
UntitledFile='Untitled.vpj';
|
||||||
|
|
||||||
|
type
|
||||||
|
TfrmMain = class(TForm)
|
||||||
|
MainMenu: TMainMenu;
|
||||||
|
mnuFile: TMenuItem;
|
||||||
|
mnuNew: TMenuItem;
|
||||||
|
mnuOpen: TMenuItem;
|
||||||
|
mnuSave: TMenuItem;
|
||||||
|
mnuSaveas: TMenuItem;
|
||||||
|
N1: TMenuItem;
|
||||||
|
mnuExit: TMenuItem;
|
||||||
|
Label1: TLabel;
|
||||||
|
grpConfig: TGroupBox;
|
||||||
|
butAdd: TSpeedButton;
|
||||||
|
OD: TOpenDialog;
|
||||||
|
Label2: TLabel;
|
||||||
|
txtNew: TEdit;
|
||||||
|
Label3: TLabel;
|
||||||
|
mnuHelp: TMenuItem;
|
||||||
|
mnuAbout: TMenuItem;
|
||||||
|
lstOld: TListBox;
|
||||||
|
butOldAdd: TSpeedButton;
|
||||||
|
butOldRemove: TSpeedButton;
|
||||||
|
butNewEdit: TSpeedButton;
|
||||||
|
Label4: TLabel;
|
||||||
|
lstNew: TVirtualStringTree;
|
||||||
|
dlgOpen: TOpenDialog;
|
||||||
|
dlgSave: TSaveDialog;
|
||||||
|
IL: TImageList;
|
||||||
|
mnuAction: TMenuItem;
|
||||||
|
mnuGenGo: TMenuItem;
|
||||||
|
barTool: TToolBar;
|
||||||
|
toolNew: TToolButton;
|
||||||
|
toolOpen: TToolButton;
|
||||||
|
toolSave: TToolButton;
|
||||||
|
toolGenGo: TToolButton;
|
||||||
|
mnuCreateEXE: TMenuItem;
|
||||||
|
dlgSaveExe: TSaveDialog;
|
||||||
|
toolCreateEXE: TToolButton;
|
||||||
|
barCool: TCoolBar;
|
||||||
|
Label5: TLabel;
|
||||||
|
Label6: TLabel;
|
||||||
|
txtMinimumBlockSize: TEdit;
|
||||||
|
UDMinimumBlockSize: TUpDown;
|
||||||
|
UDBlockDivider: TUpDown;
|
||||||
|
txtBlockDivider: TEdit;
|
||||||
|
Label7: TLabel;
|
||||||
|
UDStepSize: TUpDown;
|
||||||
|
txtStepSize: TEdit;
|
||||||
|
Label8: TLabel;
|
||||||
|
chkDebug: TCheckBox;
|
||||||
|
tbBlockSize: TTrackBar;
|
||||||
|
txtStartBlockSize: TLabel;
|
||||||
|
mnuClearcachedpatches: TMenuItem;
|
||||||
|
mnuCreateDLL: TMenuItem;
|
||||||
|
mnuCreatePAT: TMenuItem;
|
||||||
|
toolCreateDLL: TToolButton;
|
||||||
|
ToolButton1: TToolButton;
|
||||||
|
toolCreatePAT: TToolButton;
|
||||||
|
dlgSaveDLL: TSaveDialog;
|
||||||
|
dlgSavePAT: TSaveDialog;
|
||||||
|
procedure butAddClick(Sender: TObject);
|
||||||
|
procedure FormCreate(Sender: TObject);
|
||||||
|
procedure FormDestroy(Sender: TObject);
|
||||||
|
procedure mnuExitClick(Sender: TObject);
|
||||||
|
procedure UpdateStates;
|
||||||
|
procedure ReloadNewTree;
|
||||||
|
procedure SelectInNewTree(PatchIndex: Integer);
|
||||||
|
procedure butNewEditClick(Sender: TObject);
|
||||||
|
procedure lstNewChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||||
|
procedure butOldAddClick(Sender: TObject);
|
||||||
|
procedure butOldRemoveClick(Sender: TObject);
|
||||||
|
procedure mnuNewClick(Sender: TObject);
|
||||||
|
procedure mnuOpenClick(Sender: TObject);
|
||||||
|
procedure mnuSaveClick(Sender: TObject);
|
||||||
|
procedure mnuSaveasClick(Sender: TObject);
|
||||||
|
procedure mnuGenGoClick(Sender: TObject);
|
||||||
|
procedure mnuAboutClick(Sender: TObject);
|
||||||
|
procedure mnuCreateEXEClick(Sender: TObject);
|
||||||
|
procedure lstNewGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||||
|
Column: TColumnIndex; TextType: TVSTTextType;
|
||||||
|
var CellText: WideString);
|
||||||
|
procedure txtStartBlockSizeChange(Sender: TObject);
|
||||||
|
procedure txtMinimumBlockSizeChange(Sender: TObject);
|
||||||
|
procedure txtBlockDividerChange(Sender: TObject);
|
||||||
|
procedure txtStepSizeChange(Sender: TObject);
|
||||||
|
procedure chkDebugClick(Sender: TObject);
|
||||||
|
procedure tbBlockSizeChange(Sender: TObject);
|
||||||
|
procedure mnuClearcachedpatchesClick(Sender: TObject);
|
||||||
|
procedure mnuCreateDLLClick(Sender: TObject);
|
||||||
|
procedure mnuCreatePATClick(Sender: TObject);
|
||||||
|
private
|
||||||
|
{ Private declarations }
|
||||||
|
// MS: TModeSelector;
|
||||||
|
dskName: String;
|
||||||
|
function DoSave(const FileName: String; const Prompt: Boolean): String;
|
||||||
|
procedure OpenAFile(FileName: String; AskSave: Boolean=True; PromptNew: Boolean=False);
|
||||||
|
function CollectConfig: String;
|
||||||
|
procedure SetConfigTextBoxes(Config: String);
|
||||||
|
procedure PrintDebug(S: String);
|
||||||
|
public
|
||||||
|
{ Public declarations }
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
frmMain: TfrmMain;
|
||||||
|
PP: TPatchProject = nil;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses AboutForm;
|
||||||
|
|
||||||
|
{$R *.dfm}
|
||||||
|
|
||||||
|
procedure TfrmMain.butAddClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
OD.Options:=OD.Options-[ofAllowMultiSelect];
|
||||||
|
OD.Title:='Open the latest (new) version of a file...';
|
||||||
|
OD.FileName:='';
|
||||||
|
if OD.Execute then begin
|
||||||
|
PP.AddNewVersion(OD.FileName);
|
||||||
|
ReloadNewTree;
|
||||||
|
SelectInNewTree(PP.PatchFile(OD.FileName).Index);
|
||||||
|
butOldAdd.Click;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.FormCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
grpConfig.Tag:=-1;
|
||||||
|
dskName:=UntitledFile;
|
||||||
|
lstNew.NodeDataSize:=SizeOf(Integer);
|
||||||
|
OpenAFile('',False,False); //don't prompt for New! that'll bug things
|
||||||
|
ReloadNewTree;
|
||||||
|
UpdateStates;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.FormDestroy(Sender: TObject);
|
||||||
|
begin
|
||||||
|
PP.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuExitClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
Close;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.UpdateStates;
|
||||||
|
begin
|
||||||
|
Self.Caption:='VG - VPatch GUI - '+dskName;
|
||||||
|
// grpConfig.Enabled:=not (lstNew.Tag=-1);
|
||||||
|
// if not grpConfig.Enabled then grpConfig.Caption:='Select a file first';
|
||||||
|
grpConfig.Enabled:=(lstNew.SelectedCount>0);
|
||||||
|
if grpConfig.Tag=-1 then begin
|
||||||
|
txtNew.Enabled:=False;
|
||||||
|
butNewEdit.Enabled:=False;
|
||||||
|
butNewEdit.Font.Color:=clInactiveCaption;
|
||||||
|
butOldAdd.Enabled:=False;
|
||||||
|
butOldAdd.Font.Color:=clInactiveCaption;
|
||||||
|
butOldRemove.Enabled:=False;
|
||||||
|
butOldRemove.Font.Color:=clInactiveCaption;
|
||||||
|
end else begin
|
||||||
|
txtNew.Enabled:=True;
|
||||||
|
butNewEdit.Enabled:=True;
|
||||||
|
butNewEdit.Font.Color:=clWindowText;
|
||||||
|
butOldAdd.Enabled:=True;
|
||||||
|
butOldAdd.Font.Color:=clWindowText;
|
||||||
|
// butOldEdit.Enabled:=True;
|
||||||
|
butOldRemove.Enabled:=True;
|
||||||
|
butOldRemove.Font.Color:=clWindowText;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.ReloadNewTree;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
Node: PVirtualNode;
|
||||||
|
begin
|
||||||
|
lstNew.BeginUpdate;
|
||||||
|
lstNew.Clear;
|
||||||
|
for i:=0 to PP.GetPatchCount - 1 do begin
|
||||||
|
Node:=lstNew.AddChild(nil);
|
||||||
|
PInteger(lstNew.GetNodeData(Node))^:=i;
|
||||||
|
end;
|
||||||
|
lstNew.EndUpdate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.butNewEditClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
OD.Options:=OD.Options-[ofAllowMultiSelect];
|
||||||
|
OD.Title:='Select new version of file...';
|
||||||
|
OD.FileName:=txtNew.Text;
|
||||||
|
if OD.Execute then begin
|
||||||
|
i:=grpConfig.Tag;
|
||||||
|
PP.PatchFile(i).NewVersion:=OD.FileName;
|
||||||
|
ReloadNewTree;
|
||||||
|
lstNew.Selected[lstNew.GetFirstVisible]:=True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.lstNewChange(Sender: TBaseVirtualTree;
|
||||||
|
Node: PVirtualNode);
|
||||||
|
var
|
||||||
|
i,j: Integer;
|
||||||
|
begin
|
||||||
|
case lstNew.SelectedCount of
|
||||||
|
0: Exit;
|
||||||
|
1: begin
|
||||||
|
if lstNew.Selected[Node] then begin
|
||||||
|
i:=PInteger(lstNew.GetNodeData(Node))^;
|
||||||
|
grpConfig.Caption:=ExtractFileName(PP.PatchFile(i).NewVersion);
|
||||||
|
grpConfig.Tag:=i;
|
||||||
|
txtNew.Text:=PP.PatchFile(i).NewVersion;
|
||||||
|
lstOld.Clear;
|
||||||
|
for j:=0 to PP.PatchFile(i).OldVersionCount - 1 do begin
|
||||||
|
lstOld.Items.Add(PP.PatchFile(i).OldVersions[j]);
|
||||||
|
end;
|
||||||
|
SetConfigTextBoxes(PP.PatchFile(i).Config);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else begin
|
||||||
|
grpConfig.Tag:=-1; //multiple files selected - only allow config changes
|
||||||
|
txtNew.Text:='(multiple files selected)';
|
||||||
|
lstOld.Clear;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
UpdateStates;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.butOldAddClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
i,j: Integer;
|
||||||
|
begin
|
||||||
|
OD.Options:=OD.Options+[ofAllowMultiSelect];
|
||||||
|
OD.Title:='Select old versions of '+grpConfig.Caption+'...';
|
||||||
|
OD.FileName:='';
|
||||||
|
if OD.Execute then begin
|
||||||
|
i:=grpConfig.Tag;
|
||||||
|
for j:=0 to OD.Files.Count - 1 do begin
|
||||||
|
PP.PatchFile(i).AddOldVersion(OD.Files[j]);
|
||||||
|
lstOld.Items.Add(OD.Files.Strings[j]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.SelectInNewTree(PatchIndex: Integer);
|
||||||
|
var
|
||||||
|
Node: PVirtualNode;
|
||||||
|
begin
|
||||||
|
Node:=lstNew.GetFirstSelected;
|
||||||
|
while Node<>nil do begin
|
||||||
|
lstNew.Selected[Node]:=False;
|
||||||
|
Node:=lstNew.GetNextSelected(Node);
|
||||||
|
end;
|
||||||
|
Node:=lstNew.GetFirst;
|
||||||
|
while Node<>nil do begin
|
||||||
|
if PInteger(lstNew.GetNodeData(Node))^=PatchIndex then begin
|
||||||
|
lstNew.Selected[Node]:=True;
|
||||||
|
lstNewChange(lstNew,Node);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
Node:=lstNew.GetNext(Node);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.butOldRemoveClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if lstOld.ItemIndex>=0 then begin
|
||||||
|
PP.PatchFile(grpConfig.Tag).RemoveOldVersion(lstOld.ItemIndex);
|
||||||
|
lstOld.Items.Delete(lstOld.ItemIndex);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.OpenAFile(FileName: String; AskSave: Boolean=True; PromptNew: Boolean=False);
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
PP.Free; //confirm saving first?
|
||||||
|
PP:=TPatchProject.Create;
|
||||||
|
ReloadNewTree;
|
||||||
|
if FileName<>'' then begin
|
||||||
|
fs:=nil;
|
||||||
|
try
|
||||||
|
fs:=TFileStream.Create(FileName,fmOpenRead);
|
||||||
|
PP.LoadFromStream(fs);
|
||||||
|
finally
|
||||||
|
dskName:=FileName;
|
||||||
|
ReloadNewTree;
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
dskName:=UntitledFile;
|
||||||
|
if PromptNew then butAddClick(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
UpdateStates;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuNewClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
OpenAFile('',True,True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuOpenClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if dlgOpen.Execute then begin
|
||||||
|
OpenAFile(dlgOpen.FileName,True);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuSaveClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
dskName:=DoSave(dskName,False);
|
||||||
|
UpdateStates;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuSaveasClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
dskName:=DoSave(dskName,True);
|
||||||
|
UpdateStates;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TfrmMain.DoSave(const FileName: String; const Prompt: Boolean): String;
|
||||||
|
var
|
||||||
|
FN: String;
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
DoSave:='';
|
||||||
|
FN:=FileName;
|
||||||
|
if Prompt or (CompareText(FileName,UntitledFile)=0) then begin
|
||||||
|
if dlgSave.Execute then begin
|
||||||
|
FN:=dlgSave.FileName;
|
||||||
|
if ExtractFileExt(FN)='' then
|
||||||
|
FN:=FN+'.vpj';
|
||||||
|
end else begin
|
||||||
|
DoSave:=FileName;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
//do actual saving to this file...
|
||||||
|
fs:=TFileStream.Create(FN,fmCreate);
|
||||||
|
PP.SaveToStream(fs);
|
||||||
|
fs.Free;
|
||||||
|
DoSave:=FN;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuGenGoClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
Self.Visible:=False;
|
||||||
|
Cursor:=crHourGlass;
|
||||||
|
PP.Generate;
|
||||||
|
Cursor:=crDefault;
|
||||||
|
Self.Visible:=True;
|
||||||
|
SelectInNewTree(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuAboutClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
frmAbout: TfrmAbout;
|
||||||
|
begin
|
||||||
|
frmAbout:=TfrmAbout.Create(Self);
|
||||||
|
frmAbout.ShowModal;
|
||||||
|
frmAbout.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuCreateEXEClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
fr: TFileStream;
|
||||||
|
begin
|
||||||
|
//first, select it on disk (where should the exe go?)
|
||||||
|
if dlgSaveExe.FileName='' then dlgSaveExe.FileName:='VPatch.exe';
|
||||||
|
if dlgSaveExe.Execute then begin
|
||||||
|
fs:=nil;
|
||||||
|
try
|
||||||
|
fs:=TFileStream.Create(dlgSaveExe.FileName,fmCreate);
|
||||||
|
fr:=nil;
|
||||||
|
try
|
||||||
|
fr:=TFileStream.Create(ExtractFilePath(Application.ExeName)+'vpatch.bin',fmOpenRead);
|
||||||
|
fs.CopyFrom(fr,fr.Size);
|
||||||
|
finally
|
||||||
|
fr.Free;
|
||||||
|
end;
|
||||||
|
PP.WritePatches(fs);
|
||||||
|
finally
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuCreateDLLClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
fr: TFileStream;
|
||||||
|
begin
|
||||||
|
//first, select it on disk (where should the exe go?)
|
||||||
|
if dlgSaveDLL.FileName='' then dlgSaveDLL.FileName:='VPatch.DLL';
|
||||||
|
if dlgSaveDLL.Execute then begin
|
||||||
|
fs:=nil;
|
||||||
|
try
|
||||||
|
fs:=TFileStream.Create(dlgSaveDLL.FileName,fmCreate);
|
||||||
|
fr:=nil;
|
||||||
|
try
|
||||||
|
fr:=TFileStream.Create(ExtractFilePath(Application.ExeName)+'vpatchdll.bin',fmOpenRead);
|
||||||
|
fs.CopyFrom(fr,fr.Size);
|
||||||
|
finally
|
||||||
|
fr.Free;
|
||||||
|
end;
|
||||||
|
PP.WritePatches(fs);
|
||||||
|
finally
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuCreatePATClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
//first, select it on disk (where should the exe go?)
|
||||||
|
if dlgSavePAT.FileName='' then dlgSavePAT.FileName:='PatchData.pat';
|
||||||
|
if dlgSavePAT.Execute then begin
|
||||||
|
fs:=nil;
|
||||||
|
try
|
||||||
|
fs:=TFileStream.Create(dlgSavePAT.FileName,fmCreate);
|
||||||
|
PP.WritePatches(fs);
|
||||||
|
finally
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.lstNewGetText(Sender: TBaseVirtualTree;
|
||||||
|
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
|
||||||
|
var CellText: WideString);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
i:=PInteger(lstNew.GetNodeData(Node))^;
|
||||||
|
CellText:=ExtractFileName(PP.PatchFile(i).NewVersion);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.txtStartBlockSizeChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TfrmMain.CollectConfig: String;
|
||||||
|
begin
|
||||||
|
Result:=txtStartBlockSize.Caption+','+txtMinimumBlockSize.Text+','+txtBlockDivider.Text+','+txtStepSize.Text;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.txtMinimumBlockSizeChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.txtBlockDividerChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.txtStepSizeChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.SetConfigTextBoxes(Config: String);
|
||||||
|
var
|
||||||
|
a,i: Integer;
|
||||||
|
begin
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
txtStartBlockSize.Caption:=Copy(Config,1,a-1);
|
||||||
|
Config:=Copy(Config,a+1,Length(Config));
|
||||||
|
|
||||||
|
a:=StrToInt(txtStartBlockSize.Caption);
|
||||||
|
i:=-1;
|
||||||
|
while not (a=0) do begin
|
||||||
|
a:=a shr 1;
|
||||||
|
Inc(i);
|
||||||
|
end;
|
||||||
|
tbBlockSize.Position := i;
|
||||||
|
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
txtMinimumBlockSize.Text:=Copy(Config,1,a-1);
|
||||||
|
Config:=Copy(Config,a+1,Length(Config));
|
||||||
|
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
txtBlockDivider.Text:=Copy(Config,1,a-1);
|
||||||
|
Config:=Copy(Config,a+1,Length(Config));
|
||||||
|
|
||||||
|
a:=Pos(',',Config);
|
||||||
|
if(a=0) then a:=Length(Config)+1;
|
||||||
|
txtStepSize.Text:=Copy(Config,1,a-1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.chkDebugClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if chkDebug.State = cbUnchecked then
|
||||||
|
PatchGenerator.DebugEvent:=nil
|
||||||
|
else
|
||||||
|
PatchGenerator.DebugEvent:=PrintDebug;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.PrintDebug(S: String);
|
||||||
|
begin
|
||||||
|
WriteLn(S);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.tbBlockSizeChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
txtStartBlockSize.Caption:=IntToStr(1 shl tbBlockSize.Position);
|
||||||
|
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.mnuClearcachedpatchesClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
PP.ResetCache;
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
PP:=TPatchProject.Create;
|
||||||
|
end.
|
548
Contrib/VPatch/Source/GUI/PatchClasses.pas
Normal file
548
Contrib/VPatch/Source/GUI/PatchClasses.pas
Normal file
|
@ -0,0 +1,548 @@
|
||||||
|
unit PatchClasses;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses Classes, sysutils, VDSP_CRC, DLLWrapper, Dialogs;
|
||||||
|
|
||||||
|
const
|
||||||
|
DEFAULT_CONFIG = '64,64,2,32';
|
||||||
|
|
||||||
|
type
|
||||||
|
TAbstractFile = record
|
||||||
|
FileName: String;
|
||||||
|
FriendlyName: String;
|
||||||
|
CRC32: LongWord; //the longword/integer sign is going to give problems again...
|
||||||
|
Size: Integer;
|
||||||
|
//not sure about this one yet...
|
||||||
|
Cached: Boolean; //True: we have cached the patch, using latest config
|
||||||
|
//False: a) we have nothing cached (size and start are -1)
|
||||||
|
// b) we still have cache (start>0 and size too), but it's not generated using the latest config (we can keep it of course because the new config might be worse)
|
||||||
|
Cache: TMemoryStream;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TPatchFile = class (TObject)
|
||||||
|
private
|
||||||
|
FIndex: Integer;
|
||||||
|
ConfigID: String;
|
||||||
|
FNew: TAbstractFile;
|
||||||
|
FOld: Array of TAbstractFile;
|
||||||
|
protected
|
||||||
|
procedure SetNewFN(Value: String);
|
||||||
|
function GetNewFN: String;
|
||||||
|
procedure SetOldFN(i: Integer; FileName: String);
|
||||||
|
function GetOldFN(Index: Integer): String;
|
||||||
|
function GetOldVersionCount: Integer;
|
||||||
|
procedure ResetCache; overload;
|
||||||
|
procedure ResetCache(OldIndex: Integer); overload;
|
||||||
|
procedure InvalidateCache; overload;
|
||||||
|
procedure InvalidateCache(Index: Integer); overload;
|
||||||
|
function GetCached(Index: Integer): Boolean;
|
||||||
|
function GetConfig: String;
|
||||||
|
procedure SetConfig(Value: String);
|
||||||
|
public
|
||||||
|
constructor Create(Index: Integer; FileName: String); overload;
|
||||||
|
constructor Create(Index: Integer; Stream: TStream); overload;
|
||||||
|
destructor Destroy(); override;
|
||||||
|
|
||||||
|
procedure AddOldVersion(const FileName: String);
|
||||||
|
procedure RemoveOldVersion(const Index: Integer);
|
||||||
|
property OldVersions[Index: Integer]: String read GetOldFN write SetOldFN;
|
||||||
|
|
||||||
|
procedure Generate; overload;
|
||||||
|
procedure Generate(const Index: Integer); overload;
|
||||||
|
property Generated[Index: Integer]: Boolean read GetCached;
|
||||||
|
function GetPatchSize(Index: Integer): Integer;
|
||||||
|
|
||||||
|
procedure WritePatch(Index: Integer; Stream: TStream);
|
||||||
|
|
||||||
|
// LoadFromStream not supported: Use Create(Index,Stream) instead!
|
||||||
|
// procedure LoadFromStream(Stream: TStream);
|
||||||
|
procedure SaveToStream(Stream: TStream);
|
||||||
|
published
|
||||||
|
property NewVersion: String read GetNewFN write SetNewFN;
|
||||||
|
property OldVersionCount: Integer read GetOldVersionCount;
|
||||||
|
property Index: Integer read FIndex;
|
||||||
|
property Config: String read GetConfig write SetConfig;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TPatchProject = class (TObject)
|
||||||
|
private
|
||||||
|
FPat: Array of TPatchFile;
|
||||||
|
public
|
||||||
|
procedure LoadFromStream(Stream: TStream);
|
||||||
|
procedure SaveToStream(Stream: TStream);
|
||||||
|
constructor Create();
|
||||||
|
destructor Destroy(); override;
|
||||||
|
procedure AddNewVersion(FileName: String);
|
||||||
|
function PatchFile(FileName: String): TPatchFile; overload;
|
||||||
|
function PatchFile(Index: Integer): TPatchFile; overload;
|
||||||
|
function GetPatchCount: Integer;
|
||||||
|
procedure WritePatches(Stream: TStream);
|
||||||
|
procedure Generate;
|
||||||
|
procedure ResetCache;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function ReadStreamString(Stream: TStream): String;
|
||||||
|
var
|
||||||
|
Buf: Array[0..512] of Char;
|
||||||
|
i: LongInt;
|
||||||
|
S: String;
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
if i>512 then raise Exception.Create('VPJ damaged: String too long (>512)');
|
||||||
|
Stream.Read(Buf,i);
|
||||||
|
for j:=1 to i do
|
||||||
|
S:=S+Buf[j-1];
|
||||||
|
ReadStreamString:=S;
|
||||||
|
end;
|
||||||
|
|
||||||
|
//a private wrapper for the FileCRC function
|
||||||
|
function CalcCRC(FileName: String): Integer;
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
CalcCRC:=0;
|
||||||
|
fs:=nil;
|
||||||
|
try
|
||||||
|
fs:=TFileStream.Create(FileName,fmOpenRead);
|
||||||
|
CalcCRC:=FileCRC(fs);
|
||||||
|
finally
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetFileSize(FileName: String): Integer;
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
GetFileSize:=0;
|
||||||
|
fs:=nil;
|
||||||
|
try
|
||||||
|
fs:=TFileStream.Create(FileName,fmOpenRead);
|
||||||
|
GetFileSize:=fs.Size;
|
||||||
|
finally
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPatchFile }
|
||||||
|
|
||||||
|
procedure TPatchFile.AddOldVersion(const FileName: String);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
// fs: TFileStream;
|
||||||
|
begin
|
||||||
|
i:=Length(FOld);
|
||||||
|
SetLength(FOld,i+1);
|
||||||
|
FOld[i].Cache:=TMemoryStream.Create;
|
||||||
|
SetOldFN(i,FileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TPatchFile.Create(Index: Integer; FileName: String);
|
||||||
|
//var
|
||||||
|
// fs: TFileStream;
|
||||||
|
begin
|
||||||
|
inherited Create();
|
||||||
|
FIndex:=Index;
|
||||||
|
SetLength(FOld,0);
|
||||||
|
FNew.CRC32:=0;
|
||||||
|
FNew.Size:=-1;
|
||||||
|
SetNewFN(FileName);
|
||||||
|
ConfigID:=DEFAULT_CONFIG;
|
||||||
|
//just to be on the safe side
|
||||||
|
//following is now done by SetNewFN :)
|
||||||
|
//no it's not - because that one resets the cache!!!
|
||||||
|
//doesn't matter, because we're not loading from stream!!!
|
||||||
|
{ FNew.FileName:=FileName;
|
||||||
|
FNew.FriendlyName:=ExtractFileName(FileName);
|
||||||
|
FNew.CRC32:=CalcCRC(FileName);
|
||||||
|
FNew.Size:=GetFileSize(FileName);}
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TPatchFile.Create(Index: Integer; Stream: TStream);
|
||||||
|
var
|
||||||
|
i,q: LongInt;
|
||||||
|
CSize: Integer;
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
inherited Create();
|
||||||
|
FIndex:=Index;
|
||||||
|
SetLength(FOld,0);
|
||||||
|
FNew.CRC32:=0;
|
||||||
|
FNew.Size:=-1; //just to be on the safe side
|
||||||
|
|
||||||
|
//read configuration
|
||||||
|
ConfigID:=ReadStreamString(Stream);
|
||||||
|
|
||||||
|
//now load everything...
|
||||||
|
FNew.FileName:=ReadStreamString(Stream);
|
||||||
|
FNew.FriendlyName:=ReadStreamString(Stream);
|
||||||
|
Stream.Read(FNew.CRC32,SizeOf(FNew.CRC32));
|
||||||
|
Stream.Read(FNew.Size,SizeOf(FNew.Size));
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
SetLength(FOld,i);
|
||||||
|
for j:=0 to i - 1 do begin
|
||||||
|
FOld[j].FileName:=ReadStreamString(Stream);
|
||||||
|
FOld[j].FriendlyName:=ReadStreamString(Stream);
|
||||||
|
Stream.Read(FOld[j].CRC32,SizeOf(FOld[j].CRC32));
|
||||||
|
Stream.Read(FOld[j].Size,SizeOf(FOld[j].Size));
|
||||||
|
Stream.Read(q,SizeOf(q));
|
||||||
|
FOld[j].Cached:=not (q=0);
|
||||||
|
if FOld[j].Cached then begin
|
||||||
|
Stream.Read(CSize,SizeOf(CSize));
|
||||||
|
FOld[j].Cache:=TMemoryStream.Create;
|
||||||
|
FOld[j].Cache.CopyFrom(Stream,CSize);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TPatchFile.Destroy;
|
||||||
|
begin
|
||||||
|
SetLength(FOld,0);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchFile.GetNewFN: String;
|
||||||
|
begin
|
||||||
|
GetNewFN:=FNew.FileName;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchFile.GetOldFN(Index: Integer): String;
|
||||||
|
begin
|
||||||
|
Result:=FOld[Index].FileName;
|
||||||
|
if FOld[Index].Cached then
|
||||||
|
if FOld[Index].Cache.Size>0 then begin
|
||||||
|
Result:=Result + ' ('+IntToStr(FOld[Index].Cache.Size)+' bytes)';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchFile.GetOldVersionCount: Integer;
|
||||||
|
begin
|
||||||
|
GetOldVersionCount:=Length(FOld);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.ResetCache;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to Length(FOld)-1 do
|
||||||
|
ResetCache(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.RemoveOldVersion(const Index: Integer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
FOld[Index].Cache.Free;
|
||||||
|
for i:=Index to Length(FOld)-2 do begin
|
||||||
|
FOld[i]:=FOld[i+1];
|
||||||
|
end;
|
||||||
|
SetLength(FOld,Length(FOld)-1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.ResetCache(OldIndex: Integer);
|
||||||
|
begin
|
||||||
|
FOld[OldIndex].Cached:=False;
|
||||||
|
FOld[OldIndex].Size:=-1;
|
||||||
|
FOld[OldIndex].Cache.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.SaveToStream(Stream: TStream);
|
||||||
|
procedure WriteStreamString(Stream: TStream; const S: String);
|
||||||
|
var
|
||||||
|
i: LongInt;
|
||||||
|
j: Integer;
|
||||||
|
Buf: Array[0..512] of Char;
|
||||||
|
begin
|
||||||
|
i:=Length(S);
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
for j:=1 to i do
|
||||||
|
Buf[j-1]:=S[j];
|
||||||
|
Buf[i]:=#0;
|
||||||
|
Stream.Write(Buf,i);
|
||||||
|
end;
|
||||||
|
var
|
||||||
|
i,q: LongInt;
|
||||||
|
j: Integer;
|
||||||
|
tmp: Integer;
|
||||||
|
begin
|
||||||
|
//write config ID
|
||||||
|
WriteStreamString(Stream,ConfigID);
|
||||||
|
|
||||||
|
WriteStreamString(Stream,FNew.FileName);
|
||||||
|
WriteStreamString(Stream,FNew.FriendlyName);
|
||||||
|
Stream.Write(FNew.CRC32,SizeOf(FNew.CRC32));
|
||||||
|
Stream.Write(FNew.Size,SizeOf(FNew.Size));
|
||||||
|
|
||||||
|
i:=Length(FOld);
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
|
||||||
|
for j:=0 to i - 1 do begin
|
||||||
|
WriteStreamString(Stream,FOld[j].FileName);
|
||||||
|
WriteStreamString(Stream,FOld[j].FriendlyName);
|
||||||
|
Stream.Write(FOld[j].CRC32,SizeOf(FOld[j].CRC32));
|
||||||
|
Stream.Write(FOld[j].Size,SizeOf(FOld[j].Size));
|
||||||
|
if FOld[j].Cached then q:=1 else q:=0;
|
||||||
|
Stream.Write(q,SizeOf(q));
|
||||||
|
if FOld[j].Cached then begin
|
||||||
|
tmp:=FOld[j].Cache.Size;
|
||||||
|
Stream.Write(tmp,SizeOf(tmp));
|
||||||
|
FOld[j].Cache.Seek(0,soFromBeginning);
|
||||||
|
Stream.CopyFrom(FOld[j].Cache,tmp);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.SetNewFN(Value: String);
|
||||||
|
var
|
||||||
|
NewSize: Integer;
|
||||||
|
NewCRC: LongWord;
|
||||||
|
begin
|
||||||
|
FNew.FileName:=Value;
|
||||||
|
FNew.Friendlyname:=ExtractFileName(Value);
|
||||||
|
NewCRC:=CalcCRC(Value);
|
||||||
|
NewSize:=GetFileSize(Value);
|
||||||
|
//if any changes, then reset cache :)
|
||||||
|
if not ((FNew.CRC32=NewCRC) and (FNew.Size=NewSize)) then begin
|
||||||
|
FNew.CRC32:=NewCRC;
|
||||||
|
FNew.Size:=NewSize;
|
||||||
|
ResetCache;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.SetOldFN(i: Integer; FileName: String);
|
||||||
|
begin
|
||||||
|
if((i>=0) and (i<Length(FOld))) then begin
|
||||||
|
FOld[i].FileName:=FileName;
|
||||||
|
FOld[i].FriendlyName:=ExtractFileName(FileName);
|
||||||
|
FOld[i].CRC32:=CalcCRC(FileName);
|
||||||
|
FOld[i].Size:=GetFileSize(FileName);
|
||||||
|
ResetCache(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.Generate;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
//generate all of them into the cache?
|
||||||
|
for i:=0 to OldVersionCount - 1 do
|
||||||
|
Generate(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.Generate(const Index: Integer);
|
||||||
|
var
|
||||||
|
Size: Integer;
|
||||||
|
fm: TMemoryStream;
|
||||||
|
begin
|
||||||
|
fm:=TMemoryStream.Create;
|
||||||
|
Size:=DoGenerate(FOld[Index].FileName,FNew.FileName,fm,ConfigID);
|
||||||
|
if not (Size=-1) then begin
|
||||||
|
if (FOld[Index].Cache.Size>Size) or (not FOld[Index].Cached) then begin //the new one is better
|
||||||
|
FOld[Index].Cache.Clear;
|
||||||
|
fm.Seek(8,soFromBeginning);
|
||||||
|
FOld[Index].Cache.CopyFrom(fm,fm.Size-8);
|
||||||
|
end;
|
||||||
|
FOld[Index].Cached:=True;
|
||||||
|
end;
|
||||||
|
fm.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchFile.GetCached(Index: Integer): Boolean;
|
||||||
|
begin
|
||||||
|
GetCached:=FOld[Index].Cached;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchFile.GetConfig: String;
|
||||||
|
begin
|
||||||
|
GetConfig:=ConfigID;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.SetConfig(Value: String);
|
||||||
|
begin
|
||||||
|
if not Assigned(Self) then Exit;
|
||||||
|
if not SameText(Value,ConfigID) then begin
|
||||||
|
InvalidateCache; //configuration changed, invalidate cache
|
||||||
|
end;
|
||||||
|
ConfigID:=Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchFile.GetPatchSize(Index: Integer): Integer;
|
||||||
|
begin
|
||||||
|
if Generated[Index] then begin
|
||||||
|
GetPatchSize:=FOld[Index].Cache.Size;
|
||||||
|
end else
|
||||||
|
GetPatchSize:=-1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.InvalidateCache;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to Length(FOld)-1 do
|
||||||
|
InvalidateCache(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.InvalidateCache(Index: Integer);
|
||||||
|
begin
|
||||||
|
FOld[Index].Cached:=False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchFile.WritePatch(Index: Integer; Stream: TStream);
|
||||||
|
begin
|
||||||
|
if not FOld[Index].Cached then
|
||||||
|
Generate(Index);
|
||||||
|
if not FOld[Index].Cached then
|
||||||
|
raise Exception.Create('Writing of patch failed: Could not generate all patches');
|
||||||
|
FOld[Index].Cache.Seek(0,soFromBeginning);
|
||||||
|
Stream.CopyFrom(FOld[Index].Cache,FOld[Index].Cache.Size);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TPatchProject }
|
||||||
|
|
||||||
|
procedure TPatchProject.AddNewVersion(FileName: String);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
i:=Length(FPat);
|
||||||
|
SetLength(FPat,i+1);
|
||||||
|
FPat[i]:=TPatchFile.Create(i,FileName);
|
||||||
|
FPat[i].SetConfig(DEFAULT_CONFIG);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TPatchProject.Create;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
SetLength(FPat,0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TPatchProject.Destroy;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to Length(FPat)-1 do begin
|
||||||
|
FPat[i].Free;
|
||||||
|
end;
|
||||||
|
SetLength(FPat,0);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchProject.Generate;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to GetPatchCount - 1 do
|
||||||
|
FPat[i].Generate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchProject.GetPatchCount: Integer;
|
||||||
|
begin
|
||||||
|
GetPatchCount:=Length(FPat);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchProject.LoadFromStream(Stream: TStream);
|
||||||
|
var
|
||||||
|
i: LongInt;
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
//first free all patchfiles
|
||||||
|
for j:=0 to Length(FPat)-1 do begin
|
||||||
|
FPat[j].Free;
|
||||||
|
FPat[j]:=nil;
|
||||||
|
end;
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
if(i=$1A4A5056) then begin //still read old files
|
||||||
|
Stream.Read(i,SizeOf(i)); //16 dummy bytes
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
|
||||||
|
Stream.Read(i,SizeOf(i));
|
||||||
|
end;
|
||||||
|
SetLength(FPat,i);
|
||||||
|
for j:=0 to i - 1 do begin
|
||||||
|
FPat[j]:=TPatchFile.Create(j,Stream);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchProject.PatchFile(FileName: String): TPatchFile;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
PatchFile:=nil;
|
||||||
|
for i:=0 to Length(FPat) - 1 do begin
|
||||||
|
if(CompareText(FPat[i].FNew.FileName,FileName)=0) then begin
|
||||||
|
PatchFile:=FPat[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
for i:=0 to Length(FPat) - 1 do begin
|
||||||
|
if(CompareText(FPat[i].FNew.FriendlyName,FileName)=0) then begin
|
||||||
|
PatchFile:=FPat[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchProject.PatchFile(Index: Integer): TPatchFile;
|
||||||
|
begin
|
||||||
|
if (Index<Length(FPat)) and (Index>=0) then
|
||||||
|
PatchFile:=FPat[Index]
|
||||||
|
else
|
||||||
|
PatchFile:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchProject.ResetCache;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i:=0 to Pred(Length(FPat)) do
|
||||||
|
FPat[i].ResetCache;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchProject.SaveToStream(Stream: TStream);
|
||||||
|
var
|
||||||
|
HeadID: Array[0..3] of Char;
|
||||||
|
i: LongInt;
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
HeadID:='VPJ'+#26;
|
||||||
|
Stream.Write(HeadID,SizeOf(HeadID));
|
||||||
|
//16 dummy bytes
|
||||||
|
i:=0;
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
i:=Length(FPat);
|
||||||
|
Stream.Write(i,SizeOf(i));
|
||||||
|
for j:=0 to i - 1 do begin
|
||||||
|
FPat[j].SaveToStream(Stream);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchProject.WritePatches(Stream: TStream);
|
||||||
|
var
|
||||||
|
i,j,k,o: LongInt;
|
||||||
|
begin
|
||||||
|
k:=$54415056;
|
||||||
|
o:=Stream.Position;
|
||||||
|
Stream.Write(k,SizeOf(k));
|
||||||
|
k:=0;
|
||||||
|
Stream.Write(k,SizeOf(k));
|
||||||
|
k:=0;
|
||||||
|
for i:=0 to Length(FPat)-1 do begin
|
||||||
|
for j:=0 to FPat[i].GetOldVersionCount - 1 do begin
|
||||||
|
FPat[i].WritePatch(j,Stream);
|
||||||
|
Inc(k);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Stream.Seek(o+4,soFromBeginning);
|
||||||
|
Stream.Write(k,SizeOf(k));
|
||||||
|
Stream.Seek(Stream.Size,soFromBeginning);
|
||||||
|
Stream.Write(o,SizeOf(o));
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
102
Contrib/VPatch/Source/GUI/ProgressForm.dfm
Normal file
102
Contrib/VPatch/Source/GUI/ProgressForm.dfm
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
object frmProg: TfrmProg
|
||||||
|
Left = 328
|
||||||
|
Top = 266
|
||||||
|
BorderIcons = [biSystemMenu, biMinimize]
|
||||||
|
BorderStyle = bsSingle
|
||||||
|
Caption = 'Progress...'
|
||||||
|
ClientHeight = 193
|
||||||
|
ClientWidth = 385
|
||||||
|
Color = clBtnFace
|
||||||
|
Font.Charset = DEFAULT_CHARSET
|
||||||
|
Font.Color = clWindowText
|
||||||
|
Font.Height = -11
|
||||||
|
Font.Name = 'MS Sans Serif'
|
||||||
|
Font.Style = []
|
||||||
|
OldCreateOrder = False
|
||||||
|
Position = poScreenCenter
|
||||||
|
OnCreate = FormCreate
|
||||||
|
PixelsPerInch = 96
|
||||||
|
TextHeight = 13
|
||||||
|
object lblStatus: TLabel
|
||||||
|
Left = 8
|
||||||
|
Top = 8
|
||||||
|
Width = 369
|
||||||
|
Height = 17
|
||||||
|
AutoSize = False
|
||||||
|
Transparent = True
|
||||||
|
end
|
||||||
|
object lblSize: TLabel
|
||||||
|
Left = 152
|
||||||
|
Top = 8
|
||||||
|
Width = 225
|
||||||
|
Height = 17
|
||||||
|
Alignment = taRightJustify
|
||||||
|
AutoSize = False
|
||||||
|
Transparent = True
|
||||||
|
end
|
||||||
|
object lblFile: TLabel
|
||||||
|
Left = 8
|
||||||
|
Top = 48
|
||||||
|
Width = 369
|
||||||
|
Height = 17
|
||||||
|
AutoSize = False
|
||||||
|
Caption = '(filename)'
|
||||||
|
end
|
||||||
|
object lblNewFile: TLabel
|
||||||
|
Left = 8
|
||||||
|
Top = 96
|
||||||
|
Width = 369
|
||||||
|
Height = 17
|
||||||
|
AutoSize = False
|
||||||
|
Caption = '(filename)'
|
||||||
|
end
|
||||||
|
object lblTotal: TLabel
|
||||||
|
Left = 8
|
||||||
|
Top = 144
|
||||||
|
Width = 369
|
||||||
|
Height = 17
|
||||||
|
AutoSize = False
|
||||||
|
Caption = 'Total progress'
|
||||||
|
end
|
||||||
|
object shpFull: TShape
|
||||||
|
Left = 8
|
||||||
|
Top = 24
|
||||||
|
Width = 369
|
||||||
|
Height = 17
|
||||||
|
Brush.Color = clGray
|
||||||
|
end
|
||||||
|
object shpLeft: TShape
|
||||||
|
Left = 8
|
||||||
|
Top = 24
|
||||||
|
Width = 369
|
||||||
|
Height = 17
|
||||||
|
Brush.Color = clRed
|
||||||
|
end
|
||||||
|
object prgFile: TProgressBar
|
||||||
|
Left = 8
|
||||||
|
Top = 64
|
||||||
|
Width = 369
|
||||||
|
Height = 25
|
||||||
|
Min = 0
|
||||||
|
Max = 100
|
||||||
|
TabOrder = 0
|
||||||
|
end
|
||||||
|
object prgNewFile: TProgressBar
|
||||||
|
Left = 8
|
||||||
|
Top = 112
|
||||||
|
Width = 369
|
||||||
|
Height = 25
|
||||||
|
Min = 0
|
||||||
|
Max = 100
|
||||||
|
TabOrder = 1
|
||||||
|
end
|
||||||
|
object prgAll: TProgressBar
|
||||||
|
Left = 8
|
||||||
|
Top = 160
|
||||||
|
Width = 369
|
||||||
|
Height = 25
|
||||||
|
Min = 0
|
||||||
|
Max = 100
|
||||||
|
TabOrder = 2
|
||||||
|
end
|
||||||
|
end
|
74
Contrib/VPatch/Source/GUI/ProgressForm.pas
Normal file
74
Contrib/VPatch/Source/GUI/ProgressForm.pas
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
unit ProgressForm;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||||
|
Dialogs, StdCtrls, ComCtrls, ExtCtrls, Math;
|
||||||
|
|
||||||
|
type
|
||||||
|
TfrmProg = class(TForm)
|
||||||
|
prgFile: TProgressBar;
|
||||||
|
lblFile: TLabel;
|
||||||
|
lblNewFile: TLabel;
|
||||||
|
prgNewFile: TProgressBar;
|
||||||
|
lblTotal: TLabel;
|
||||||
|
prgAll: TProgressBar;
|
||||||
|
lblStatus: TLabel;
|
||||||
|
shpFull: TShape;
|
||||||
|
shpLeft: TShape;
|
||||||
|
lblSize: TLabel;
|
||||||
|
procedure GetStatusProc(S: PChar; Point, Total,
|
||||||
|
CurrentSavings: Integer); stdcall;
|
||||||
|
procedure FormCreate(Sender: TObject);
|
||||||
|
private
|
||||||
|
{ Private declarations }
|
||||||
|
public
|
||||||
|
{ Public declarations }
|
||||||
|
FilePos,FileRange,AllPos,AllRange: Byte;
|
||||||
|
CTotal: Integer;
|
||||||
|
t2: TDateTime;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
frmProg: TfrmProg;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{$R *.dfm}
|
||||||
|
|
||||||
|
procedure TfrmProg.GetStatusProc(S: PChar; Point, Total, CurrentSavings: Integer); stdcall;
|
||||||
|
var
|
||||||
|
a,b: Integer;
|
||||||
|
j: Single;
|
||||||
|
begin
|
||||||
|
if Length(S)>0 then
|
||||||
|
lblStatus.Caption:=S;
|
||||||
|
if (Total<0) then begin
|
||||||
|
Total:=CTotal;
|
||||||
|
if (Now-t2)*24*3600*10<8 then Exit; //update only every 800 milliseconds
|
||||||
|
end;
|
||||||
|
if (Total>=0) then CTotal:=Total;
|
||||||
|
if (Total>=0) and (Point>=0) then begin
|
||||||
|
a:=(Point*100) div Total;
|
||||||
|
prgFile.Position:=a;
|
||||||
|
b:=FilePos+(a*FileRange) div 100;
|
||||||
|
prgNewFile.Position:=b;
|
||||||
|
prgAll.Position:=AllPos+(b*AllRange) div 100;
|
||||||
|
end;
|
||||||
|
if (CurrentSavings>=0) and (Total>=0) then begin
|
||||||
|
j:=(Total-CurrentSavings)*shpFull.Width/Total;
|
||||||
|
shpLeft.Width:=Max(Round(j),3);
|
||||||
|
lblSize.Caption:=IntToStr(Total-CurrentSavings)+' of '+IntToStr(Total)+' ('+IntToStr(CurrentSavings*100 div Total)+'%)';
|
||||||
|
end;
|
||||||
|
Refresh;
|
||||||
|
t2:=Now;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TfrmProg.FormCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FilePos:=0; FileRange:=100; AllPos:=0; AllRange:=100; CTotal:=-1;
|
||||||
|
t2:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
87
Contrib/VPatch/Source/GUI/VPatchGUI.dof
Normal file
87
Contrib/VPatch/Source/GUI/VPatchGUI.dof
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
[FileVersion]
|
||||||
|
Version=6.0
|
||||||
|
[Compiler]
|
||||||
|
A=8
|
||||||
|
B=0
|
||||||
|
C=1
|
||||||
|
D=1
|
||||||
|
E=0
|
||||||
|
F=0
|
||||||
|
G=1
|
||||||
|
H=1
|
||||||
|
I=1
|
||||||
|
J=0
|
||||||
|
K=0
|
||||||
|
L=1
|
||||||
|
M=0
|
||||||
|
N=1
|
||||||
|
O=1
|
||||||
|
P=1
|
||||||
|
Q=0
|
||||||
|
R=0
|
||||||
|
S=0
|
||||||
|
T=0
|
||||||
|
U=0
|
||||||
|
V=1
|
||||||
|
W=0
|
||||||
|
X=1
|
||||||
|
Y=1
|
||||||
|
Z=1
|
||||||
|
ShowHints=1
|
||||||
|
ShowWarnings=1
|
||||||
|
UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
|
||||||
|
[Linker]
|
||||||
|
MapFile=0
|
||||||
|
OutputObjs=0
|
||||||
|
ConsoleApp=0
|
||||||
|
DebugInfo=0
|
||||||
|
RemoteSymbols=0
|
||||||
|
MinStackSize=16384
|
||||||
|
MaxStackSize=1048576
|
||||||
|
ImageBase=4194304
|
||||||
|
ExeDescription=
|
||||||
|
[Directories]
|
||||||
|
OutputDir=
|
||||||
|
UnitOutputDir=
|
||||||
|
PackageDLLOutputDir=
|
||||||
|
PackageDCPOutputDir=
|
||||||
|
SearchPath=
|
||||||
|
Packages=vcl;rtl;dbrtl;adortl;vcldb;vclx;bdertl;vcldbx;ibxpress;dsnap;cds;bdecds;qrpt;teeui;teedb;tee;dss;teeqr;visualclx;visualdbclx;dsnapcrba;dsnapcon;VclSmp;vclshlctrls;vclie;xmlrtl;inet;inetdbbde;inetdbxpress;nmfast;webdsnap;websnap;dbexpress;dbxcds;indy;dclOffice2k;VirtualTreesD6;packageTib;inetdb
|
||||||
|
Conditionals=
|
||||||
|
DebugSourceDirs=
|
||||||
|
UsePackages=0
|
||||||
|
[Parameters]
|
||||||
|
RunParams=
|
||||||
|
HostApplication=
|
||||||
|
Launcher=
|
||||||
|
UseLauncher=0
|
||||||
|
DebugCWD=
|
||||||
|
[Language]
|
||||||
|
ActiveLang=
|
||||||
|
ProjectLang=
|
||||||
|
RootDir=
|
||||||
|
[Version Info]
|
||||||
|
IncludeVerInfo=1
|
||||||
|
AutoIncBuild=1
|
||||||
|
MajorVer=2
|
||||||
|
MinorVer=0
|
||||||
|
Release=0
|
||||||
|
Build=10
|
||||||
|
Debug=0
|
||||||
|
PreRelease=0
|
||||||
|
Special=0
|
||||||
|
Private=0
|
||||||
|
DLL=0
|
||||||
|
Locale=1043
|
||||||
|
CodePage=1252
|
||||||
|
[Version Info Keys]
|
||||||
|
CompanyName=Van de Sande Productions
|
||||||
|
FileDescription=VG - VPatch GUI
|
||||||
|
FileVersion=2.0.0.10
|
||||||
|
InternalName=VPatchGUI
|
||||||
|
LegalCopyright=
|
||||||
|
LegalTrademarks=
|
||||||
|
OriginalFilename=
|
||||||
|
ProductName=
|
||||||
|
ProductVersion=2.0 final
|
||||||
|
Comments=
|
19
Contrib/VPatch/Source/GUI/VPatchGUI.dpr
Normal file
19
Contrib/VPatch/Source/GUI/VPatchGUI.dpr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
program VPatchGUI;
|
||||||
|
|
||||||
|
uses
|
||||||
|
Forms,
|
||||||
|
MainForm in 'MainForm.pas' {frmMain},
|
||||||
|
PatchClasses in 'PatchClasses.pas',
|
||||||
|
VDSP_CRC in '..\VDSP_CRC.pas',
|
||||||
|
DLLWrapper in 'DLLWrapper.pas',
|
||||||
|
AboutForm in 'AboutForm.pas' {frmAbout},
|
||||||
|
PatchGenerator in '..\PatchGenerator.pas',
|
||||||
|
TreeCode in '..\TreeCode.pas';
|
||||||
|
|
||||||
|
{$R *.res}
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application.Initialize;
|
||||||
|
Application.CreateForm(TfrmMain, frmMain);
|
||||||
|
Application.Run;
|
||||||
|
end.
|
BIN
Contrib/VPatch/Source/GUI/VPatchGUI.res
Normal file
BIN
Contrib/VPatch/Source/GUI/VPatchGUI.res
Normal file
Binary file not shown.
125
Contrib/VPatch/Source/GenPat/GenPat2.dpr
Normal file
125
Contrib/VPatch/Source/GenPat/GenPat2.dpr
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
program GenPat2;
|
||||||
|
|
||||||
|
{
|
||||||
|
VPatch 2 - Patch Generator
|
||||||
|
===============================
|
||||||
|
|
||||||
|
(c) 2001-2003 Van de Sande Productions
|
||||||
|
|
||||||
|
This is the main program unit for the commandline version. It implements
|
||||||
|
commandline options (like /b=) and displays help if no options are given.
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
2.0 20030811 Koen Initial documentation
|
||||||
|
}
|
||||||
|
|
||||||
|
{$APPTYPE CONSOLE}
|
||||||
|
uses
|
||||||
|
PatchGenerator in 'PatchGenerator.pas',
|
||||||
|
VDSP_CRC in 'VDSP_CRC.pas',
|
||||||
|
Sysutils,
|
||||||
|
TreeCode in 'TreeCode.pas';
|
||||||
|
|
||||||
|
type
|
||||||
|
TEventHandler = class
|
||||||
|
procedure PrintDebug(S: String);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TEventhandler.PrintDebug(S: String);
|
||||||
|
begin
|
||||||
|
WriteLn(S);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$DEFINE READCONFIG} //try to read genpat.ini?
|
||||||
|
{.$DEFINE AUTOWAIT} //have /wait command line switch on by default?
|
||||||
|
//useful when debugging
|
||||||
|
|
||||||
|
var
|
||||||
|
Config: TextFile;
|
||||||
|
T1,T2: TDateTime;
|
||||||
|
d: Integer;
|
||||||
|
S,Key: String;
|
||||||
|
ShowDebug: Boolean;
|
||||||
|
PG: TPatchGenerator;
|
||||||
|
EV: TEventHandler;
|
||||||
|
begin
|
||||||
|
EV:=TEventHandler.Create;
|
||||||
|
PG:=TPatchGenerator.Create;
|
||||||
|
PG.StartBlockSize:=64;
|
||||||
|
|
||||||
|
WriteLn('GenPat v2.0 final');
|
||||||
|
WriteLn('=================');
|
||||||
|
WriteLn;
|
||||||
|
WriteLn('(c) 2001-2003 Van de Sande Productions');
|
||||||
|
WriteLn('Website: http://www.tibed.net/vpatch');
|
||||||
|
WriteLn('E-mail: koen@tibed.net');
|
||||||
|
WriteLn;
|
||||||
|
ShowDebug:=FindCmdLineSwitch('debug',['/'],True);
|
||||||
|
if ShowDebug then
|
||||||
|
DebugEvent:=EV.PrintDebug;
|
||||||
|
|
||||||
|
{$IFDEF READCONFIG}
|
||||||
|
if FileExists('genpat.ini') then begin
|
||||||
|
AssignFile(Config,'genpat.ini');
|
||||||
|
Reset(Config);
|
||||||
|
while not eof(Config) do begin
|
||||||
|
ReadLn(Config,S);
|
||||||
|
d:=Pos('=',S);
|
||||||
|
if not (d=0) then begin
|
||||||
|
Key:=LowerCase(Copy(S,1,d-1));
|
||||||
|
S:=Copy(S,d+1,Length(S));
|
||||||
|
if CompareStr(Key,'startblocksize')=0 then PG.StartBlockSize:=StrToInt(S);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
CloseFile(Config);
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
for d:=1 to ParamCount do begin
|
||||||
|
if CompareStr(LowerCase(Copy(ParamStr(d),1,3)),'/b=')=0 then begin
|
||||||
|
PG.StartBlockSize:=StrToInt(Copy(ParamStr(d),4,10));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (CompareStr(ParamStr(1),'')=0) or (CompareStr(ParamStr(2),'')=0) or (CompareStr(ParamStr(3),'')=0) then begin
|
||||||
|
WriteLn('This program will take (sourcefile) as input and create a (patchfile).');
|
||||||
|
WriteLn('With this patchfile, you can convert a (sourcefile) into (targetfile).');
|
||||||
|
WriteLn;
|
||||||
|
WriteLn('Command line info:');
|
||||||
|
WriteLn(' GENPAT (sourcefile) (targetfile) (patchfile)');
|
||||||
|
WriteLn;
|
||||||
|
WriteLn('Command line options (you do not need them):');
|
||||||
|
WriteLn('/B=(BlockSize) Set blocksize (def=64), multiple of 2');
|
||||||
|
WriteLn('/WAIT Wait for a keypress after program complete');
|
||||||
|
WriteLn('/DEBUG Show runtime debug information');
|
||||||
|
WriteLn('Note: all these parameters must be *after* the filenames!');
|
||||||
|
WriteLn;
|
||||||
|
Write('Press a enter to exit ');
|
||||||
|
ReadLn(S);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FileExists(ParamStr(3)) then begin
|
||||||
|
WriteLn('Using existing file to include patches in: '+ParamStr(3));
|
||||||
|
PG.LoadFromFile(ParamStr(3));
|
||||||
|
end;
|
||||||
|
|
||||||
|
T1:=Now;
|
||||||
|
WriteLn('Patch body size: '+IntToStr(PG.CreatePatch(ParamStr(1),ParamStr(2))));
|
||||||
|
PG.WriteToFile(ParamStr(3));
|
||||||
|
|
||||||
|
T2:=Now;
|
||||||
|
Write('GenPat.exe finished execution in: ');
|
||||||
|
WriteLn(FloatToStr((T2-T1)*24*60*60),'s');
|
||||||
|
WriteLn;
|
||||||
|
{$IFNDEF AUTOWAIT}
|
||||||
|
if FindCmdLineSwitch('wait',['/'],True) then begin
|
||||||
|
{$ENDIF}
|
||||||
|
WriteLn;
|
||||||
|
WriteLn('Press a key');
|
||||||
|
ReadLn(S);
|
||||||
|
{$IFNDEF AUTOWAIT}
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
PG.Free;
|
||||||
|
end.
|
591
Contrib/VPatch/Source/GenPat/PatchGenerator.pas
Normal file
591
Contrib/VPatch/Source/GenPat/PatchGenerator.pas
Normal file
|
@ -0,0 +1,591 @@
|
||||||
|
unit PatchGenerator;
|
||||||
|
|
||||||
|
{
|
||||||
|
VPatch 2 - Patch Generator
|
||||||
|
==========================
|
||||||
|
|
||||||
|
(c) 2002-2003 Van de Sande Productions
|
||||||
|
|
||||||
|
This unit contains the 'core' functionality of VPatch. TPatchGenerator can
|
||||||
|
load/create/save .PAT files and supports CreatePatch(Old, New) to generate
|
||||||
|
new patches. The only configurable parameter is StartBlockSize.
|
||||||
|
Though I cleaned up the code a little bit, there is very little documentation.
|
||||||
|
That's why I will briefly explain the general workings of the current VPatch
|
||||||
|
algoritm.
|
||||||
|
There is a source file, which is divided into blocks of BlockSize. Block 1
|
||||||
|
spans bytes 0-15, block 2 16-31, etc if blocksize = 16. For every block, a
|
||||||
|
checksum is calculated and then the block is inserted into a binary search
|
||||||
|
tree, which is sorted on this checksum.
|
||||||
|
Now, the target file (new version) is traversed linearly. For a block at a
|
||||||
|
certain position, the checksum is calculated. Then, a lookup is performed in
|
||||||
|
the binary search tree to find all blocks in the source file which match this
|
||||||
|
checksum. For every occurence, it is checked how many consecutive bytes match
|
||||||
|
with this block (note: since the checksum is not unique, this can be 0 as well,
|
||||||
|
but since all occurences are checked, the largest match is selected). Note also
|
||||||
|
that this match length is not limited to BlockSize but can be larger as well;
|
||||||
|
everything beyond the block end is checked as well (the block is merely used
|
||||||
|
as a starting position for checking the match).
|
||||||
|
For those biggest block matches between source/target files, a copy instruction
|
||||||
|
will be generated in the patch file. For 'inbetween' or unmatchable blocks, the
|
||||||
|
data of the new file is placed in the patch file. This involves some
|
||||||
|
housekeeping, which is what most of the other code does.
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
2.0 20030811 Koen Initial documentation
|
||||||
|
}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes,
|
||||||
|
Sysutils,
|
||||||
|
TreeCode,
|
||||||
|
VDSP_CRC;
|
||||||
|
|
||||||
|
type
|
||||||
|
TStatusNotifyEvent = procedure(S: String; Current, Total, Savings: Integer) of object;
|
||||||
|
TDebugNotifyEvent = procedure(S: String) of object;
|
||||||
|
PDataBlock = ^TDataBlock;
|
||||||
|
TDataBlock = record
|
||||||
|
SourceOffset: Integer;
|
||||||
|
TargetOffset: Integer;
|
||||||
|
Size: Integer;
|
||||||
|
Next: PDataBlock;
|
||||||
|
end;
|
||||||
|
//internal structure for FindBlock
|
||||||
|
TBlock = record
|
||||||
|
Offset: Integer;
|
||||||
|
Size: Integer;
|
||||||
|
end;
|
||||||
|
TPatchGenerator = class
|
||||||
|
private
|
||||||
|
noPat: Integer;
|
||||||
|
PRay: Array of TDataBlock;
|
||||||
|
NRay: Array of TDataBlock;
|
||||||
|
|
||||||
|
FPatchData: TMemoryStream;
|
||||||
|
FStartBlockSize: Integer; //initial block size
|
||||||
|
FBlockDivider: Integer; //... block size is divided by this
|
||||||
|
FMinimumBlockSize: Integer;//until this minimum is reached
|
||||||
|
FStepSize: Integer;
|
||||||
|
|
||||||
|
//input: ASubBlock, which is a pointer to the start of the block to look
|
||||||
|
//for in ABlock. The entire ABlock is searched. The function returns the
|
||||||
|
//offset of the block, when it is found. The ASize parameter contains the
|
||||||
|
//size of this block
|
||||||
|
procedure ShowDebug(S: String);
|
||||||
|
|
||||||
|
function FindBlock(ASubBlock, ABlock, ABlockTree: Pointer;
|
||||||
|
var ASubBlockStart: Integer; ASubBlockSize, ABlockSize,
|
||||||
|
AMatchSize, ABlockTreeNodeCount: Integer; var ASize: Integer): Integer;
|
||||||
|
|
||||||
|
procedure FindBlockSize(ASubBlock, ABlock: Pointer; ASubBlockSize,
|
||||||
|
ABlockSize: Integer; var ASubStart, AStart, AFoundSize: Integer);
|
||||||
|
function WritePatchToStream(Target: Pointer; SourceCRC,
|
||||||
|
TargetCRC: Integer): Integer;
|
||||||
|
|
||||||
|
procedure RemoveExistingPatch(ACRC: Integer);
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure Clear;
|
||||||
|
function CreatePatch(SourceFileName, TargetFileName: String): Integer;
|
||||||
|
property StartBlockSize: Integer read FStartBlockSize write FStartBlockSize;
|
||||||
|
property BlockDivider: Integer read FBlockDivider write FBlockDivider;
|
||||||
|
property MinimumBlockSize: Integer read FMinimumBlockSize write FMinimumBlockSize;
|
||||||
|
property StepSize: Integer read FStepSize write FStepSize;
|
||||||
|
function Size: Integer;
|
||||||
|
procedure WriteToFile(AFileName: String);
|
||||||
|
procedure WriteToStream(AStream: TStream);
|
||||||
|
procedure LoadFromFile(AFileName: String);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
BUF_BLOCK_SIZE = 4096;
|
||||||
|
INIT_BLOCK_COUNT=10000;
|
||||||
|
|
||||||
|
var
|
||||||
|
DebugEvent: TDebugNotifyEvent = nil;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TPatchGenerator }
|
||||||
|
|
||||||
|
procedure TPatchGenerator.Clear;
|
||||||
|
begin
|
||||||
|
FPatchData.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TPatchGenerator.Create;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
FPatchData:=TMemoryStream.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchGenerator.CreatePatch(SourceFileName,
|
||||||
|
TargetFileName: String): Integer;
|
||||||
|
var
|
||||||
|
fsSource, fsTarget: TFileStream;
|
||||||
|
fm: TMemoryStream;
|
||||||
|
Source, Target: Pointer;
|
||||||
|
SourceSize, TargetSize: Integer;
|
||||||
|
SourceCRC, TargetCRC: Integer;
|
||||||
|
SourceTree: Pointer;
|
||||||
|
SourceTreeNodeCount: Cardinal;
|
||||||
|
cBlockSize: Integer;
|
||||||
|
|
||||||
|
o,i,lastO: Integer;
|
||||||
|
Start,Siz,BetweenSiz: Integer;
|
||||||
|
retTO: Integer;
|
||||||
|
noN: Integer;
|
||||||
|
begin
|
||||||
|
fsSource:=TFileStream.Create(SourceFileName,fmOpenRead);
|
||||||
|
fsTarget:=TFileStream.Create(TargetFileName,fmOpenRead);
|
||||||
|
fm:=TMemoryStream.Create;
|
||||||
|
|
||||||
|
SetLength(PRay,INIT_BLOCK_COUNT);
|
||||||
|
SetLength(NRay,INIT_BLOCK_COUNT);
|
||||||
|
|
||||||
|
//Load those files into memory!
|
||||||
|
SourceSize:=fsSource.Size;
|
||||||
|
GetMem(Source,SourceSize);
|
||||||
|
fm.CopyFrom(fsSource,SourceSize);
|
||||||
|
Move(fm.Memory^,Source^,SourceSize);
|
||||||
|
SourceCRC:=FileCRC(fsSource);
|
||||||
|
fsSource.Free;
|
||||||
|
|
||||||
|
fm.Clear;
|
||||||
|
TargetSize:=fsTarget.Size;
|
||||||
|
GetMem(Target,TargetSize);
|
||||||
|
fm.CopyFrom(fsTarget,TargetSize);
|
||||||
|
Move(fm.Memory^,Target^,TargetSize);
|
||||||
|
TargetCRC:=FileCRC(fsTarget);
|
||||||
|
fsTarget.Free;
|
||||||
|
fm.Free;
|
||||||
|
|
||||||
|
PRay[0].TargetOffset:=0;
|
||||||
|
PRay[0].SourceOffset:=0;
|
||||||
|
PRay[0].Size:=0;
|
||||||
|
noPat:=1;
|
||||||
|
|
||||||
|
//termination block
|
||||||
|
|
||||||
|
PRay[noPat].SourceOffset:=0;
|
||||||
|
PRay[noPat].TargetOffset:=TargetSize;
|
||||||
|
PRay[noPat].Size:=0;
|
||||||
|
|
||||||
|
//we only have one pass in this mode
|
||||||
|
// StartBlockSize:=16;
|
||||||
|
MinimumBlockSize:=StartBlockSize;
|
||||||
|
StepSize:=1;
|
||||||
|
BlockDivider:=2;
|
||||||
|
|
||||||
|
//because we are dividing first inside.
|
||||||
|
cBlockSize:=StartBlockSize*BlockDivider;
|
||||||
|
|
||||||
|
SourceTree:=nil;
|
||||||
|
SourceTreeNodeCount:=BuildTree(Source,SourceTree,SourceSize,cBlockSize div BlockDivider);
|
||||||
|
SortTree(SourceTree,SourceTreeNodeCount);
|
||||||
|
|
||||||
|
//now, we must do the above again - with a smaller block size
|
||||||
|
repeat
|
||||||
|
if cBlockSize<=MinimumBlockSize then break;
|
||||||
|
cBlockSize:=cBlockSize div BlockDivider;
|
||||||
|
noN:=0;
|
||||||
|
for i:=1 to noPat do begin
|
||||||
|
//calculate location of the inbetween parts
|
||||||
|
Start:=PRay[i-1].TargetOffset+PRay[i-1].Size;
|
||||||
|
BetweenSiz:=PRay[i].TargetOffset-Start;
|
||||||
|
|
||||||
|
NRay[noN].SourceOffset:=PRay[i-1].SourceOffset;
|
||||||
|
NRay[noN].TargetOffset:=PRay[i-1].TargetOffset;
|
||||||
|
NRay[noN].Size:=PRay[i-1].Size;
|
||||||
|
Inc(noN);
|
||||||
|
if BetweenSiz>0 then begin
|
||||||
|
|
||||||
|
o:=Start;
|
||||||
|
repeat
|
||||||
|
//ShowDebug(PChar('DoFind '+IntToStr(o)));
|
||||||
|
LastO:=o;
|
||||||
|
retTO:=FindBlock(Target,Source,SourceTree,o,TargetSize,SourceSize,cBlockSize,SourceTreeNodeCount,Siz);
|
||||||
|
if not (Siz=0) then
|
||||||
|
ShowDebug(IntToStr(LastO)+' -> Source='+IntToStr(retTO)+' Target='+IntToStr(o)+' Size='+IntToStr(Siz));
|
||||||
|
|
||||||
|
if Siz=0 then begin
|
||||||
|
o:=LastO+StepSize;
|
||||||
|
end else begin
|
||||||
|
//we have found a block, let's add it!
|
||||||
|
NRay[noN].SourceOffset:=retTO;
|
||||||
|
NRay[noN].TargetOffset:=o;
|
||||||
|
NRay[noN].Size:=Siz;
|
||||||
|
Inc(noN);
|
||||||
|
if noN>=Length(NRay) then begin
|
||||||
|
SetLength(NRay,Length(NRay)*2);
|
||||||
|
SetLength(PRay,Length(PRay)*2);
|
||||||
|
end;
|
||||||
|
Inc(o,Siz);
|
||||||
|
end;
|
||||||
|
|
||||||
|
//check to see if we're not inside another one.
|
||||||
|
Siz:=NRay[noN].TargetOffset-NRay[noN-1].TargetOffset-NRay[noN-1].Size;
|
||||||
|
If Siz<0 then begin //that's impossible! (overlapping should be eliminated)
|
||||||
|
NRay[noN].TargetOffset:=NRay[noN].TargetOffset-Siz;
|
||||||
|
NRay[noN].Size:=NRay[noN].Size+Siz;
|
||||||
|
NRay[noN].SourceOffset:=NRay[noN].SourceOffset-Siz;
|
||||||
|
end;
|
||||||
|
until o>Start+BetweenSiz;
|
||||||
|
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
//I think the last termination block isn't copied: do so now.
|
||||||
|
NRay[noN].SourceOffset:=PRay[noPat].SourceOffset;
|
||||||
|
NRay[noN].TargetOffset:=PRay[noPat].TargetOffset;
|
||||||
|
NRay[noN].Size:=PRay[noPat].Size;
|
||||||
|
//copy back into PRay
|
||||||
|
for i:=0 to noN do begin
|
||||||
|
PRay[i].SourceOffset:=NRay[i].SourceOffset;
|
||||||
|
PRay[i].TargetOffset:=NRay[i].TargetOffset;
|
||||||
|
PRay[i].Size:=NRay[i].Size;
|
||||||
|
end;
|
||||||
|
noPat:=noN;
|
||||||
|
until false;
|
||||||
|
|
||||||
|
//writing is next!
|
||||||
|
ShowDebug('Writing patch');
|
||||||
|
|
||||||
|
Result:=WritePatchToStream(Target, SourceCRC, TargetCRC);
|
||||||
|
|
||||||
|
ClearTree(SourceTree,SourceTreeNodeCount);
|
||||||
|
FreeMem(Source,SourceSize);
|
||||||
|
FreeMem(Target,TargetSize);
|
||||||
|
ShowDebug('Done');
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TPatchGenerator.Destroy;
|
||||||
|
begin
|
||||||
|
FPatchData.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchGenerator.FindBlock(ASubBlock, ABlock, ABlockTree: Pointer; var ASubBlockStart: Integer;
|
||||||
|
ASubBlockSize, ABlockSize, AMatchSize, ABlockTreeNodeCount: Integer; var ASize: Integer): Integer;
|
||||||
|
//This procedure locates location of a block in the target file
|
||||||
|
//Then, it calls FindBlockSize to determine size of this block
|
||||||
|
var
|
||||||
|
MatchSize, FoundSize: Integer;
|
||||||
|
q,r,i: Integer;
|
||||||
|
FoundCache_SubOffset, FoundCache_Size, FoundCache_Offset: Integer;
|
||||||
|
Checksum: Cardinal;
|
||||||
|
PFound: PTreeNode;
|
||||||
|
FoundCount: Integer;
|
||||||
|
begin
|
||||||
|
//if we find nothing...
|
||||||
|
|
||||||
|
FoundCache_Size:=0;
|
||||||
|
FoundCache_Offset:=0;
|
||||||
|
FoundCache_SubOffset:=ASubBlockStart;
|
||||||
|
|
||||||
|
FindBlock:=0;
|
||||||
|
ASize:=0;
|
||||||
|
|
||||||
|
MatchSize:=AMatchSize;
|
||||||
|
|
||||||
|
//we can only find MatchSize sized blocks in the tree!
|
||||||
|
if MatchSize > ASubBlockSize - ASubBlockStart then Exit;
|
||||||
|
if MatchSize = 0 then Exit;
|
||||||
|
|
||||||
|
Checksum:=0;
|
||||||
|
calculateChecksum(ASubBlock,ASubBlockStart,MatchSize,Checksum);
|
||||||
|
PFound:=TreeFind(Checksum,ABlockTree,ABlockTreeNodeCount,FoundCount);
|
||||||
|
|
||||||
|
for i:=0 to Pred(FoundCount) do begin
|
||||||
|
FoundSize:=MatchSize;
|
||||||
|
//q = offset in Block
|
||||||
|
q:=PFound^.Offset;
|
||||||
|
//r = offset in SubBlock
|
||||||
|
r:=ASubBlockStart;
|
||||||
|
FindBlockSize(ASubBlock, ABlock, ASubBlockSize, ABlockSize, r, q, FoundSize);
|
||||||
|
if FoundSize>FoundCache_Size then begin
|
||||||
|
FoundCache_SubOffset:=r;
|
||||||
|
FoundCache_Offset:=q;
|
||||||
|
FoundCache_Size:=FoundSize;
|
||||||
|
end;
|
||||||
|
ShowDebug(' Block Size Start='+IntToStr(r)+' tarStart='+IntToStr(q)+' Size='+IntToStr(FoundSize));
|
||||||
|
PFound:=PTreeNode(Integer(PFound)+SizeOf(TTreeNode));
|
||||||
|
end;
|
||||||
|
|
||||||
|
FindBlock:=FoundCache_Offset;
|
||||||
|
ASize:=FoundCache_Size;
|
||||||
|
ASubBlockStart:=FoundCache_SubOffset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchGenerator.FindBlockSize(ASubBlock, ABlock: Pointer; ASubBlockSize, ABlockSize: Integer; var ASubStart,AStart,AFoundSize: Integer);
|
||||||
|
var
|
||||||
|
FoundSize: Integer;
|
||||||
|
a,c,d,i: Integer;
|
||||||
|
f1p,f2p,f1Size,f2Size: Integer;
|
||||||
|
beforeSize: Integer;
|
||||||
|
CurBufSize: Integer;
|
||||||
|
begin
|
||||||
|
//OK, now let's go...
|
||||||
|
//Trace after -> how long does this go on?
|
||||||
|
f1p:=Integer(ASubBlock)+ASubStart;
|
||||||
|
f2p:=Integer(ABlock)+AStart;
|
||||||
|
f1Size:=ASubBlockSize-ASubStart;
|
||||||
|
f2Size:=ABlockSize-AStart;
|
||||||
|
FoundSize:=0;
|
||||||
|
CurBufSize := BUF_BLOCK_SIZE; //size of the block we're checking
|
||||||
|
while not (CurBufSize = 0) do begin
|
||||||
|
//we need equal bytes from both... so if one of them EOF, it's the end.
|
||||||
|
if FoundSize+CurBufSize>f1Size then CurBufSize:=f1Size - FoundSize;
|
||||||
|
if FoundSize+CurBufSize>f2Size then CurBufSize:=f2Size - FoundSize;
|
||||||
|
if CompareMem(Pointer(f1p),Pointer(f2p),CurBufSize) then begin
|
||||||
|
Inc(FoundSize,CurBufSize);
|
||||||
|
Inc(f1p,CurBufSize);
|
||||||
|
Inc(f2p,CurBufSize);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
CurBufSize:=CurBufSize div 2;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FoundSize = 0 then begin AFoundSize:=0; Exit; end;
|
||||||
|
|
||||||
|
//Trace before -> how much bytes are still the same before the block?
|
||||||
|
//First, read 1 block from source and 1 block from target, start from back to compare how much they differ
|
||||||
|
//just take BUF_BLOCK_SIZE as maximum size for the block before - that's surely
|
||||||
|
//big enough!
|
||||||
|
beforeSize:=BUF_BLOCK_SIZE;
|
||||||
|
a:=ASubStart-beforeSize;
|
||||||
|
if a<0 then begin
|
||||||
|
a:=0;
|
||||||
|
beforeSize:=ASubStart;
|
||||||
|
end;
|
||||||
|
//b is the current before block size
|
||||||
|
c:=AStart-beforeSize;
|
||||||
|
if c<0 then begin
|
||||||
|
c:=0;
|
||||||
|
beforeSize:=AStart;
|
||||||
|
a:=ASubStart-beforeSize;
|
||||||
|
end;
|
||||||
|
//a=Offset in source
|
||||||
|
//b=Size of beforeblock
|
||||||
|
//c=offset in target
|
||||||
|
|
||||||
|
d:=0;
|
||||||
|
for i:=beforeSize-1 downto 0 do begin
|
||||||
|
//if not (f1^[a+i]=f2^[c+i]) then begin
|
||||||
|
if not (PByte(Integer(ASubBlock)+a+i)^=PByte(Integer(ABlock)+c+i)^) then begin
|
||||||
|
//d=how many bytes before are the same?
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
Inc(d);
|
||||||
|
end;
|
||||||
|
Inc(FoundSize,d);
|
||||||
|
Dec(ASubStart,d);
|
||||||
|
Dec(AStart,d);
|
||||||
|
AFoundSize:=FoundSize;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchGenerator.Size: Integer;
|
||||||
|
begin
|
||||||
|
Result:=FPatchData.Size;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchGenerator.ShowDebug(S: String);
|
||||||
|
begin
|
||||||
|
if Assigned(DebugEvent) then DebugEvent(S);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPatchGenerator.WritePatchToStream(Target: Pointer; SourceCRC, TargetCRC: Integer): Integer;
|
||||||
|
var
|
||||||
|
HeadID: Array[0..3] of Char;
|
||||||
|
NoBlocks, NoBlocksOffset, BodySize, BodySizeOffset: Integer;
|
||||||
|
b: Byte;
|
||||||
|
w: Word;
|
||||||
|
i, j: Integer;
|
||||||
|
l: LongWord;
|
||||||
|
Start, Siz: Integer;
|
||||||
|
PTarget: Pointer;
|
||||||
|
begin
|
||||||
|
RemoveExistingPatch(SourceCRC);
|
||||||
|
with FPatchData do begin
|
||||||
|
Seek(0,soFromEnd);
|
||||||
|
if Size = 0 then begin
|
||||||
|
HeadID:='VPAT';
|
||||||
|
Write(HeadID,SizeOf(HeadID));
|
||||||
|
l:=0;
|
||||||
|
Write(l,SizeOf(l)); //NoFiles
|
||||||
|
end;
|
||||||
|
l:=0;
|
||||||
|
NoBlocksOffset:=Position;
|
||||||
|
Write(l,SizeOf(l)); //should become NoBlocks later
|
||||||
|
Write(SourceCRC,SizeOf(SourceCRC)); //source CRC
|
||||||
|
Write(TargetCRC,SizeOf(TargetCRC)); //target CRC
|
||||||
|
BodySizeOffset:=Position;
|
||||||
|
Write(l,SizeOf(l)); //should become BodySize (of this patch)
|
||||||
|
|
||||||
|
NoBlocks:=0;
|
||||||
|
BodySize:=0;
|
||||||
|
//Write the patch...
|
||||||
|
for i:=0 to noPat - 1 do begin
|
||||||
|
//write char 1 - integer/copysource
|
||||||
|
//write char 2 - long/copysource
|
||||||
|
//write char 5 - integer/insidepatch
|
||||||
|
//write char 6 - long/insidepatch
|
||||||
|
|
||||||
|
Start:=PRay[i].TargetOffset+PRay[i].Size;
|
||||||
|
Siz:= PRay[i+1].TargetOffset-Start;
|
||||||
|
|
||||||
|
If Siz<0 then begin //that's impossible! (overlapping should be eliminated)
|
||||||
|
PRay[i+1].TargetOffset:=PRay[i+1].TargetOffset-Siz;
|
||||||
|
PRay[i+1].Size:=PRay[i+1].Size+Siz;
|
||||||
|
PRay[i+1].SourceOffset:=PRay[i+1].SourceOffset-Siz;
|
||||||
|
Siz:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not (PRay[i].Size=0) then begin
|
||||||
|
if (PRay[i].Size<=255) then begin
|
||||||
|
b:=1;
|
||||||
|
Write(b,SizeOf(b));
|
||||||
|
b:=PRay[i].Size;
|
||||||
|
Write(b,SizeOf(b));
|
||||||
|
Inc(BodySize,2);
|
||||||
|
end else if PRay[i].Size<=65535 then begin
|
||||||
|
b:=2;
|
||||||
|
Write(b,SizeOf(b));
|
||||||
|
w:=PRay[i].Size;
|
||||||
|
Write(w,SizeOf(w));
|
||||||
|
Inc(BodySize,3);
|
||||||
|
end else begin
|
||||||
|
b:=3;
|
||||||
|
Write(b,SizeOf(b));
|
||||||
|
Write(PRay[i].Size,SizeOf(Integer));
|
||||||
|
Inc(BodySize,5);
|
||||||
|
end;
|
||||||
|
Write(PRay[i].SourceOffset,SizeOf(Integer));
|
||||||
|
Inc(BodySize,SizeOf(Integer));
|
||||||
|
Inc(NoBlocks);
|
||||||
|
end;
|
||||||
|
//Now write the writeblock
|
||||||
|
If Not (Siz = 0) Then begin
|
||||||
|
if Siz<=255 then begin
|
||||||
|
b:=5;
|
||||||
|
Write(b,SizeOf(b));
|
||||||
|
b:=Siz;
|
||||||
|
Write(b,SizeOf(b));
|
||||||
|
Inc(BodySize,2);
|
||||||
|
end else if Siz<=65535 then begin
|
||||||
|
b:=6;
|
||||||
|
Write(b,1);
|
||||||
|
w:=Siz;
|
||||||
|
Write(w,2);
|
||||||
|
Inc(BodySize,3);
|
||||||
|
end else begin
|
||||||
|
b:=7;
|
||||||
|
Write(b,1);
|
||||||
|
Write(Siz,4);
|
||||||
|
Inc(BodySize,5);
|
||||||
|
end;
|
||||||
|
PTarget:=Pointer(Integer(Target)+Start);
|
||||||
|
j:=Start;
|
||||||
|
repeat
|
||||||
|
//read
|
||||||
|
if (j+4096>Start+Siz) then begin
|
||||||
|
Write(PTarget^,Start+Siz-j);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
Write(PTarget^,4096);
|
||||||
|
Inc(j,4096);
|
||||||
|
PTarget:=Pointer(Integer(PTarget)+4096);
|
||||||
|
until false;
|
||||||
|
Inc(BodySize,Siz);
|
||||||
|
Inc(NoBlocks);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Seek(NoBlocksOffset,soFromBeginning);
|
||||||
|
Write(NoBlocks,SizeOf(NoBlocks));
|
||||||
|
Seek(BodySizeOffset,soFromBeginning);
|
||||||
|
Write(BodySize,SizeOf(BodySize));
|
||||||
|
ShowDebug('Patch body size: '+IntToStr(BodySize));
|
||||||
|
ShowDebug('Total patch size:'+IntToStr(Size));
|
||||||
|
//now increase file count
|
||||||
|
Seek(4,soFromBeginning);
|
||||||
|
Read(i,SizeOf(i));
|
||||||
|
Inc(i);
|
||||||
|
Seek(4,soFromBeginning);
|
||||||
|
Write(i,SizeOf(i));
|
||||||
|
Seek(0,soFromEnd);
|
||||||
|
Result:=BodySize;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchGenerator.WriteToFile(AFileName: String);
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
fs:=TFileStream.Create(AFileName,fmCreate);
|
||||||
|
FPatchData.Seek(0,soFromBeginning);
|
||||||
|
fs.CopyFrom(FPatchData,FPatchData.Size);
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchGenerator.LoadFromFile(AFileName: String);
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
begin
|
||||||
|
fs:=TFileStream.Create(AFileName,fmOpenRead);
|
||||||
|
FPatchData.Clear;
|
||||||
|
FPatchData.CopyFrom(fs,fs.Size);
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchGenerator.RemoveExistingPatch(ACRC: Integer);
|
||||||
|
var
|
||||||
|
HeadID: Array[0..3] of Char;
|
||||||
|
NoFiles, i, j, SourceCRC, MSize: Integer;
|
||||||
|
StartPos: Integer;
|
||||||
|
ms: TMemoryStream;
|
||||||
|
begin
|
||||||
|
with FPatchData do begin
|
||||||
|
if Size = 0 then Exit;
|
||||||
|
Seek(0,soFromBeginning);
|
||||||
|
Read(HeadID,SizeOf(HeadID));
|
||||||
|
if HeadID = 'VPAT' then begin
|
||||||
|
Read(NoFiles,SizeOf(NoFiles));
|
||||||
|
for i:=0 to Pred(NoFiles) do begin
|
||||||
|
if Position >= Size then Break;
|
||||||
|
StartPos:=Position;
|
||||||
|
Read(j,SizeOf(j)); //NoBlocks
|
||||||
|
Read(SourceCRC,SizeOf(SourceCRC)); //SourceCRC
|
||||||
|
Read(j,SizeOf(j)); //TargetCRC
|
||||||
|
Read(j,SizeOf(j)); //BodySize
|
||||||
|
Seek(j,soFromCurrent);
|
||||||
|
if SourceCRC = ACRC then begin
|
||||||
|
ms:=TMemoryStream.Create;
|
||||||
|
MSize:=Size-Position;
|
||||||
|
if MSize > 0 then ms.CopyFrom(FPatchData,MSize);
|
||||||
|
ms.Seek(0, soFromBeginning);
|
||||||
|
FPatchData.Seek(StartPos,soFromBeginning);
|
||||||
|
FPatchData.SetSize(Size - j - SizeOf(Integer) * 4);
|
||||||
|
FPatchData.CopyFrom(ms,ms.Size);
|
||||||
|
ms.Free;
|
||||||
|
Dec(NoFiles);
|
||||||
|
Seek(4,soFromBeginning);
|
||||||
|
Write(NoFiles,SizeOf(NoFiles));
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPatchGenerator.WriteToStream(AStream: TStream);
|
||||||
|
begin
|
||||||
|
FPatchData.Seek(0,soFromBeginning);
|
||||||
|
AStream.CopyFrom(FPatchData,FPatchData.Size);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
245
Contrib/VPatch/Source/GenPat/TreeCode.pas
Normal file
245
Contrib/VPatch/Source/GenPat/TreeCode.pas
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
unit TreeCode;
|
||||||
|
|
||||||
|
{
|
||||||
|
VPatch 2 - Binary Checksum Tree
|
||||||
|
===============================
|
||||||
|
|
||||||
|
(c) 2002-2003 Van de Sande Productions
|
||||||
|
|
||||||
|
This unit implements a binary search tree, which is constructed from a memory
|
||||||
|
block by BuildTree. This memory block is divided into equal-sized blocks of
|
||||||
|
BlockSize, and for every block a checksum is calculated. Then, it is inserted
|
||||||
|
in the binary tree, which is sorted on the checksum.
|
||||||
|
The patch generator will search for the checksums using a binary search, which
|
||||||
|
is O(log n) (much better than the old 1.x algoritm, which was O(n)).
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
2.0 20030811 Koen Initial documentation
|
||||||
|
}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
type
|
||||||
|
TSortStack=record
|
||||||
|
lo,hi: Integer;
|
||||||
|
end;
|
||||||
|
PTreeNode = ^TTreeNode;
|
||||||
|
TTreeNode = record
|
||||||
|
Checksum: Cardinal;
|
||||||
|
Offset: Cardinal;
|
||||||
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
TREENODE_SIZE = SizeOf(TTreeNode);
|
||||||
|
|
||||||
|
procedure calculateChecksum(AData: Pointer; AStart, ASize: Cardinal; var K: Cardinal);
|
||||||
|
procedure calculateNext(AData: Pointer; AStart, ASize: Cardinal; var K: Cardinal);
|
||||||
|
function BuildTree(ASource: Pointer; var ATree: Pointer; ASourceSize, ABLOCKSIZE: Cardinal): Cardinal;
|
||||||
|
procedure SortTree(ATree: Pointer; ANodeCount: Cardinal);
|
||||||
|
procedure ClearTree(var ATree: Pointer; ANodeCount: Cardinal);
|
||||||
|
function TreeFind(AChecksum: Cardinal; ABlockTree: Pointer; ABlockTreeNodeCount: Integer; var FoundCount: Integer): PTreeNode;
|
||||||
|
function GetItem(ATree: Pointer; Index, ANodeCount: Cardinal): TTreeNode;
|
||||||
|
|
||||||
|
procedure Test;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses SysUtils;
|
||||||
|
|
||||||
|
procedure calculateChecksum(AData: Pointer; AStart, ASize: Cardinal; var K: Cardinal);
|
||||||
|
var
|
||||||
|
A,B,i,j: Cardinal;
|
||||||
|
begin
|
||||||
|
A:=K and $0000FFFF;
|
||||||
|
B:=(K and $FFFF0000) shr 16;
|
||||||
|
j:=Cardinal(AData)+AStart;
|
||||||
|
for i:=1 to ASize do begin
|
||||||
|
A:=A + PByte(j)^;
|
||||||
|
B:=B + (ASize-i+1)*PByte(j)^;
|
||||||
|
Inc(j);
|
||||||
|
end;
|
||||||
|
K:=(A and $0000FFFF) or ((B and $0000FFFF) shl 16);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure calculateNext(AData: Pointer; AStart, ASize: Cardinal; var K: Cardinal);
|
||||||
|
var
|
||||||
|
A,B,j: Cardinal;
|
||||||
|
begin
|
||||||
|
j:=Cardinal(AData)+AStart;
|
||||||
|
A:=(K-PByte(j-1)^+PByte(j+ASize-1)^) and $0000FFFF;
|
||||||
|
B:=((K shr 16)-ASize*PByte(j-1)^+A) and $0000FFFF;
|
||||||
|
K:=A or (B shl 16);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function BuildTree(ASource: Pointer; var ATree: Pointer; ASourceSize, ABLOCKSIZE: Cardinal): Cardinal;
|
||||||
|
var
|
||||||
|
i, NodeCount: Cardinal;
|
||||||
|
Node: TTreeNode;
|
||||||
|
begin
|
||||||
|
Assert(not Assigned(ATree),'Cannot use initialized tree in BuildTree!');
|
||||||
|
NodeCount:=ASourceSize div ABLOCKSIZE;
|
||||||
|
GetMem(ATree,NodeCount*TREENODE_SIZE);
|
||||||
|
if NodeCount > 0 then begin
|
||||||
|
for i:=0 to Pred(NodeCount) do begin
|
||||||
|
Node.Offset:=i*ABLOCKSIZE;
|
||||||
|
Node.Checksum:=0;
|
||||||
|
calculateChecksum(ASource,Node.Offset,ABLOCKSIZE,Node.Checksum);
|
||||||
|
Move(Node,Pointer(Cardinal(ATree)+i*TREENODE_SIZE)^,TREENODE_SIZE);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Result:=NodeCount;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure SetItem(ATree: Pointer; Index, ANodeCount: Cardinal; New: TTreeNode);
|
||||||
|
var
|
||||||
|
p: PTreeNode;
|
||||||
|
begin
|
||||||
|
Assert(Index<ANodeCount,'Tree/GetItem: Index too big');
|
||||||
|
p:=PTreeNode(Cardinal(ATree)+Index*TREENODE_SIZE);
|
||||||
|
p^:=New;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetItem(ATree: Pointer; Index, ANodeCount: Cardinal): TTreeNode;
|
||||||
|
var
|
||||||
|
p: PTreeNode;
|
||||||
|
begin
|
||||||
|
Assert(Index<ANodeCount,'Tree/GetItem: Index too big '+IntToStr(Index));
|
||||||
|
p:=PTreeNode(Cardinal(ATree)+Index*TREENODE_SIZE);
|
||||||
|
Result:=p^;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure SortTree(ATree: Pointer; ANodeCount: Cardinal);
|
||||||
|
var
|
||||||
|
compare: Cardinal;
|
||||||
|
aStack: Array[1..128] of TSortStack;
|
||||||
|
StackPtr: Integer;
|
||||||
|
Mid,i,j,low,hi: Integer;
|
||||||
|
Switcher: TTreeNode;
|
||||||
|
begin
|
||||||
|
If ANodeCount = 0 Then Exit;
|
||||||
|
StackPtr:=1;
|
||||||
|
aStack[StackPtr].lo:=0;
|
||||||
|
aStack[StackPtr].hi:=ANodeCount - 1;
|
||||||
|
Inc(StackPtr);
|
||||||
|
while not (StackPtr=1) do begin
|
||||||
|
StackPtr:=StackPtr-1;
|
||||||
|
low:=aStack[StackPtr].lo;
|
||||||
|
hi:=aStack[StackPtr].hi;
|
||||||
|
while true do begin
|
||||||
|
i:=low;
|
||||||
|
j:=hi;
|
||||||
|
Mid:=(low + hi) div 2;
|
||||||
|
compare:=PTreeNode(Integer(ATree)+Mid*TREENODE_SIZE)^.Checksum;
|
||||||
|
while true do begin
|
||||||
|
While PTreeNode(Integer(ATree)+i*TREENODE_SIZE)^.Checksum < compare do begin
|
||||||
|
Inc(i);
|
||||||
|
end;
|
||||||
|
While PTreeNode(Integer(ATree)+j*TREENODE_SIZE)^.Checksum > compare do begin
|
||||||
|
j:=j-1;
|
||||||
|
end;
|
||||||
|
If (i <= j) Then begin
|
||||||
|
Move(Pointer(Integer(ATree)+j*TREENODE_SIZE)^,Switcher,TREENODE_SIZE);
|
||||||
|
Move(Pointer(Integer(ATree)+i*TREENODE_SIZE)^,Pointer(Integer(ATree)+j*TREENODE_SIZE)^,TREENODE_SIZE);
|
||||||
|
Move(Switcher,Pointer(Integer(ATree)+i*TREENODE_SIZE)^,TREENODE_SIZE);
|
||||||
|
Inc(i);
|
||||||
|
Dec(j);
|
||||||
|
End;
|
||||||
|
if not (i <= j) then break;
|
||||||
|
end;
|
||||||
|
If j - low < hi - i Then begin
|
||||||
|
If i < hi Then begin
|
||||||
|
aStack[StackPtr].lo:=i;
|
||||||
|
aStack[StackPtr].hi:=hi;
|
||||||
|
Inc(StackPtr);
|
||||||
|
End;
|
||||||
|
hi:=j;
|
||||||
|
end Else begin
|
||||||
|
If low < j Then begin
|
||||||
|
aStack[StackPtr].lo:=low;
|
||||||
|
aStack[StackPtr].hi:=j;
|
||||||
|
Inc(StackPtr);
|
||||||
|
End;
|
||||||
|
low:=i;
|
||||||
|
End;
|
||||||
|
if not (low<hi) then break;
|
||||||
|
end;
|
||||||
|
if StackPtr=1 then break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ClearTree(var ATree: Pointer; ANodeCount: Cardinal);
|
||||||
|
begin
|
||||||
|
FreeMem(ATree,ANodeCount*TREENODE_SIZE);
|
||||||
|
ATree:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TreeFind(AChecksum: Cardinal; ABlockTree: Pointer; ABlockTreeNodeCount: Integer; var FoundCount: Integer): PTreeNode;
|
||||||
|
var
|
||||||
|
lo,mid,hi,m: Integer;
|
||||||
|
tmp: Cardinal;
|
||||||
|
begin
|
||||||
|
lo:=0;
|
||||||
|
hi:=ABlockTreeNodeCount-1;
|
||||||
|
while true do begin
|
||||||
|
mid:=(lo+hi) div 2;
|
||||||
|
tmp:=PCardinal(Integer(ABlockTree)+mid*TREENODE_SIZE)^;
|
||||||
|
if tmp = AChecksum then begin
|
||||||
|
FoundCount:=1;
|
||||||
|
m:=mid;
|
||||||
|
Result:=PTreeNode(Integer(ABlockTree)+m*TREENODE_SIZE);
|
||||||
|
while m > 0 do begin
|
||||||
|
Dec(m);
|
||||||
|
if PCardinal(Integer(ABlockTree)+m*TREENODE_SIZE)^ = tmp then begin
|
||||||
|
Result:=PTreeNode(Integer(ABlockTree)+m*TREENODE_SIZE);
|
||||||
|
Inc(FoundCount);
|
||||||
|
end else
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
m:=mid;
|
||||||
|
while m < ABlockTreeNodeCount-1 do begin
|
||||||
|
Inc(m);
|
||||||
|
if PCardinal(Integer(ABlockTree)+m*TREENODE_SIZE)^ = tmp then begin
|
||||||
|
Inc(FoundCount);
|
||||||
|
end else
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
if lo>=hi then Break;
|
||||||
|
if AChecksum < tmp then begin
|
||||||
|
hi:=mid-1;
|
||||||
|
end else begin
|
||||||
|
lo:=mid+1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
FoundCount:=0; Result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Test;
|
||||||
|
var
|
||||||
|
p: Pointer;
|
||||||
|
t: TTreeNode;
|
||||||
|
r: PTreeNode;
|
||||||
|
i,q: Integer;
|
||||||
|
NC: Integer;
|
||||||
|
begin
|
||||||
|
NC:=100;
|
||||||
|
GetMem(p,800);
|
||||||
|
for i:=0 to 99 do begin
|
||||||
|
t.Offset:=i*100;
|
||||||
|
t.Checksum:=i div 2;
|
||||||
|
SetItem(p,i,NC,t);
|
||||||
|
end;
|
||||||
|
SortTree(p,NC);
|
||||||
|
for i:=0 to 99 do begin
|
||||||
|
t:=GetItem(p,i,NC);
|
||||||
|
Write(IntToStr(t.Checksum)+' ');
|
||||||
|
end;
|
||||||
|
r:=TreeFind(7,p,NC,q);
|
||||||
|
WriteLn(IntToStr(q));
|
||||||
|
t:=r^;
|
||||||
|
WriteLn(IntToStr(t.Checksum)+' ');
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
77
Contrib/VPatch/Source/GenPat/VAppend.dpr
Normal file
77
Contrib/VPatch/Source/GenPat/VAppend.dpr
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
program VAppend;
|
||||||
|
|
||||||
|
{$APPTYPE CONSOLE}
|
||||||
|
|
||||||
|
uses
|
||||||
|
SysUtils;
|
||||||
|
|
||||||
|
var
|
||||||
|
fs, fo: File;
|
||||||
|
Patch: String;
|
||||||
|
OutFile: String = 'VPATCH.EXE';
|
||||||
|
Runtime: String = 'VPATCH.BIN';
|
||||||
|
o: LongWord;
|
||||||
|
Buf: Array[0..4095] of Byte;
|
||||||
|
Size, BufSize: Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
WriteLn('VAppend v2.0');
|
||||||
|
WriteLn('============');
|
||||||
|
WriteLn;
|
||||||
|
WriteLn('(c) 2001-2002 Van de Sande Productions');
|
||||||
|
WriteLn('Website: http://www.tibed.net/vpatch');
|
||||||
|
WriteLn('E-mail: koen@tibed.net');
|
||||||
|
WriteLn;
|
||||||
|
if ParamCount = 0 then begin
|
||||||
|
WriteLn('Use this program to append .PAT files to the VPatch runtime.');
|
||||||
|
WriteLn;
|
||||||
|
WriteLn(' VAPPEND (patch file) [output file] [runtime]');
|
||||||
|
WriteLn;
|
||||||
|
WriteLn('By default, the output file is VPATCH.EXE and the runtime is VPATCH.BIN');
|
||||||
|
end;
|
||||||
|
if not FileExists(ParamStr(1)) then begin
|
||||||
|
WriteLn('ERROR: Patch file not found');
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
Patch := ParamStr(1);
|
||||||
|
if ParamCount > 1 then OutFile := ParamStr(2);
|
||||||
|
if ParamCount > 2 then Runtime := ParamStr(3);
|
||||||
|
WriteLn('Patch: '+Patch);
|
||||||
|
WriteLn('Runtime: '+Runtime);
|
||||||
|
WriteLn('Output: '+OutFile);
|
||||||
|
|
||||||
|
AssignFile(fo,OutFile);
|
||||||
|
Rewrite(fo,1);
|
||||||
|
//copy the runtime
|
||||||
|
AssignFile(fs,Runtime);
|
||||||
|
FileMode:=fmOpenRead;
|
||||||
|
Reset(fs,1);
|
||||||
|
BufSize:=4096;
|
||||||
|
o:=FileSize(fs); //patch start offset
|
||||||
|
Size:=FileSize(fs);
|
||||||
|
while Size>0 do begin
|
||||||
|
if Size-BufSize<0 then BufSize:=Size;
|
||||||
|
BlockRead(fs,Buf,BufSize);
|
||||||
|
BlockWrite(fo,Buf,BufSize);
|
||||||
|
Dec(Size,BufSize);
|
||||||
|
end;
|
||||||
|
CloseFile(fs);
|
||||||
|
//do the patch
|
||||||
|
AssignFile(fs,Patch);
|
||||||
|
FileMode:=fmOpenRead;
|
||||||
|
Reset(fs,1);
|
||||||
|
BufSize:=4096;
|
||||||
|
Size:=FileSize(fs);
|
||||||
|
while Size>0 do begin
|
||||||
|
if Size-BufSize<0 then BufSize:=Size;
|
||||||
|
BlockRead(fs,Buf,BufSize);
|
||||||
|
BlockWrite(fo,Buf,BufSize);
|
||||||
|
Dec(Size,BufSize);
|
||||||
|
end;
|
||||||
|
CloseFile(fs);
|
||||||
|
|
||||||
|
BlockWrite(fo,o,SizeOf(o));
|
||||||
|
CloseFile(fo);
|
||||||
|
WriteLn('Created.');
|
||||||
|
end.
|
||||||
|
|
26
Contrib/VPatch/Source/GenPat/VPatch2.bpg
Normal file
26
Contrib/VPatch/Source/GenPat/VPatch2.bpg
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
VERSION = BWS.01
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
!ifndef ROOT
|
||||||
|
ROOT = $(MAKEDIR)\..
|
||||||
|
!endif
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$**
|
||||||
|
DCC = $(ROOT)\bin\dcc32.exe $**
|
||||||
|
BRCC = $(ROOT)\bin\brcc32.exe $**
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
PROJECTS = GenPat2.exe VAppend.exe VPatchGUI.exe
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
default: $(PROJECTS)
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
GenPat2.exe: GenPat2.dpr
|
||||||
|
$(DCC)
|
||||||
|
|
||||||
|
VAppend.exe: VAppend.dpr
|
||||||
|
$(DCC)
|
||||||
|
|
||||||
|
VPatchGUI.exe: gui\VPatchGUI.dpr
|
||||||
|
$(DCC)
|
||||||
|
|
||||||
|
|
115
Contrib/VPatch/Source/GenPat/vdsp_crc.pas
Normal file
115
Contrib/VPatch/Source/GenPat/vdsp_crc.pas
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
unit VDSP_CRC;
|
||||||
|
|
||||||
|
{
|
||||||
|
VPatch 2 - CRC
|
||||||
|
==============
|
||||||
|
|
||||||
|
(c) 2002-2003 Van de Sande Productions
|
||||||
|
|
||||||
|
This unit can calculate the standard ZIP CRC32 for a filestream.
|
||||||
|
|
||||||
|
What's new
|
||||||
|
----------
|
||||||
|
2.0 20030811 Koen Initial documentation
|
||||||
|
}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses Classes;
|
||||||
|
|
||||||
|
//var
|
||||||
|
//this is the CRC32 table
|
||||||
|
// CRCTable: Array[0..255] of LongWord;
|
||||||
|
{= (
|
||||||
|
//this table used to be inside the exe, but now it has been replaced by a calculation routine which saves 1 KB
|
||||||
|
$0,$77073096,$EE0E612C,$990951BA,$76DC419,
|
||||||
|
$706AF48F,$E963A535,$9E6495A3,$EDB8832,$79DCB8A4,
|
||||||
|
$E0D5E91E,$97D2D988,$9B64C2B,$7EB17CBD,$E7B82D07,
|
||||||
|
$90BF1D91,$1DB71064,$6AB020F2,$F3B97148,$84BE41DE,
|
||||||
|
$1ADAD47D,$6DDDE4EB,$F4D4B551,$83D385C7,$136C9856,
|
||||||
|
$646BA8C0,$FD62F97A,$8A65C9EC,$14015C4F,$63066CD9,
|
||||||
|
$FA0F3D63,$8D080DF5,$3B6E20C8,$4C69105E,$D56041E4,
|
||||||
|
$A2677172,$3C03E4D1,$4B04D447,$D20D85FD,$A50AB56B,
|
||||||
|
$35B5A8FA,$42B2986C,$DBBBC9D6,$ACBCF940,$32D86CE3,
|
||||||
|
$45DF5C75,$DCD60DCF,$ABD13D59,$26D930AC,$51DE003A,
|
||||||
|
$C8D75180,$BFD06116,$21B4F4B5,$56B3C423,$CFBA9599,
|
||||||
|
$B8BDA50F,$2802B89E,$5F058808,$C60CD9B2,$B10BE924,
|
||||||
|
$2F6F7C87,$58684C11,$C1611DAB,$B6662D3D,$76DC4190,
|
||||||
|
$1DB7106,$98D220BC,$EFD5102A,$71B18589,$6B6B51F,
|
||||||
|
$9FBFE4A5,$E8B8D433,$7807C9A2,$F00F934,$9609A88E,
|
||||||
|
$E10E9818,$7F6A0DBB,$86D3D2D,$91646C97,$E6635C01,
|
||||||
|
$6B6B51F4,$1C6C6162,$856530D8,$F262004E,$6C0695ED,
|
||||||
|
$1B01A57B,$8208F4C1,$F50FC457,$65B0D9C6,$12B7E950,
|
||||||
|
$8BBEB8EA,$FCB9887C,$62DD1DDF,$15DA2D49,$8CD37CF3,
|
||||||
|
$FBD44C65,$4DB26158,$3AB551CE,$A3BC0074,$D4BB30E2,
|
||||||
|
$4ADFA541,$3DD895D7,$A4D1C46D,$D3D6F4FB,$4369E96A,
|
||||||
|
$346ED9FC,$AD678846,$DA60B8D0,$44042D73,$33031DE5,
|
||||||
|
$AA0A4C5F,$DD0D7CC9,$5005713C,$270241AA,$BE0B1010,
|
||||||
|
$C90C2086,$5768B525,$206F85B3,$B966D409,$CE61E49F,
|
||||||
|
$5EDEF90E,$29D9C998,$B0D09822,$C7D7A8B4,$59B33D17,
|
||||||
|
$2EB40D81,$B7BD5C3B,$C0BA6CAD,$EDB88320,$9ABFB3B6,
|
||||||
|
$3B6E20C,$74B1D29A,$EAD54739,$9DD277AF,$4DB2615,
|
||||||
|
$73DC1683,$E3630B12,$94643B84,$D6D6A3E,$7A6A5AA8,
|
||||||
|
$E40ECF0B,$9309FF9D,$A00AE27,$7D079EB1,$F00F9344,
|
||||||
|
$8708A3D2,$1E01F268,$6906C2FE,$F762575D,$806567CB,
|
||||||
|
$196C3671,$6E6B06E7,$FED41B76,$89D32BE0,$10DA7A5A,
|
||||||
|
$67DD4ACC,$F9B9DF6F,$8EBEEFF9,$17B7BE43,$60B08ED5,
|
||||||
|
$D6D6A3E8,$A1D1937E,$38D8C2C4,$4FDFF252,$D1BB67F1,
|
||||||
|
$A6BC5767,$3FB506DD,$48B2364B,$D80D2BDA,$AF0A1B4C,
|
||||||
|
$36034AF6,$41047A60,$DF60EFC3,$A867DF55,$316E8EEF,
|
||||||
|
$4669BE79,$CB61B38C,$BC66831A,$256FD2A0,$5268E236,
|
||||||
|
$CC0C7795,$BB0B4703,$220216B9,$5505262F,$C5BA3BBE,
|
||||||
|
$B2BD0B28,$2BB45A92,$5CB36A04,$C2D7FFA7,$B5D0CF31,
|
||||||
|
$2CD99E8B,$5BDEAE1D,$9B64C2B0,$EC63F226,$756AA39C,
|
||||||
|
$26D930A,$9C0906A9,$EB0E363F,$72076785,$5005713,
|
||||||
|
$95BF4A82,$E2B87A14,$7BB12BAE,$CB61B38,$92D28E9B,
|
||||||
|
$E5D5BE0D,$7CDCEFB7,$BDBDF21,$86D3D2D4,$F1D4E242,
|
||||||
|
$68DDB3F8,$1FDA836E,$81BE16CD,$F6B9265B,$6FB077E1,
|
||||||
|
$18B74777,$88085AE6,$FF0F6A70,$66063BCA,$11010B5C,
|
||||||
|
$8F659EFF,$F862AE69,$616BFFD3,$166CCF45,$A00AE278,
|
||||||
|
$D70DD2EE,$4E048354,$3903B3C2,$A7672661,$D06016F7,
|
||||||
|
$4969474D,$3E6E77DB,$AED16A4A,$D9D65ADC,$40DF0B66,
|
||||||
|
$37D83BF0,$A9BCAE53,$DEBB9EC5,$47B2CF7F,$30B5FFE9,
|
||||||
|
$BDBDF21C,$CABAC28A,$53B39330,$24B4A3A6,$BAD03605,
|
||||||
|
$CDD70693,$54DE5729,$23D967BF,$B3667A2E,$C4614AB8,
|
||||||
|
$5D681B02,$2A6F2B94,$B40BBE37,$C30C8EA1,$5A05DF1B,
|
||||||
|
$2D02EF8D}
|
||||||
|
|
||||||
|
function FileCRC(fs: TFileStream): Integer;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function FileCRC(fs: TFileStream): Integer;
|
||||||
|
const
|
||||||
|
CRCBlock = 4096;
|
||||||
|
var
|
||||||
|
CRCTable: Array[0..255] of LongWord;
|
||||||
|
c: LongWord; //!!! this must be an unsigned 32-bits var!
|
||||||
|
Block: Array[0..CRCBlock-1] of Byte;
|
||||||
|
i,j,bytesread: Integer;
|
||||||
|
begin
|
||||||
|
//this used to be the InitCRC procedure
|
||||||
|
For i:= 0 To 255 do begin
|
||||||
|
c:= i;
|
||||||
|
For j:= 0 To 7 do begin
|
||||||
|
If (c And 1)=0 Then begin
|
||||||
|
c:= (c div 2);
|
||||||
|
end Else begin
|
||||||
|
c:= (c div 2) Xor $EDB88320;
|
||||||
|
End;
|
||||||
|
end;
|
||||||
|
CRCTable[i]:= c;
|
||||||
|
end;
|
||||||
|
// InitCRC procedure end;
|
||||||
|
c:=$FFFFFFFF;
|
||||||
|
fs.Seek(0,soFromBeginning);
|
||||||
|
for i:=0 to (fs.Size div CRCBlock)+1 do begin
|
||||||
|
bytesread:=fs.Read(Block,CRCBlock);
|
||||||
|
for j:=0 to bytesread-1 do begin
|
||||||
|
c:=CRCTable[(c and $FF) xor Block[j]] xor (((c and $FFFFFF00) div 256) and $FFFFFF);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
FileCRC:=c xor $FFFFFFFF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
|
@ -1,6 +1,6 @@
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "..\ExDLL\exdll.h"
|
#include "..\..\..\ExDLL\exdll.h"
|
||||||
|
|
||||||
int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest);
|
int DoPatch(HANDLE hPatch, HANDLE hSource, HANDLE hDest);
|
||||||
void strcopy(char *tgt, const char *src);
|
void strcopy(char *tgt, const char *src);
|
|
@ -53,7 +53,7 @@ BSC32=bscmake.exe
|
||||||
# ADD BSC32 /nologo
|
# ADD BSC32 /nologo
|
||||||
LINK32=link.exe
|
LINK32=link.exe
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"..\..\Plugins\VPatch.dll" /opt:nowin98
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"_DllMainCRTStartup" /dll /machine:I386 /nodefaultlib /out:"..\..\..\..\Plugins\VPatch.dll" /opt:nowin98
|
||||||
# SUBTRACT LINK32 /pdb:none
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "vpatchdll - Win32 Debug"
|
!ELSEIF "$(CFG)" == "vpatchdll - Win32 Debug"
|
Loading…
Add table
Add a link
Reference in a new issue