Jump to content
Tuts 4 You

[Delphi] Some perhaps helpfull Patch functions/procs


Gushe

Recommended Posts

Posted

Hello everybody. :)

While trying to create my own patcher with some extended features in Delphi, I created some functions that I could easy Copy-Paste to other patchers, and to ease-up further use.

The first one will Patch One byte at a specified Offset:

//Patches one byte at a certain Offset.
Procedure OffsetBytePatch(AppPath: string; Offset: Longint; PatchByte: byte);
var
PatchFile: File Of Byte;
begin
AssignFile(PatchFile , AppPath);
Reset(PatchFile);
Seek(PatchFile, Offset);
Write(PatchFile, PatchByte);
CloseFile(PatchFile);
end;

The second one will Read one byte at a certain offset, for use in eg. checking if already patched.

//Reads on byte at a certain Offset.
Function OffsetByteRead(AppPath: string; Offset: Longint; PatchByte: byte): byte;
var
PatchFile: File Of Byte;
ReadByte: Byte;
Count: integer;
begin
AssignFile(PatchFile, AppPath);
Reset(PatchFile);
Seek(PatchFile, Offset);
BlockRead(PatchFile, ReadByte, 1, Count); if Count = 1 then
result := ReadByte
else result := NULL;
end;

A Third one will patch a String, starting at a certain offset. Il will automatically keep the same size and fill remaing space with 00's. (So that whole string gets nicely patched). Perhaps usefull in eg. Custom caption changes.

//Patches a String into an Executable, Starting from a certain offset.
// Remaining Bytes will be filled with 00's.
Procedure OffsetStringPatch(AppPath: string; Offset: Longint; PatchString: string; LengthOfBlock: integer);
var
PatchFile: File Of Byte;
ByteArray: Array Of Byte;
I: integer;
begin
PatchString := PatchString + StringOfChar('0', (LengthOfBlock - (LengthOfBlock - Length(PatchString))) * 2);for I := 1 to Length(PatchString) do begin
ByteArray[I] := StrToInt(('$' + MidStr(PatchString, 1, 2)));
Delete(PatchString, 1, 2);
end; AssignFile(PatchFile, AppPath);
Reset(PatchFile);
Seek(PatchFile, Offset); BlockWrite(PatchFile, ByteArray, Length(ByteArray)); CloseFile(PatchFile);
end;

The fourth one will, how convenient, Read a string, starting at a certain offset. Might be helpfull in layout changes, to make a live editor.

//Reads and Returns the String, starting at a certain Offset for LengthOfBlock bytes long.
Function OffsetStringRead(AppPath: string; Offset: Longint; LengthOfBlock: integer): string;
var
PatchFile: File Of Byte;
ByteArray: Array Of Byte;
I: integer;
resultString: string;
begin
AssignFile(PatchFile, AppPath);
Reset(PatchFile);
Seek(PatchFile, Offset); BlockRead(PatchFile, byteArray, LengthOfBlock); CloseFile(PatchFile);for I := 1 to Length(byteArray) do begin
resultString := resultString + Chr(strtoint('$' + inttostr(byteArray[I])));
end;

Note: I just created these for my own use. I'm just posting them here because they might perhaps be helpfull for any beginner. Feel free to use and edit them as much as you like.

If you have any suggestions for me, I'd love to hear it. :)

Greetingz,

GuShe

  • 4 weeks later...
Posted

I would recommend using Win32 API, not just for efficient, but it's faster also and safer, you never know what could happen with Delphi's VCL.

nice snippets though, very basic but could be useful for others.

Posted
but it's faster also and safer, you never know what could happen with Delphi's VCL.

faster - yes

but safer ???

You have to do all sorts of error checking, allocate mem, deal with pointers and weird stuff.

VCL is far easier and the speed increase is meaningless compared to the poor performance of disk access...

  • 3 months later...
Posted (edited)
unit Unit2;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm2 = class(TForm)

Button1: TButton;

Edit1: TEdit;

Edit2: TEdit;

Button2: TButton;

OpenDialog1: TOpenDialog;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form2: TForm2;

implementation

{$R *.dfm}

function MidStr

(Const Str: String; From, Size: Word): String;

begin

MidStr := Copy(Str, From, Size)

end;

Procedure OffsetStringPatch(AppPath: string; Offset: Longint; PatchString: string; LengthOfBlock: integer);

var

PatchFile: File Of Byte;

ByteArray: Array Of Byte;

I: integer;

begin

PatchString := PatchString + StringOfChar('0', (LengthOfBlock - (LengthOfBlock - Length(PatchString))) * 2);

for I := 1 to Length(PatchString) do begin

ByteArray := StrToInt(('$' + MidStr(PatchString, 1, 2)));

Delete(PatchString, 1, 2);

end;

AssignFile(PatchFile, AppPath);

Reset(PatchFile);

Seek(PatchFile, Offset);

BlockWrite(PatchFile, ByteArray, Length(ByteArray));

CloseFile(PatchFile);

end;

procedure TForm2.Button1Click(Sender: TObject);

begin

opendialog1.Execute() ;

edit1.Text:=opendialog1.FileName;

end;

procedure TForm2.Button2Click(Sender: TObject);

begin

OffsetStringPatch(edit1.Text,$00451000,'696e',2)

end;

end.

and i got:

deeeeeeeeeeeeeeeeeeeeee.png

:( (((

deeeeeeeeeeeeeeeeeeeeeez.png

Edited by 6748222
Posted

Yes, there is something to be slightly improved:

SetLength(byteArray,Length(PatchString)); // You must allocate memory for  the array
for I := 0 to Length(PatchString) - 1 do begin // A dynamic array starts its index by 0...
ByteArray[I] := StrToInt(('$' + MidStr(PatchString, 1, 2)));
Delete(PatchString, 1, 2);
end;

Thanks for sharing your code Gushe ;)

Cheers

Nacho_dj

Posted (edited)

Thanks 4 fast replay :wub:

hey! its works now :wub::wub::wub::wub:

Edited by 6748222
Posted

Good stuff , thanx

Posted

I just noticed, why did you use BlockRead and not Read, it's a single Byte so BlockRead would be useful to read more than a single byte.

Posted
I just noticed, why did you use BlockRead and not Read, it's a single Byte so BlockRead would be useful to read more than a single byte.

Not really getting what you're trying to say. :lol:

Posted
I just noticed, why did you use BlockRead and not Read, it's a single Byte so BlockRead would be useful to read more than a single byte.

Not really getting what you're trying to say. :lol:

Read() - Read data from a binary or text file

BlockRead() - Reads a block of data records from an untyped binary file

So if he's reading a single byte, why not just use Read() ?

Posted
I just noticed, why did you use BlockRead and not Read, it's a single Byte so BlockRead would be useful to read more than a single byte.

Not really getting what you're trying to say. :lol:

Read() - Read data from a binary or text file

BlockRead() - Reads a block of data records from an untyped binary file

So if he's reading a single byte, why not just use Read() ?

Because it would add an extra if statement, resulting in nearly no remarkable better performance, right? :)

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...