cheat-engine/Cheat Engine/frmSaveMemoryRegionUnit.pas
2021-11-16 20:58:25 +01:00

250 lines
6.2 KiB
ObjectPascal
Executable file

unit frmSaveMemoryRegionUnit;
{$MODE Delphi}
interface
uses
{$ifdef darwin}
macport,
{$endif}
LCLIntf, Messages, SysUtils, Classes, Graphics, Controls, Forms, symbolhandler,
Dialogs, StdCtrls, NewKernelHandler, CEFuncProc, ExtCtrls, LResources, Menus, betterControls;
type
{ TfrmSaveMemoryRegion }
TfrmSaveMemoryRegion = class(TForm)
smrImageList: TImageList;
miClearList: TMenuItem;
Panel1: TPanel;
Panel2: TPanel;
Label1: TLabel;
lbRegions: TListBox;
PopupMenu1: TPopupMenu;
SaveDialog1: TSaveDialog;
DontInclude: TCheckBox;
Panel3: TPanel;
Button1: TButton;
Button2: TButton;
Panel4: TPanel;
Label2: TLabel;
Label3: TLabel;
editFrom: TEdit;
editTo: TEdit;
Button3: TButton;
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure DontIncludeClick(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure lbRegionsDblClick(Sender: TObject);
procedure miClearListClick(Sender: TObject);
private
{ Private declarations }
alreadywarned: boolean;
public
{ Public declarations }
end;
var
frmSaveMemoryRegion: TfrmSaveMemoryRegion;
implementation
uses ProcessHandlerUnit, Parsers, mainunit2;
resourcestring
rsPleaseAddAtLeastOneAddressRegionToTheList = 'Please add at least one address region to the list';
rsNotAllTheMemoryWasReadableIn = 'Not all the memory was readable in';
rsNoStartAddress = 'If you don''t include the header data you''ll have to specify the startaddress yourself when loading the file(That means '+strCheatEngine+' won''t fill in the '
+'startaddress text field when loaded for you)';
rsIsNotAValidAddress = '%s is not a valid address';
type Tregion=class
public
fromaddress,toaddress:ptrint;
constructor create(fa,ta:ptrint);
end;
constructor TRegion.create(fa,ta:ptrint);
begin
fromaddress:=fa;
toaddress:=ta;
inherited create;
end;
procedure TfrmSaveMemoryRegion.Button2Click(Sender: TObject);
begin
close;
end;
procedure TfrmSaveMemoryRegion.Button1Click(Sender: TObject);
var f: TFilestream;
fromaddress,toaddress: qword;
temp: ptrUint;
size: dword;
buf: array of pointer;
i: integer;
unreadable: array of integer;
s: string;
begin
if lbregions.Items.Count=0 then
begin
if (editfrom.Text<>'') and (editto.Text<>'') then
button3.click
else
raise exception.Create(rsPleaseAddAtLeastOneAddressRegionToTheList);
end;
setlength(unreadable,0);
setlength(buf,lbregions.items.count);
for i:=0 to lbregions.items.count-1 do
begin
fromaddress:=tregion(lbregions.Items.Objects[i]).fromaddress;
toaddress:=tregion(lbregions.Items.Objects[i]).toaddress;
size:=toaddress-fromaddress+1;
getmem(buf[i],size);
if (not readprocessmemory(processhandle,pointer(ptrUint(fromaddress)),buf[i],size,temp)) then
begin
if (temp<>size) then
begin
setlength(unreadable,length(unreadable)+1);
unreadable[length(unreadable)-1]:=i;
end;
end;
end;
if length(unreadable)>0 then
begin
for i:=0 to length(buf)-1 do
freememandnil(buf[i]);
s:=rsNotAllTheMemoryWasReadableIn;
for i:=0 to length(unreadable)-1 do
s:=s+' '+lbregions.items[unreadable[i]];
raise exception.Create(s);
end;
if savedialog1.Execute then
begin
f:=TFilestream.Create(savedialog1.FileName,fmCreate);
try
if not dontinclude.checked then
begin
f.WriteBuffer(pchar('CHEATENGINE')^,11);
temp:=3; //version
f.WriteBuffer(temp,4);
end;
for i:=0 to length(buf)-1 do
begin
if not dontinclude.checked then
begin
fromaddress:=tregion(lbregions.Items.Objects[i]).fromaddress;
toaddress:=tregion(lbregions.Items.Objects[i]).toaddress;
size:=toaddress-fromaddress+1;
f.WriteBuffer(fromaddress,8);
f.WriteBuffer(size,4);
end;
f.WriteBuffer(buf[i]^,size);
freememandnil(buf[i]);
end;
modalresult:=mrOK;
finally
f.Free;
end;
end;
end;
procedure TfrmSaveMemoryRegion.DontIncludeClick(Sender: TObject);
begin
if not alreadywarned then
if DontInclude.Checked then
begin
alreadywarned:=true;
messagedlg(rsNoStartAddress, mtInformation, [mbok], 0);
end;
end;
procedure TfrmSaveMemoryRegion.Button3Click(Sender: TObject);
var fromaddress,toaddress:qword;
begin
try
fromaddress:=StrToQWordEx('$'+editfrom.Text);
except
fromaddress:=symhandler.getAddressFromName(editfrom.Text);
end;
try
toaddress:=StrToQWordEx('$'+editto.text);
except
toaddress:=symhandler.getAddressFromName(editto.text);
end;
if fromaddress>toaddress then
begin //xor swap
fromaddress:=fromaddress xor toaddress;
toaddress:=toaddress xor fromaddress;
fromaddress:=fromaddress xor toaddress;
end;
lbregions.Items.AddObject(inttohex(fromaddress,8)+'-'+inttohex(toaddress,8),tregion.Create(fromaddress,toaddress));
dontinclude.Enabled:=lbregions.Items.Count<=1;
if lbregions.Items.Count>1 then dontinclude.Checked:=false;
end;
procedure TfrmSaveMemoryRegion.FormShow(Sender: TObject);
begin
editfrom.ClientWidth:=canvas.textwidth('DDDDDDDDDDDD');
editTo.ClientWidth:=editfrom.ClientWidth;
end;
procedure TfrmSaveMemoryRegion.lbRegionsDblClick(Sender: TObject);
var i: integer;
begin
if lbregions.ItemIndex<>-1 then
begin
tregion(lbregions.Items.Objects[lbregions.ItemIndex]).Free;
i:=0;
while i<lbregions.Count do
begin
if lbregions.Selected[i] then
lbregions.Items.Delete(i)
else
inc(i);
end;
end;
dontinclude.Enabled:=lbregions.Items.Count<=1;
end;
procedure TfrmSaveMemoryRegion.miClearListClick(Sender: TObject);
begin
while lbRegions.Count>0 do
begin
tregion(lbregions.Items.Objects[0]).Free;
lbregions.Items.Delete(0);
end;
end;
initialization
{$i frmSaveMemoryRegionUnit.lrs}
end.