mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
447 lines
9.7 KiB
ObjectPascal
Executable file
447 lines
9.7 KiB
ObjectPascal
Executable file
unit Unit1;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
jwawindows, windows, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
|
|
GamePanel, renderobject,glext, GL,glu, player,scoreboard, target, bullet, guitextobject,
|
|
staticguiobject, gamebase, levelselect, gametutorial1, gametutorial2, gametutorial3;
|
|
|
|
type
|
|
|
|
|
|
|
|
{ TForm1 }
|
|
TForm1 = class(TForm)
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
private
|
|
{ private declarations }
|
|
p: TGamePanel;
|
|
currentGame: TGameBase;
|
|
|
|
lasttick: qword;
|
|
codebase: ptruint;
|
|
codesize: ptruint;
|
|
|
|
|
|
integrityCheckThread: TThread;
|
|
procedure integritycheckcheck;
|
|
|
|
procedure startgame2(sender: TObject);
|
|
procedure startgame3(sender: TObject);
|
|
procedure finishedTutorial(sender: TObject);
|
|
procedure GameSelect(sender: TObject);
|
|
|
|
|
|
procedure renderGame(sender: TObject);
|
|
procedure gametick(sender: TObject);
|
|
function KeyHandler(GamePanel: TObject; keventtype: integer; Key: Word; Shift: TShiftState):boolean;
|
|
public
|
|
{ public declarations }
|
|
end;
|
|
|
|
var
|
|
Form1: TForm1;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
{ TForm1 }
|
|
|
|
uses registry, md5, frmHelpUnit;
|
|
|
|
type
|
|
TIntegrityCheckThread=class(tthread)
|
|
private
|
|
codebase: ptruint;
|
|
codesize: integer;
|
|
integrityCheckValue: dword;
|
|
function check1: dword;
|
|
function check2: dword;
|
|
function check3: dword;
|
|
procedure valid;
|
|
procedure invalid;
|
|
public
|
|
|
|
heartbeat: qword;
|
|
lastcheckwasvalid: boolean;
|
|
procedure execute; override;
|
|
procedure docheck;
|
|
end;
|
|
|
|
|
|
function peinfo_getcodesize(header: pointer; headersize: integer=0): dword;
|
|
var
|
|
ImageNTHeader: PImageNtHeaders;
|
|
begin
|
|
result:=0;
|
|
|
|
if (headersize=0) or (PImageDosHeader(header)^._lfanew<=headersize-sizeof(TImageNtHeaders)) then
|
|
begin
|
|
ImageNTHeader:=PImageNtHeaders(ptrUint(header)+PImageDosHeader(header)^._lfanew);
|
|
result:=ImageNTHeader^.OptionalHeader.SizeOfCode;
|
|
end;
|
|
end;
|
|
|
|
function peinfo_getdatabase(header: pointer; headersize: integer=0): ptrUint;
|
|
var
|
|
ImageNTHeader: PImageNtHeaders;
|
|
begin
|
|
result:=0;
|
|
if (headersize=0) or (PImageDosHeader(header)^._lfanew<=headersize-sizeof(TImageNtHeaders)) then
|
|
begin
|
|
ImageNTHeader:=PImageNtHeaders(ptrUint(header)+PImageDosHeader(header)^._lfanew);
|
|
{$ifndef cpu64}
|
|
result:=ImageNTHeader^.OptionalHeader.BaseOfData;
|
|
{$endif}
|
|
end;
|
|
end;
|
|
|
|
function peinfo_getcodebase(header: pointer; headersize: integer=0): ptrUint;
|
|
var
|
|
ImageNTHeader: PImageNtHeaders;
|
|
begin
|
|
result:=0;
|
|
if (headersize=0) or (PImageDosHeader(header)^._lfanew<=headersize-sizeof(TImageNtHeaders)) then
|
|
begin
|
|
ImageNTHeader:=PImageNtHeaders(ptrUint(header)+PImageDosHeader(header)^._lfanew);
|
|
result:=ImageNTHeader^.OptionalHeader.BaseOfCode;
|
|
end;
|
|
end;
|
|
|
|
function peinfo_getEntryPoint(header: pointer; headersize: integer=0): ptrUint;
|
|
var
|
|
ImageNTHeader: PImageNtHeaders;
|
|
begin
|
|
result:=0;
|
|
if (headersize=0) or (PImageDosHeader(header)^._lfanew<=headersize-sizeof(TImageNtHeaders)) then
|
|
begin
|
|
ImageNTHeader:=PImageNtHeaders(ptrUint(header)+PImageDosHeader(header)^._lfanew);
|
|
result:=ImageNTHeader^.OptionalHeader.AddressOfEntryPoint;
|
|
end;
|
|
|
|
end;
|
|
|
|
function peinfo_getheadersize(header: pointer): dword;
|
|
var
|
|
ImageNTHeader: PImageNtHeaders;
|
|
begin
|
|
result:=0;
|
|
if PImageDosHeader(header)^.e_magic<>IMAGE_DOS_SIGNATURE then exit;
|
|
|
|
ImageNTHeader:=PImageNtHeaders(ptrUint(header)+PImageDosHeader(header)^._lfanew);
|
|
if ptrUint(ImageNTHeader)-ptrUint(header)>$1000 then exit;
|
|
if ImageNTHeader^.Signature<>IMAGE_NT_SIGNATURE then exit;
|
|
|
|
result:=ImageNTHeader^.OptionalHeader.SizeOfHeaders;
|
|
end;
|
|
|
|
function peinfo_getimagesize(header: pointer): dword;
|
|
var
|
|
ImageNTHeader: PImageNtHeaders;
|
|
begin
|
|
ImageNTHeader:=PImageNtHeaders(ptrUint(header)+PImageDosHeader(header)^._lfanew);
|
|
result:=ImageNTHeader^.OptionalHeader.SizeOfImage;
|
|
end;
|
|
|
|
|
|
function TIntegrityCheckThread.check1:dword;
|
|
var
|
|
mem: pword;
|
|
r: dword;
|
|
i: integer;
|
|
begin
|
|
mem:=pword(codebase);
|
|
r:=$deadbeef;
|
|
for i:=0 to (codesize div 2)-1 do
|
|
begin
|
|
r:=r xor mem[i];
|
|
inc(r,12);
|
|
end;
|
|
|
|
result:=r;
|
|
end;
|
|
|
|
function TIntegrityCheckThread.check2:dword;
|
|
var
|
|
mem: pword;
|
|
r: dword;
|
|
i: integer;
|
|
begin
|
|
mem:=pword(codebase);
|
|
r:=$feeddead;
|
|
for i:=0 to (codesize div 2)-1 do
|
|
begin
|
|
r:=r + mem[i];
|
|
end;
|
|
|
|
result:=r;
|
|
end;
|
|
|
|
function TIntegrityCheckThread.check3:dword;
|
|
var
|
|
mem: pword;
|
|
r: dword;
|
|
i: integer;
|
|
begin
|
|
mem:=pword(codebase);
|
|
r:=$cececece;
|
|
for i:=0 to (codesize div 2)-1 do
|
|
begin
|
|
r:=r xor mem[i];
|
|
dec(r,77);
|
|
end;
|
|
|
|
result:=r;
|
|
end;
|
|
|
|
procedure TIntegrityCheckThread.valid;
|
|
var
|
|
i: integer;
|
|
s: string;
|
|
begin
|
|
s:=form1.caption;
|
|
i:=Pos(' (Integrity check error)',s);
|
|
if i>0 then //valid now
|
|
begin
|
|
form1.caption:=copy(form1.caption,1,i);
|
|
end;
|
|
end;
|
|
|
|
procedure TIntegrityCheckThread.invalid;
|
|
var s: string;
|
|
begin
|
|
s:=form1.caption;
|
|
if Pos(' (Integrity check error)',s)=0 then
|
|
form1.caption:=form1.caption+' (Integrity check error)';
|
|
end;
|
|
|
|
procedure TIntegrityCheckThread.docheck;
|
|
var
|
|
c1,c2,c3: dword;
|
|
cf: dword;
|
|
begin
|
|
c1:=check1;
|
|
c2:=check2;
|
|
c3:=check3;
|
|
|
|
cf:=(c1 xor c2)+c3;
|
|
if cf=0 then inc(cf);
|
|
|
|
if integrityCheckValue=0 then
|
|
integrityCheckValue:=cf
|
|
else
|
|
begin
|
|
lastcheckwasvalid:=cf=integrityCheckValue;
|
|
if lastcheckwasvalid then
|
|
synchronize(@Valid)
|
|
else
|
|
synchronize(@Invalid);
|
|
end;
|
|
end;
|
|
|
|
procedure TIntegrityCheckThread.execute;
|
|
var
|
|
|
|
m: pointer;
|
|
begin
|
|
m:=pointer(GetModuleHandle(nil));
|
|
|
|
codebase:=ptruint(m)+peinfo_getcodebase(m);
|
|
codesize:=peinfo_getcodesize(m);
|
|
|
|
while not terminated do
|
|
begin
|
|
heartbeat:=GetTickCount64;
|
|
docheck;
|
|
|
|
|
|
sleep(100);
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.gametick(sender:TObject);
|
|
var
|
|
currenttime: qword;
|
|
diff: qword;
|
|
begin
|
|
currenttime:=GetTickCount64;
|
|
diff:=currenttime-lasttick;
|
|
lasttick:=currenttime;
|
|
|
|
if currentgame<>nil then
|
|
currentgame.gametick(currenttime, diff);
|
|
end;
|
|
|
|
procedure TForm1.renderGame(sender: TObject);
|
|
begin
|
|
if currentgame<>nil then
|
|
currentgame.render;
|
|
end;
|
|
|
|
function TForm1.KeyHandler(GamePanel: TObject; keventtype: integer; Key: Word; Shift: TShiftState):boolean;
|
|
begin
|
|
if currentgame<>nil then
|
|
exit(currentgame.keyhandler(GamePanel, keventtype, key, shift))
|
|
else
|
|
result:=false;
|
|
end;
|
|
|
|
procedure TForm1.IntegrityCheckCheck;
|
|
var
|
|
itt: TIntegrityCheckThread;
|
|
hb: qword;
|
|
startwait: qword;
|
|
begin
|
|
itt:=TIntegrityCheckThread(integrityCheckThread);
|
|
itt.docheck;
|
|
|
|
hb:=itt.heartbeat;
|
|
if ((gettickcount64-hb)>1000) then
|
|
begin
|
|
startwait:=gettickcount64;
|
|
while (gettickcount64-startwait)<5000 do //wait 5 seconds max
|
|
begin
|
|
if itt.heartbeat>hb then exit;
|
|
CheckSynchronize(100);
|
|
end;
|
|
|
|
itt.Terminate;
|
|
itt.WaitFor;
|
|
itt.lastcheckwasvalid:=false;
|
|
form1.caption:=form1.caption+' (total integrity check failure)';
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
procedure TForm1.finishedTutorial(sender: TObject);
|
|
var
|
|
s,s2: string;
|
|
mem: pword;
|
|
r: dword;
|
|
i: integer;
|
|
begin
|
|
if usedcheats then
|
|
begin
|
|
s:='winned';
|
|
s2:='. yay';
|
|
end
|
|
else
|
|
begin
|
|
s:='beaten';
|
|
|
|
IntegrityCheckCheck;
|
|
|
|
if TIntegrityCheckThread(integrityCheckThread).lastcheckwasvalid then
|
|
s2:=#13#10', and you have beaten the integrity check!'#13#10#13#10'Really well done!'
|
|
else
|
|
s2:='. Well done';
|
|
end;
|
|
|
|
|
|
showmessage(format('You have %s all 3 ''games'' %s!',[s,s2]));
|
|
ExitProcess(0);
|
|
end;
|
|
|
|
procedure TForm1.startgame3(sender: TObject);
|
|
begin
|
|
IntegrityCheckCheck;
|
|
|
|
if currentgame<>nil then
|
|
freeandnil(currentGame);
|
|
|
|
caption:='Step 3';
|
|
currentgame:=TGame3.create(p);
|
|
currentgame.OnWin:=@finishedTutorial; //todo someday: rpg kinda game, followed by an online 'game' (chatgame more likely)
|
|
|
|
frmHelp.Attach(self,'G3');
|
|
end;
|
|
|
|
|
|
procedure TForm1.startgame2(sender: TObject);
|
|
|
|
begin
|
|
IntegrityCheckCheck;
|
|
|
|
if currentgame<>nil then
|
|
freeandnil(currentGame);
|
|
|
|
caption:='Step 2';
|
|
currentgame:=TGame2.create(p);
|
|
currentgame.OnWin:=@startgame3;
|
|
frmHelp.Attach(self,'G2');
|
|
end;
|
|
|
|
procedure TForm1.GameSelect(sender: TObject);
|
|
var gs: TLevelSelect;
|
|
begin
|
|
IntegrityCheckCheck;
|
|
|
|
gs:=TLevelSelect(currentgame);
|
|
case gs.level of
|
|
1:
|
|
begin
|
|
if currentgame<>nil then
|
|
freeandnil(currentGame);
|
|
|
|
Caption:='Step 1';
|
|
currentGame:=TGame1.create(p);
|
|
currentGame.OnWin:=@startGame2;
|
|
end;
|
|
2: startgame2(sender);
|
|
3: startgame3(sender);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure TForm1.FormCreate(Sender: TObject);
|
|
begin
|
|
integrityCheckThread:=TIntegrityCheckThread.create(false);
|
|
end;
|
|
|
|
procedure TForm1.FormShow(Sender: TObject);
|
|
var reg: Tregistry;
|
|
begin
|
|
p:=TGamePanel.Create(Self);
|
|
p.OnGameRender:=@renderGame;
|
|
p.OnGameTick:=@gametick;
|
|
p.Align:=alClient;
|
|
p.parent:=self;
|
|
|
|
// startgame3(Self);
|
|
// startgame2(self);
|
|
|
|
reg:=tregistry.create;
|
|
if reg.OpenKey('\Software\Cheat Engine\GTutorial', false) then
|
|
begin
|
|
//if reg.ValueExists('This does not count as a solution for tutorial 1') then
|
|
begin
|
|
//level select screen
|
|
Caption:='Select Level';
|
|
currentGame:=TLevelSelect.create(p);
|
|
currentGame.OnWin:=@GameSelect;
|
|
end;
|
|
end;
|
|
|
|
//still here, so game1:
|
|
if currentgame=nil then
|
|
begin
|
|
IntegrityCheckCheck;
|
|
|
|
currentGame:=TGame1.create(p);
|
|
currentGame.OnWin:=@startGame2;
|
|
frmHelp.Attach(self,'G1');
|
|
end;
|
|
|
|
p.AddKeyEventHandler(@keyhandler);
|
|
lasttick:=GetTickCount64;
|
|
end;
|
|
|
|
end.
|
|
|