mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
11563 lines
312 KiB
ObjectPascal
Executable file
11563 lines
312 KiB
ObjectPascal
Executable file
unit MainUnit;
|
|
|
|
//{$MODE Delphi}
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$ifdef darwin}
|
|
LResources, LCLIntf, LCLProc, MacOSAll,MacOSXPosix, LMessages, Classes, Forms, Controls, Messages,
|
|
ComCtrls, stdctrls,sysutils, graphics,menus, dialogs, extctrls, math, buttons,
|
|
ImgList, ActnList, registry, Clipbrd, NewKernelHandler, Assemblerunit,
|
|
symbolhandler,autoassembler, addresslist, CustomTypeHandler, MemoryRecordUnit,memscan,
|
|
SaveFirstScan, foundlisthelper, disassembler, tablist, simpleaobscanner,frmSelectionlistunit,
|
|
lua, LuaHandler, lauxlib, lualib,CEDebugger,debughelper ,speedhack2, groupscancommandparser,
|
|
frmautoinjectunit, commonTypeDefs, unrandomizer,savedscanhandler,luafile,hotkeyhandler,
|
|
genericHotkey,LazLogger,lcltype,syncobjs, SyncObjs2,FrmMemoryRecordDropdownSettingsUnit,
|
|
ceguicomponents,formdesignerunit,xmlutils,vartypestrings,plugin,byteinterpreter,
|
|
MenuItemExtra,frmgroupscanalgoritmgeneratorunit
|
|
|
|
, macport,LCLVersion, UTF8Process, macportdefines, fgl, networkInterfaceApi,
|
|
networkInterface,
|
|
|
|
betterControls; //last one
|
|
{$endif}
|
|
|
|
{$ifdef windows}
|
|
jwaWindows, Windows, LCLIntf, LCLProc, Messages, SysUtils, Classes, SyncObjs,
|
|
SyncObjs2, Graphics,
|
|
Controls, Forms, ComCtrls, StdCtrls, Menus, Buttons, shellapi,
|
|
imagehlp, ExtCtrls, Dialogs, Clipbrd, CEDebugger, kerneldebugger, assemblerunit,
|
|
hotkeyhandler, registry, Math, ImgList, commctrl, NewKernelHandler,
|
|
unrandomizer, symbolhandler, ActnList, LResources, hypermode, memscan,
|
|
autoassembler, plugin, savefirstscan, menuitemExtra, speedhack2, AccessCheck,
|
|
foundlisthelper, disassembler, peinfounit, PEInfoFunctions,
|
|
simpleaobscanner, pointervaluelist, ManualModuleLoader, debughelper,
|
|
frmRegistersunit, ctypes, addresslist, addresslisthandlerunit, memoryrecordunit,
|
|
windows7taskbar, tablist, DebuggerInterface, vehdebugger, tableconverter,
|
|
customtypehandler, lua, luahandler, lauxlib, lualib, frmSelectionlistunit,
|
|
htmlhelp, win32int, {defaulttranslator,} fileaccess, formdesignerunit,
|
|
ceguicomponents, frmautoinjectunit, cesupport, trainergenerator, genericHotkey,
|
|
luafile, xmplayer_server, sharedMemory{$ifdef windows}, win32proc{$endif},
|
|
vmxfunctions, FileUtil, networkInterfaceApi, networkconfig, d3dhookUnit, PNGcomn,
|
|
FPimage, byteinterpreter, frmgroupscanalgoritmgeneratorunit, vartypestrings,
|
|
groupscancommandparser, GraphType, IntfGraphics, RemoteMemoryManager,
|
|
DBK64SecondaryLoader, savedscanhandler, debuggertypedefinitions, networkInterface,
|
|
FrmMemoryRecordDropdownSettingsUnit, xmlutils, zstream, zstreamext, commonTypeDefs,
|
|
VirtualQueryExCache, LazLogger, LazUTF8, LCLVersion, fgl, betterControls;
|
|
{$endif}
|
|
//the following are just for compatibility
|
|
|
|
|
|
|
|
const
|
|
copypasteversion = 4;
|
|
|
|
const
|
|
wm_freedebugger = WM_USER + 1;
|
|
|
|
const
|
|
//wm_scandone = WM_USER + 2;
|
|
wm_pluginsync = WM_USER + 3;
|
|
|
|
wm_showerror = WM_USER + 4;
|
|
|
|
//scantabs
|
|
type
|
|
TProcessOpenedEvent=procedure(processid: THandle; processhandle: DWORD; caption: string) of object;
|
|
|
|
|
|
TScanState = record
|
|
alignsizechangedbyuser: boolean;
|
|
compareToSavedScan: boolean;
|
|
currentlySelectedSavedResultname: string; //I love long variable names
|
|
|
|
compareToColumn: integer;
|
|
|
|
cbCompareToSavedScan: record
|
|
visible: boolean;
|
|
end;
|
|
lblcompareToSavedScan: record
|
|
Caption: string;
|
|
Visible: boolean;
|
|
end;
|
|
|
|
|
|
|
|
|
|
FromAddress: record
|
|
Text: string;
|
|
end;
|
|
|
|
ToAddress: record
|
|
Text: string;
|
|
end;
|
|
|
|
cbReadOnly: record
|
|
Checked: boolean;
|
|
end;
|
|
|
|
cbfastscan: record
|
|
Checked: boolean;
|
|
end;
|
|
|
|
cbunicode: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
cbcodepage: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
cbnot: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
cbLuaformula: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
cbNewLuaState: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
cbRepeatUntilStopped: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
|
|
cbCaseSensitive: record
|
|
checked: boolean;
|
|
visible: boolean;
|
|
end;
|
|
|
|
edtAlignment: record
|
|
Text: string;
|
|
Enabled: boolean;
|
|
end;
|
|
|
|
rbFsmAligned:record
|
|
checked: boolean;
|
|
end;
|
|
|
|
|
|
cbpercentage: record
|
|
exists: boolean;
|
|
Checked: boolean;
|
|
end;
|
|
|
|
|
|
floatpanel: record
|
|
Visible: boolean;
|
|
rounded: boolean;
|
|
roundedextreme: boolean;
|
|
truncated: boolean;
|
|
end;
|
|
|
|
rbbit: record
|
|
Visible: boolean;
|
|
Enabled: boolean;
|
|
Checked: boolean;
|
|
end;
|
|
|
|
rbdec: record
|
|
Visible: boolean;
|
|
Enabled: boolean;
|
|
Checked: boolean;
|
|
end;
|
|
|
|
cbHexadecimal: record
|
|
Visible: boolean;
|
|
Checked: boolean;
|
|
Enabled: boolean;
|
|
end;
|
|
|
|
gbScanOptionsEnabled: boolean;
|
|
|
|
scantype: record
|
|
options: string;
|
|
ItemIndex: integer;
|
|
Enabled: boolean;
|
|
dropdowncount: integer;
|
|
end;
|
|
|
|
vartype: record
|
|
//options: TStringList;
|
|
ItemIndex: integer;
|
|
Enabled: boolean;
|
|
end;
|
|
|
|
|
|
memscan: TMemscan;
|
|
foundlist: TFoundList;
|
|
|
|
|
|
scanvalue: record
|
|
Visible: boolean;
|
|
Text: string;
|
|
end;
|
|
|
|
scanvalue2: record
|
|
exists: boolean;
|
|
Text: string;
|
|
end;
|
|
|
|
firstscanstate: record
|
|
Caption: string;
|
|
Enabled: boolean;
|
|
end;
|
|
|
|
nextscanstate: record
|
|
Enabled: boolean;
|
|
end;
|
|
|
|
btnFirst: record
|
|
tag: integer;
|
|
end;
|
|
|
|
foundlist3: record
|
|
ItemIndex: integer;
|
|
end;
|
|
foundlistDisplayOverride: integer;
|
|
|
|
|
|
cbfloatSimple: record
|
|
Checked: boolean;
|
|
end;
|
|
|
|
end;
|
|
PScanState = ^TScanState;
|
|
|
|
|
|
type
|
|
TFlash = class(TThread)
|
|
public
|
|
procedure Execute; override;
|
|
procedure col;
|
|
end;
|
|
|
|
|
|
type
|
|
TToggleWindows = class(TThread)
|
|
private
|
|
public
|
|
constructor Create(CreateSuspended: boolean);
|
|
procedure Execute; override;
|
|
end;
|
|
|
|
type
|
|
TAutoAttachThread=class(TThread)
|
|
private
|
|
fInterval: integer;
|
|
public
|
|
CurrentProcessList: TStringList;
|
|
procedure autoattachcheck;
|
|
constructor Create(CreateSuspended: boolean);
|
|
procedure Execute; override;
|
|
published
|
|
property Interval: integer read fInterval write fInterval;
|
|
end;
|
|
|
|
|
|
|
|
type
|
|
grouptype = array[1..6] of boolean;
|
|
|
|
|
|
type
|
|
|
|
{ TMainForm }
|
|
|
|
TFreezeThread=class(TThread)
|
|
private
|
|
fAddressList: TAddresslist;
|
|
freezeInterval: integer;
|
|
procedure applyFreeze;
|
|
public
|
|
procedure Execute; override;
|
|
constructor Create(AddressList: TAddresslist; interval: integer);
|
|
end;
|
|
|
|
//TPreviousResultList=specialize TFPGList<TSavedScanHandler>;
|
|
|
|
TMainForm = class(TForm)
|
|
actOpenLuaEngine: TAction;
|
|
actOpenDissectStructure: TAction;
|
|
btnSetSpeedhack2: TButton;
|
|
btnAddAddressManually: TButton;
|
|
btnMemoryView: TButton;
|
|
cbCaseSensitive: TCheckBox;
|
|
cbCopyOnWrite: TCheckBox;
|
|
cbExecutable: TCheckBox;
|
|
cbFastScan: TCheckBox;
|
|
cbFloatSimple: TCheckBox;
|
|
cbHexadecimal: TCheckBox;
|
|
cbPauseWhileScanning: TCheckBox;
|
|
cbSpeedhack: TCheckBox;
|
|
cbUnicode: TCheckBox;
|
|
cbUnrandomizer: TCheckBox;
|
|
cbWritable: TCheckBox;
|
|
cbpercentage: TCheckBox;
|
|
cbNot: TCheckBox;
|
|
cbCodePage: TCheckBox;
|
|
cbRepeatUntilStopped: TCheckBox;
|
|
cbCompareToSavedScan: TCheckBox;
|
|
cbLuaFormula: TCheckBox;
|
|
cbNewLuaState: TCheckBox;
|
|
cbPresentMemoryOnly: TCheckBox;
|
|
ColorDialog1: TColorDialog;
|
|
CreateGroup: TMenuItem;
|
|
FromAddress: TEdit;
|
|
andlabel: TLabel;
|
|
lblcompareToSavedScan: TLabel;
|
|
miTestAccessViolationThread: TMenuItem;
|
|
miTriggerAccessViolation: TMenuItem;
|
|
MenuItem16: TMenuItem;
|
|
MenuItem17: TMenuItem;
|
|
MenuItem18: TMenuItem;
|
|
miClearWorkingSet: TMenuItem;
|
|
miNetworkReadUseProcMem: TMenuItem;
|
|
miNetworkReadUsePtrace: TMenuItem;
|
|
miNetworkReadUseVmread: TMenuItem;
|
|
miNetworkWriteUseProcMem: TMenuItem;
|
|
miNetworkWriteUsePtrace: TMenuItem;
|
|
miNetworkWriteUseVmWrite: TMenuItem;
|
|
miDeleteSavedScanResults: TMenuItem;
|
|
miOnlyShowCurrentCompareToColumn: TMenuItem;
|
|
miLoadRecent: TMenuItem;
|
|
miAlwaysHideChildren: TMenuItem;
|
|
miFoundListPreferences: TMenuItem;
|
|
N2: TMenuItem;
|
|
mfImageList: TImageList;
|
|
lblSigned: TLabel;
|
|
MainMenu2: TMainMenu;
|
|
miTutorial64: TMenuItem;
|
|
MenuItem14: TMenuItem;
|
|
MenuItem15: TMenuItem;
|
|
Copyselectedaddresses1: TMenuItem;
|
|
miAutoAssembleErrorMessage: TMenuItem;
|
|
miLuaDocumentation: TMenuItem;
|
|
miForgotScan: TMenuItem;
|
|
miDotNET: TMenuItem;
|
|
miGetDotNetObjectList: TMenuItem;
|
|
miDBVMFindWhatWritesOrAccesses: TMenuItem;
|
|
pmPresentMemoryOnly: TPopupMenu;
|
|
sep2: TMenuItem;
|
|
miChangeValueBack: TMenuItem;
|
|
miSignTable: TMenuItem;
|
|
miSaveFile: TMenuItem;
|
|
miAsyncScript: TMenuItem;
|
|
miFlFindWhatAccesses: TMenuItem;
|
|
MenuItem13: TMenuItem;
|
|
miFlFindWhatWrites: TMenuItem;
|
|
miLanguages: TMenuItem;
|
|
ScanText2: TLabel;
|
|
scanvalue2: TEdit;
|
|
sbClearActiveMemory: TSpeedButton;
|
|
tLuaGCPassive: TTimer;
|
|
tLuaGCActive: TTimer;
|
|
ToAddress: TEdit;
|
|
editSH2: TEdit;
|
|
edtAlignment: TEdit;
|
|
Foundlist3: TListView;
|
|
ImageList2: TImageList;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Label54: TLabel;
|
|
lblSH0: TLabel;
|
|
lblSH20: TLabel;
|
|
MenuItem1: TMenuItem;
|
|
MenuItem10: TMenuItem;
|
|
MenuItem11: TMenuItem;
|
|
miEnableLCLDebug: TMenuItem;
|
|
miDisassemble: TMenuItem;
|
|
miBindDeactivation: TMenuItem;
|
|
miScanDirtyOnly: TMenuItem;
|
|
miScanPagedOnly: TMenuItem;
|
|
miGeneratePointermap: TMenuItem;
|
|
miDisplayHex: TMenuItem;
|
|
miNetwork: TMenuItem;
|
|
miCompression: TMenuItem;
|
|
miManualExpandCollapse: TMenuItem;
|
|
miSetDropdownOptions: TMenuItem;
|
|
miSave: TMenuItem;
|
|
miSnapshothandler: TMenuItem;
|
|
miSetupSnapshotKeys: TMenuItem;
|
|
miDisplayDefault: TMenuItem;
|
|
miDisplayByte: TMenuItem;
|
|
miDisplay2Byte: TMenuItem;
|
|
miDisplay4Byte: TMenuItem;
|
|
miDisplayFloat: TMenuItem;
|
|
miDisplayDouble: TMenuItem;
|
|
miDisplay8Byte: TMenuItem;
|
|
MenuItem19: TMenuItem;
|
|
miShowPreviousValue: TMenuItem;
|
|
MenuItem4: TMenuItem;
|
|
miShowCustomTypeDebug: TMenuItem;
|
|
miShowAsSigned: TMenuItem;
|
|
miOpenFile: TMenuItem;
|
|
MenuItem8: TMenuItem;
|
|
miTutorial: TMenuItem;
|
|
miLockMouseInGame: TMenuItem;
|
|
miChangeValue: TMenuItem;
|
|
miAddAddress: TMenuItem;
|
|
miAllowCollapse: TMenuItem;
|
|
miSetCrosshair: TMenuItem;
|
|
miWireframe: TMenuItem;
|
|
miZbuffer: TMenuItem;
|
|
miHookD3D: TMenuItem;
|
|
mi3d: TMenuItem;
|
|
miUndoValue: TMenuItem;
|
|
miPresetWritable: TMenuItem;
|
|
MenuItem2: TMenuItem;
|
|
MenuItem3: TMenuItem;
|
|
miShowLuaScript: TMenuItem;
|
|
MenuItem5: TMenuItem;
|
|
miPresetAll: TMenuItem;
|
|
miAddFile: TMenuItem;
|
|
MenuItem9: TMenuItem;
|
|
miResyncFormsWithLua: TMenuItem;
|
|
miCreateLuaForm: TMenuItem;
|
|
miLuaFormsSeperator: TMenuItem;
|
|
miTable: TMenuItem;
|
|
miSaveScanresults: TMenuItem;
|
|
MenuItem6: TMenuItem;
|
|
MenuItem7: TMenuItem;
|
|
miShowAsBinary: TMenuItem;
|
|
miZeroTerminate: TMenuItem;
|
|
miResetRange: TMenuItem;
|
|
miChangeColor: TMenuItem;
|
|
miGroupconfig: TMenuItem;
|
|
miDefineNewCustomTypeLua: TMenuItem;
|
|
miDeleteCustomType: TMenuItem;
|
|
miHideChildren: TMenuItem;
|
|
miBindActivation: TMenuItem;
|
|
miRecursiveSetValue: TMenuItem;
|
|
miDefineNewCustomType: TMenuItem;
|
|
miEditCustomType: TMenuItem;
|
|
miRenameTab: TMenuItem;
|
|
miTablistSeperator: TMenuItem;
|
|
miCloseTab: TMenuItem;
|
|
miAddTab: TMenuItem;
|
|
miFreezePositive: TMenuItem;
|
|
miFreezeNegative: TMenuItem;
|
|
Panel1: TPanel;
|
|
Panel10: TPanel;
|
|
Panel14: TPanel;
|
|
Panel2: TPanel;
|
|
Panel3: TPanel;
|
|
Panel6: TPanel;
|
|
Panel8: TPanel;
|
|
Panel9: TPanel;
|
|
pnlFloat: TPanel;
|
|
pnlScanOptions: TPanel;
|
|
pnlScanValueOptions: TPanel;
|
|
pmTablist: TPopupMenu;
|
|
pmValueType: TPopupMenu;
|
|
pmResetRange: TPopupMenu;
|
|
pmScanRegion: TPopupMenu;
|
|
rbBit: TRadioButton;
|
|
rbDec: TRadioButton;
|
|
rbFsmAligned: TRadioButton;
|
|
rbfsmLastDigts: TRadioButton;
|
|
rt1: TRadioButton;
|
|
rt2: TRadioButton;
|
|
rt3: TRadioButton;
|
|
SettingsButton: TSpeedButton;
|
|
tbSpeed: TTrackBar;
|
|
UpdateTimer: TTimer;
|
|
FreezeTimer: TTimer;
|
|
PopupMenu2: TPopupMenu;
|
|
Deletethisrecord1: TMenuItem;
|
|
Browsethismemoryregion1: TMenuItem;
|
|
Calculatenewvaluepart21: TMenuItem;
|
|
Freezealladdresses2: TMenuItem;
|
|
sep1: TMenuItem;
|
|
N1: TMenuItem;
|
|
N4: TMenuItem;
|
|
Copy1: TMenuItem;
|
|
Paste1: TMenuItem;
|
|
Cut1: TMenuItem;
|
|
Setbreakpoint1: TMenuItem;
|
|
SetHotkey1: TMenuItem;
|
|
N5: TMenuItem;
|
|
Panel4: TPanel;
|
|
advancedbutton: TSpeedButton;
|
|
CommentButton: TSpeedButton;
|
|
Panel5: TPanel;
|
|
ProcessLabel: TLabel;
|
|
foundcountlabel: TLabel;
|
|
ScanText: TLabel;
|
|
lblScanType: TLabel;
|
|
lblValueType: TLabel;
|
|
LoadButton: TSpeedButton;
|
|
SaveButton: TSpeedButton;
|
|
Label6: TLabel;
|
|
SpeedButton2: TSpeedButton;
|
|
SpeedButton3: TSpeedButton;
|
|
gbScanOptions: TGroupBox;
|
|
btnNewScan: TButton;
|
|
btnNextScan: TButton;
|
|
ScanType: TComboBox;
|
|
VarType: TComboBox;
|
|
ProgressBar: TProgressBar;
|
|
UndoScan: TButton;
|
|
scanvalue: TEdit;
|
|
foundlistpopup: TPopupMenu;
|
|
Browsethismemoryarrea1: TMenuItem;
|
|
Removeselectedaddresses1: TMenuItem;
|
|
Selectallitems1: TMenuItem;
|
|
OpenDialog1: TOpenDialog;
|
|
SaveDialog1: TSaveDialog;
|
|
TopDisabler: TTimer;
|
|
emptypopup: TPopupMenu;
|
|
ccpmenu: TPopupMenu;
|
|
Cut2: TMenuItem;
|
|
Copy2: TMenuItem;
|
|
Paste2: TMenuItem;
|
|
Splitter1: TSplitter;
|
|
Findoutwhataccessesthisaddress1: TMenuItem;
|
|
Showashexadecimal1: TMenuItem;
|
|
Panel7: TPanel;
|
|
sbOpenProcess: TSpeedButton;
|
|
Change1: TMenuItem;
|
|
Description1: TMenuItem;
|
|
Address1: TMenuItem;
|
|
Type1: TMenuItem;
|
|
Value1: TMenuItem;
|
|
Changescript1: TMenuItem;
|
|
ActionList1: TActionList;
|
|
actSave: TAction;
|
|
actOpen: TAction;
|
|
actAutoAssemble: TAction;
|
|
Forcerechecksymbols1: TMenuItem;
|
|
Smarteditaddresses1: TMenuItem;
|
|
Pointerscanforthisaddress1: TMenuItem;
|
|
Plugins1: TMenuItem;
|
|
UpdateFoundlisttimer: TTimer;
|
|
Browsethismemoryregioninthedisassembler1: TMenuItem;
|
|
AutoAttachTimer: TTimer;
|
|
btnFirst: TButton;
|
|
btnNext: TButton;
|
|
LogoPanel: TPanel;
|
|
Logo: TImage;
|
|
MainMenu1: TMainMenu;
|
|
File1: TMenuItem;
|
|
Process1: TMenuItem;
|
|
miHelp: TMenuItem;
|
|
Edit3: TMenuItem;
|
|
miAbout: TMenuItem;
|
|
OpenProcess1: TMenuItem;
|
|
Save1: TMenuItem;
|
|
Load1: TMenuItem;
|
|
Settings1: TMenuItem;
|
|
N6: TMenuItem;
|
|
a1: TMenuItem;
|
|
b1: TMenuItem;
|
|
c1: TMenuItem;
|
|
d1: TMenuItem;
|
|
e1: TMenuItem;
|
|
CreateProcess1: TMenuItem;
|
|
New1: TMenuItem;
|
|
N7: TMenuItem;
|
|
ools1: TMenuItem;
|
|
N8: TMenuItem;
|
|
Helpindex1: TMenuItem;
|
|
Plugins2: TMenuItem;
|
|
actMemoryView: TAction;
|
|
actOpenProcesslist: TAction;
|
|
procedure actOpenDissectStructureExecute(Sender: TObject);
|
|
procedure actOpenLuaEngineExecute(Sender: TObject);
|
|
procedure Address1Click(Sender: TObject);
|
|
procedure cbCompareToSavedScanChange(Sender: TObject);
|
|
procedure cbLuaFormulaChange(Sender: TObject);
|
|
procedure cbPercentageOnChange(Sender: TObject);
|
|
procedure cbCodePageChange(Sender: TObject);
|
|
procedure cbRepeatUntilStoppedChange(Sender: TObject);
|
|
procedure cbUnicodeChange(Sender: TObject);
|
|
procedure Copyselectedaddresses1Click(Sender: TObject);
|
|
procedure EnableLCLClick(Sender: TObject);
|
|
procedure cbFastScanChange(Sender: TObject);
|
|
procedure Description1Click(Sender: TObject);
|
|
procedure edtAlignmentKeyPress(Sender: TObject; var Key: char);
|
|
procedure FormDropFiles(Sender: TObject; const FileNames: array of string);
|
|
procedure Foundlist3ColumnClick(Sender: TObject; Column: TListColumn);
|
|
procedure Foundlist3CustomDrawItem(Sender: TCustomListView;
|
|
Item: TListItem; State: TCustomDrawState; var DefaultDraw: boolean);
|
|
procedure Foundlist3CustomDrawSubItem(Sender: TCustomListView;
|
|
Item: TListItem; SubItem: Integer; State: TCustomDrawState;
|
|
var DefaultDraw: Boolean);
|
|
procedure CreateGroupClick(Sender: TObject);
|
|
procedure gbScanOptionsChangeBounds(Sender: TObject);
|
|
procedure Label3Click(Sender: TObject);
|
|
procedure miTestAccessViolationThreadClick(Sender: TObject);
|
|
procedure miTriggerAccessViolationClick(Sender: TObject);
|
|
procedure miTutorial64Click(Sender: TObject);
|
|
procedure MenuItem15Click(Sender: TObject);
|
|
procedure MenuItem16Click(Sender: TObject);
|
|
procedure miClearWorkingSetClick(Sender: TObject);
|
|
procedure miDeleteSavedScanResultsClick(Sender: TObject);
|
|
procedure miFoundListPreferencesClick(Sender: TObject);
|
|
procedure miAutoAssembleErrorMessageClick(Sender: TObject);
|
|
procedure miHelpClick(Sender: TObject);
|
|
procedure miLuaDocumentationClick(Sender: TObject);
|
|
procedure miForgotScanClick(Sender: TObject);
|
|
procedure miGetDotNetObjectListClick(Sender: TObject);
|
|
procedure miChangeValueBackClick(Sender: TObject);
|
|
procedure miDBVMFindWhatWritesOrAccessesClick(Sender: TObject);
|
|
procedure miAlwaysHideChildrenClick(Sender: TObject);
|
|
procedure miNetworkClick(Sender: TObject);
|
|
procedure miNetworkReadUseProcMemClick(Sender: TObject);
|
|
procedure miOnlyShowCurrentCompareToColumnClick(Sender: TObject);
|
|
procedure miSignTableClick(Sender: TObject);
|
|
procedure miAsyncScriptClick(Sender: TObject);
|
|
procedure miFlFindWhatAccessesClick(Sender: TObject);
|
|
procedure miBindDeactivationClick(Sender: TObject);
|
|
procedure miDisassembleClick(Sender: TObject);
|
|
procedure miFlFindWhatWritesClick(Sender: TObject);
|
|
procedure miSaveFileClick(Sender: TObject);
|
|
procedure miScanDirtyOnlyClick(Sender: TObject);
|
|
procedure miCompressionClick(Sender: TObject);
|
|
procedure miGeneratePointermapClick(Sender: TObject);
|
|
procedure miManualExpandCollapseClick(Sender: TObject);
|
|
procedure miSaveClick(Sender: TObject);
|
|
procedure mi3dClick(Sender: TObject);
|
|
procedure miChangeDisplayTypeClick(Sender: TObject);
|
|
procedure miOpenFileClick(Sender: TObject);
|
|
procedure miScanPagedOnlyClick(Sender: TObject);
|
|
procedure miSetDropdownOptionsClick(Sender: TObject);
|
|
procedure miShowAsSignedClick(Sender: TObject);
|
|
procedure miShowCustomTypeDebugClick(Sender: TObject);
|
|
procedure miShowPreviousValueClick(Sender: TObject);
|
|
procedure miSnapshothandlerClick(Sender: TObject);
|
|
procedure miTutorialClick(Sender: TObject);
|
|
procedure miChangeValueClick(Sender: TObject);
|
|
procedure MenuItem1Click(Sender: TObject);
|
|
procedure miShowLuaScriptClick(Sender: TObject);
|
|
procedure miAddAddressClick(Sender: TObject);
|
|
procedure miAllowCollapseClick(Sender: TObject);
|
|
procedure miHookD3DClick(Sender: TObject);
|
|
procedure miLockMouseInGameClick(Sender: TObject);
|
|
procedure miPresetAllClick(Sender: TObject);
|
|
procedure miAddFileClick(Sender: TObject);
|
|
procedure MenuItem9Click(Sender: TObject);
|
|
procedure miPresetWritableClick(Sender: TObject);
|
|
procedure miResyncFormsWithLuaClick(Sender: TObject);
|
|
procedure miCreateLuaFormClick(Sender: TObject);
|
|
procedure MenuItem7Click(Sender: TObject);
|
|
procedure miSetCrosshairClick(Sender: TObject);
|
|
procedure miTableClick(Sender: TObject);
|
|
procedure miResetRangeClick(Sender: TObject);
|
|
procedure miChangeColorClick(Sender: TObject);
|
|
procedure miDefineNewCustomTypeLuaClick(Sender: TObject);
|
|
procedure miDeleteCustomTypeClick(Sender: TObject);
|
|
procedure miBindActivationClick(Sender: TObject);
|
|
procedure miEditCustomTypeClick(Sender: TObject);
|
|
procedure miHideChildrenClick(Sender: TObject);
|
|
procedure miDefineNewCustomTypeClick(Sender: TObject);
|
|
procedure miRecursiveSetValueClick(Sender: TObject);
|
|
procedure miRenameTabClick(Sender: TObject);
|
|
procedure miAddTabClick(Sender: TObject);
|
|
procedure miCloseTabClick(Sender: TObject);
|
|
procedure miFreezeNegativeClick(Sender: TObject);
|
|
procedure miFreezePositiveClick(Sender: TObject);
|
|
procedure miSaveScanresultsClick(Sender: TObject);
|
|
procedure miShowAsBinaryClick(Sender: TObject);
|
|
procedure miUndoValueClick(Sender: TObject);
|
|
procedure miWireframeClick(Sender: TObject);
|
|
procedure miZbufferClick(Sender: TObject);
|
|
procedure miZeroTerminateClick(Sender: TObject);
|
|
procedure Panel5Resize(Sender: TObject);
|
|
procedure pmTablistPopup(Sender: TObject);
|
|
procedure pmValueTypePopup(Sender: TObject);
|
|
procedure rbFsmAlignedChange(Sender: TObject);
|
|
procedure rtChange(Sender: TObject);
|
|
procedure Save1Click(Sender: TObject);
|
|
procedure ShowProcessListButtonClick(Sender: TObject);
|
|
procedure btnNewScanClick(Sender: TObject);
|
|
procedure btnNextScanClick(Sender: TObject);
|
|
procedure btnMemoryViewClick(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure AddressKeyPress(Sender: TObject; var Key: char);
|
|
procedure FoundListDblClick(Sender: TObject);
|
|
procedure Browsethismemoryarrea1Click(Sender: TObject);
|
|
procedure tLuaGCActiveTimer(Sender: TObject);
|
|
procedure tLuaGCPassiveTimer(Sender: TObject);
|
|
procedure UpdateTimerTimer(Sender: TObject);
|
|
procedure FreezeTimerTimer(Sender: TObject);
|
|
procedure Browsethismemoryregion1Click(Sender: TObject);
|
|
procedure Deletethisrecord1Click(Sender: TObject);
|
|
procedure ScanvalueoldKeyPress(Sender: TObject; var Key: char);
|
|
procedure Calculatenewvaluepart21Click(Sender: TObject);
|
|
procedure btnAddAddressManuallyClick(Sender: TObject);
|
|
procedure ScanTypeChange(Sender: TObject);
|
|
procedure Value1Click(Sender: TObject);
|
|
procedure VarTypeChange(Sender: TObject);
|
|
procedure LogoClick(Sender: TObject);
|
|
procedure VarTypeDropDown(Sender: TObject);
|
|
procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
|
|
procedure SpeedButton2Click(Sender: TObject);
|
|
procedure SpeedButton3Click(Sender: TObject);
|
|
procedure Selectallitems1Click(Sender: TObject);
|
|
procedure Freezealladdresses2Click(Sender: TObject);
|
|
procedure PopupMenu2Popup(Sender: TObject);
|
|
procedure foundlistpopupPopup(Sender: TObject);
|
|
procedure Removeselectedaddresses1Click(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var cAction: TCloseAction);
|
|
procedure CommentButtonClick(Sender: TObject);
|
|
procedure Copy1Click(Sender: TObject);
|
|
procedure Cut1Click(Sender: TObject);
|
|
procedure Paste1Click(Sender: TObject);
|
|
procedure Setbreakpoint1Click(Sender: TObject);
|
|
procedure TopDisablerTimer(Sender: TObject);
|
|
procedure advancedbuttonClick(Sender: TObject);
|
|
procedure cbHexadecimalClick(Sender: TObject);
|
|
procedure SetHotkey1Click(Sender: TObject);
|
|
procedure UndoScanClick(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure rbBitClick(Sender: TObject);
|
|
procedure rbDecClick(Sender: TObject);
|
|
procedure Cut2Click(Sender: TObject);
|
|
procedure Copy2Click(Sender: TObject);
|
|
procedure Paste2Click(Sender: TObject);
|
|
procedure ccpmenuPopup(Sender: TObject);
|
|
procedure Splitter1Moved(Sender: TObject);
|
|
procedure SettingsClick(Sender: TObject);
|
|
procedure cbCaseSensitiveClick(Sender: TObject);
|
|
procedure LogoMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
procedure Findoutwhataccessesthisaddress1Click(Sender: TObject);
|
|
procedure OpenProcesslist1Click(Sender: TObject);
|
|
procedure CloseCheatEngine1Click(Sender: TObject);
|
|
procedure Showashexadecimal1Click(Sender: TObject);
|
|
procedure OpenMemorybrowser1Click(Sender: TObject);
|
|
procedure cbPauseWhileScanningClick(Sender: TObject);
|
|
procedure ProcessLabelDblClick(Sender: TObject);
|
|
procedure ProcessLabelMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
procedure cbUnrandomizerClick(Sender: TObject);
|
|
procedure cbUnrandomizerMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
procedure actOpenExecute(Sender: TObject);
|
|
procedure actSaveExecute(Sender: TObject);
|
|
procedure actAutoAssembleExecute(Sender: TObject);
|
|
procedure Changescript1Click(Sender: TObject);
|
|
procedure Forcerechecksymbols1Click(Sender: TObject);
|
|
procedure Smarteditaddresses1Click(Sender: TObject);
|
|
procedure Pointerscanforthisaddress1Click(Sender: TObject);
|
|
procedure Foundlist3Data(Sender: TObject; Item: TListItem);
|
|
procedure UpdateFoundlisttimerTimer(Sender: TObject);
|
|
procedure Foundlist3KeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
|
|
procedure Browsethismemoryregioninthedisassembler1Click(Sender: TObject);
|
|
procedure AutoAttachTimerTimer(Sender: TObject);
|
|
procedure btnFirstClick(Sender: TObject);
|
|
procedure btnNextClick(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure tbSpeedChange(Sender: TObject);
|
|
procedure btnSetSpeedhack2Click(Sender: TObject);
|
|
procedure cbSpeedhackChange(Sender: TObject);
|
|
procedure Process1Click(Sender: TObject);
|
|
procedure miAboutClick(Sender: TObject);
|
|
procedure CreateProcess1Click(Sender: TObject);
|
|
procedure Helpindex1Click(Sender: TObject);
|
|
procedure New1Click(Sender: TObject);
|
|
procedure File1Click(Sender: TObject);
|
|
procedure actOpenProcesslistExecute(Sender: TObject);
|
|
procedure Type1Click(Sender: TObject);
|
|
private
|
|
repeatscantimer: TTimer;
|
|
onetimeonly: boolean; //to protect against make mainform visible (.show)
|
|
|
|
scantimestart, scantimefinish: int64;
|
|
|
|
tabcounter: integer;
|
|
//variable that only goes up, doesn't go down when a tab is deleted
|
|
scantablist: TTablist;
|
|
|
|
oldscanvalue2text: string;
|
|
aaa: single;
|
|
hotkeypressed: integer;
|
|
|
|
cancelbutton: TButton;
|
|
//cancel button that spawns during a scan, disabled initially to prevent doubleclick accidents
|
|
cancelbuttonenabler: TTimer;
|
|
//timer that will enable the cancelbutton after 3 seconds
|
|
|
|
groupconfigbutton: TButton;
|
|
|
|
oldwidth, oldheight: integer;
|
|
newaddress: ptrUint;
|
|
isbit: boolean;
|
|
tempbitmap: Tbitmap;
|
|
dontrunshow: boolean;
|
|
|
|
LastWasHex: boolean;
|
|
dontconvert: boolean;
|
|
FlashProcessButton: TFlash;
|
|
oldvartype: integer;
|
|
|
|
unrandomize: Tunrandomize;
|
|
|
|
|
|
|
|
reinterpretcheck: integer;
|
|
|
|
ffoundcount: int64;
|
|
foundlistDisplayOverride: integer; //a number specifying what type to display (0=default)
|
|
|
|
SaveFirstScanThread: TSaveFirstScanThread;
|
|
|
|
foundlist: Tfoundlist;
|
|
|
|
compareToSavedScan: boolean;
|
|
fActivePreviousResultColumn: integer; //the column index which is going to be compared against
|
|
currentlySelectedSavedResultname: string; //I love long variable names
|
|
|
|
PreviousResultList: Tlist;
|
|
|
|
|
|
|
|
lastscantype: integer;
|
|
oldhandle: thandle;
|
|
|
|
alignsizechangedbyuser: boolean;
|
|
scantypechangedbyhotkey: boolean;
|
|
|
|
fIsProtected: boolean;
|
|
fOnProcessOpened: TProcessOpenedEvent;
|
|
|
|
overlayid: integer; //debug
|
|
lastAdded: record
|
|
Address: string;
|
|
vartype: TVariableType;
|
|
customTypeName: string;
|
|
end;
|
|
|
|
foundlistColors: record
|
|
NormalValueColor: TColor;
|
|
ChangedValueColor: TColor;
|
|
StaticColor: TColor;
|
|
DynamicColor: TColor;
|
|
CompareToHeaderColor: TColor;
|
|
end;
|
|
|
|
|
|
saveGotCanceled: boolean; //set to true if the last save button click was canceled
|
|
|
|
UserDefinedTableName: string; //set when a user opens a table (when set the filename prediction will be turned off)
|
|
|
|
speedhackDisableTimer: TTimer;
|
|
boundsupdater: TTimer;
|
|
|
|
freezeThread: TFreezeThread;
|
|
|
|
showStaticAsStatic: boolean;
|
|
AddressListOverrideFontSize: boolean;
|
|
|
|
RecentFiles: Tstringlist;
|
|
|
|
InsideSetActivePreviousResult: boolean;
|
|
|
|
exceptionerrorcs: TCriticalSection;
|
|
currentexceptionerror: string;
|
|
showingException: boolean;
|
|
|
|
TraceExceptions: boolean;
|
|
|
|
procedure updateNetworkOption(sender: TObject);
|
|
procedure updateNetworkOptions;
|
|
|
|
procedure ClearRecentFiles(Sender:TObject);
|
|
procedure RecentFilesClick(Sender:TObject);
|
|
procedure CheckForSpeedhackKey(sender: TObject);
|
|
|
|
procedure doNewScan;
|
|
procedure SetExpectedTableName;
|
|
|
|
function CheckIfSaved: boolean;
|
|
procedure checkpaste;
|
|
procedure hotkey(var Message: TMessage); {$ifdef windows}message WM_HOTKEY;{$endif}
|
|
|
|
procedure MemScanStart(sender: TObject);
|
|
procedure MemScanDone(sender: TObject);
|
|
procedure PluginSync(var m: TMessage); message wm_pluginsync;
|
|
procedure ShowError;
|
|
procedure Edit;
|
|
procedure paste(simplecopypaste: boolean);
|
|
procedure CopySelectedRecords;
|
|
|
|
|
|
procedure exceptionhandler(Sender: TObject; E: Exception);
|
|
procedure toggleWindow;
|
|
procedure adjustbringtofronttext;
|
|
|
|
procedure scanEpilogue(canceled: boolean);
|
|
procedure CancelbuttonClick(Sender: TObject);
|
|
procedure CancelbuttonenablerInterval(Sender: TObject);
|
|
procedure repeatScanTimerTimer(sender: TObject);
|
|
|
|
procedure changeScriptCallback(memrec: TMemoryRecord; script: string; scriptchanged: boolean);
|
|
|
|
//processlist
|
|
procedure ProcessItemClick(Sender: TObject);
|
|
|
|
//property functions
|
|
function GetRoundingType: TRoundingType;
|
|
procedure SetRoundingType(rt: TRoundingType);
|
|
function getScanStart: ptruint;
|
|
procedure setScanStart(newscanstart: ptruint);
|
|
function getScanStop: ptruint;
|
|
procedure setScanStop(newscanstop: ptruint);
|
|
function getFastscan: boolean;
|
|
procedure setFastScan(state: boolean);
|
|
|
|
function getSelectedVariableType: TVariableType;
|
|
procedure setfoundcount(x: int64);
|
|
|
|
|
|
procedure AddresslistDropByListview(Sender: TObject; node: TTreenode;
|
|
attachmode: TNodeAttachMode);
|
|
|
|
procedure SaveCurrentState(scanstate: PScanState; skipuservalues: boolean=false);
|
|
procedure SetupInitialScanTabState(scanstate: PScanState; IsFirstEntry: boolean);
|
|
procedure ScanTabListTabChange(Sender: TObject; oldselection: integer);
|
|
|
|
procedure UpdateFloatRelatedPositions;
|
|
|
|
//custom type:
|
|
procedure CreateCustomType(customtype: TCustomtype; script: string;
|
|
scriptchanged: boolean; lua: boolean = False);
|
|
|
|
|
|
procedure LoadCustomTypesFromRegistry;
|
|
|
|
procedure setGbScanOptionsEnabled(state: boolean);
|
|
procedure cbSaferPhysicalMemoryChange(sender: tobject);
|
|
|
|
|
|
function onhelp(Command: word; Data: PtrInt; var CallHelp: boolean): boolean;
|
|
procedure SaveIntialTablesDir(dir: string);
|
|
|
|
function convertvalue(ovartype, nvartype: integer; oldvalue: string;
|
|
washexadecimal, ishexadecimal: boolean): string;
|
|
|
|
//designer functions
|
|
procedure RenameFileClick(Sender: TObject);
|
|
procedure SaveFileClick(Sender: TObject);
|
|
procedure DeleteFileClick(Sender: TObject);
|
|
|
|
procedure EditFormClick(Sender: TObject);
|
|
procedure RestoreAndShowFormClick(Sender: TObject);
|
|
procedure DeleteFormClick(Sender: TObject);
|
|
procedure FormDesignerClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
|
|
procedure setIsProtected(p: boolean);
|
|
|
|
procedure d3dclicktest(_overlayid: integer; x, y: integer);
|
|
|
|
|
|
procedure createGroupConfigButton;
|
|
procedure destroyGroupConfigButton;
|
|
|
|
procedure BoundsUpdate(sender: TObject);
|
|
procedure SpawnBoundsUpdater;
|
|
|
|
procedure MemscanGuiUpdate(sender: TObject; totaladdressestoscan: qword; currentlyscanned: qword; foundcount: qword);
|
|
|
|
function getUseThreadToFreeze: boolean;
|
|
procedure setUseThreadToFreeze(state: boolean);
|
|
|
|
procedure recentFilesUpdate(filepath: string);
|
|
|
|
procedure reloadPreviousResults;
|
|
procedure cleanupPreviousResults;
|
|
public
|
|
{ Public declarations }
|
|
addresslist: TAddresslist;
|
|
|
|
//test: single;
|
|
itemshavechanged: boolean;
|
|
|
|
debugproc: boolean;
|
|
autoopen: boolean;
|
|
//boolean set when table is opened by other means than user file picker
|
|
|
|
Priority: Dword;
|
|
memimage: TMemorystream;
|
|
|
|
canceled: boolean;
|
|
|
|
originalheight: integer;
|
|
originalwidth: integer;
|
|
|
|
fronttext: string;
|
|
|
|
|
|
|
|
editedsincelastsave: boolean;
|
|
|
|
autoattachlist: TStringList;
|
|
extraautoattachlist: TStringList;
|
|
//modifed by plugins and scripts, not affected by settings changes
|
|
oldcodelistcount: integer;
|
|
|
|
memscan: tmemscan;
|
|
LuaForms: TList;
|
|
LuaFiles: TLuaFileList;
|
|
InternalLuaFiles: TLuaFileList;
|
|
frmLuaTableScript: Tfrmautoinject;
|
|
|
|
|
|
cbsaferPhysicalMemory: TCheckbox;
|
|
mustClose: boolean;
|
|
|
|
imgSignature: TImage;
|
|
|
|
|
|
|
|
{$ifdef darwin}
|
|
cbDirty: TCheckbox;
|
|
{$endif}
|
|
|
|
procedure setActivePreviousResultColumn(c: integer);
|
|
procedure Hotkey2(command: integer);
|
|
|
|
|
|
procedure updated3dgui;
|
|
procedure RefreshCustomTypes;
|
|
|
|
procedure autoattachcheck(pl: TStringList = nil); // can be called by AutoAttachTimer or AutoAttachThread
|
|
function openprocessPrologue: boolean;
|
|
procedure openProcessEpilogue(oldprocessname: string; oldprocess: dword;
|
|
oldprocesshandle: dword; autoattachopen: boolean = False);
|
|
|
|
|
|
procedure ChangedHandle(Sender: TObject);
|
|
procedure plugintype0click(Sender: TObject);
|
|
procedure plugintype5click(Sender: TObject);
|
|
procedure OnToolsClick(Sender: TObject);
|
|
procedure AddToRecord(Line: integer; node: TTreenode = nil;
|
|
attachmode: TNodeAttachMode = naAdd);
|
|
procedure AddAutoAssembleScript(script: string);
|
|
procedure reinterpretaddresses;
|
|
|
|
|
|
procedure ClearList;
|
|
|
|
procedure CreateScanValue2;
|
|
procedure DestroyScanValue2;
|
|
|
|
|
|
procedure CreateCbPercentage;
|
|
procedure DestroyCbPercentage;
|
|
|
|
procedure UpdateScanType;
|
|
procedure enableGui(isnextscan: boolean);
|
|
procedure disableGui;
|
|
procedure SpawnCancelButton;
|
|
procedure DestroyCancelButton;
|
|
|
|
function AddressListAutoAssemblerEdit(Sender: TObject; memrec: TMemoryRecord): boolean;
|
|
procedure createFormdesigner;
|
|
procedure UpdateMenu;
|
|
|
|
procedure DoGroupconfigButtonClick(sender: tobject);
|
|
|
|
function getVarType: TVariableType;
|
|
function getVarType2: TVariableType;
|
|
procedure setVarType(vt: TVariableType);
|
|
|
|
function GetScanType: TScanOption;
|
|
function GetScanType2: TScanOption;
|
|
|
|
procedure DBVMFindWhatWritesOrAccesses(address: ptruint);
|
|
|
|
|
|
property foundcount: int64 read ffoundcount write setfoundcount;
|
|
property RoundingType: TRoundingType read GetRoundingType write SetRoundingType;
|
|
property ScanStart: ptruint read getScanStart write setScanStart;
|
|
property ScanStop: ptruint read getScanStop write setScanStop;
|
|
property FastScan: boolean read getFastscan write setFastscan;
|
|
|
|
|
|
property SelectedVariableType: TVariableType read getSelectedVariableType;
|
|
property isProtected: boolean read fIsProtected write setIsProtected;
|
|
|
|
property ActivePreviousResultColumn: integer read fActivePreviousResultColumn write setActivePreviousResultColumn;
|
|
published
|
|
property Progressbar1: TProgressBar read Progressbar write ProgressBar;
|
|
property About1: TMenuItem read miAbout write miAbout;
|
|
property Help1: TMenuItem read miHelp write miHelp;
|
|
property OnProcessOpened: TProcessOpenedEvent read fOnProcessOpened write fOnProcessOpened;
|
|
property UseThreadToFreeze: boolean read getUseThreadToFreeze write setUseThreadToFreeze;
|
|
end;
|
|
|
|
var
|
|
MainForm: TMainForm;
|
|
ToggleWindows: TTogglewindows;
|
|
AutoAttachThread: TAutoAttachThread;
|
|
|
|
resourcestring
|
|
strPhysicalMemory = 'Physical Memory';
|
|
|
|
implementation
|
|
|
|
|
|
uses cefuncproc, MainUnit2, ProcessWindowUnit, MemoryBrowserFormUnit, TypePopup, HotKeys,
|
|
aboutunit, formhotkeyunit, formDifferentBitSizeUnit,
|
|
CommentsUnit, formsettingsunit, formAddressChangeUnit, Changeoffsetunit,
|
|
FoundCodeUnit, AdvancedOptionsUnit, frmProcessWatcherUnit,
|
|
formPointerOrPointeeUnit, OpenSave, formmemoryregionsunit, formProcessInfo,
|
|
PasteTableentryFRM, pointerscannerfrm, PointerscannerSettingsFrm,
|
|
frmFloatingPointPanelUnit, pluginexports {$ifdef windows},DBK32functions, frmUltimapUnit,
|
|
frmSetCrosshairUnit{$endif},StructuresFrm2 {$ifdef windows} ,frmMemoryViewExUnit,
|
|
frmD3DHookSnapshotConfigUnit,frmSaveSnapshotsUnit, frmsnapshothandlerUnit,
|
|
frmNetworkDataCompressionUnit{$endif},ProcessHandlerUnit, processlist, pointeraddresslist,
|
|
PointerscanresultReader, Parsers, Globals {$ifdef windows},GnuAssembler, xinput{$endif} ,DPIHelper,
|
|
multilineinputqueryunit {$ifdef windows},winsapi{$endif} ,LuaClass, Filehandler{$ifdef windows}, feces{$endif}
|
|
{$ifdef windows},frmDBVMWatchConfigUnit, frmDotNetObjectListUnit{$endif} ,ceregistry ,UnexpectedExceptionsHelper
|
|
,frmFoundlistPreferencesUnit, fontSaveLoadRegistry{$ifdef windows}, cheatecoins{$endif},strutils, iptlogdisplay,
|
|
libcepack, symbolsync;
|
|
|
|
resourcestring
|
|
rsInvalidStartAddress = 'Invalid start address: %s';
|
|
rsInvalidStopAddress = 'Invalid stop address: %s';
|
|
rsThisButtonWillTryToCancelTheCurrentScanClickTwiceT =
|
|
'This button will try to cancel the current scan. Click twice to force an exit';
|
|
rsCancel = 'Cancel';
|
|
strWindowFailedToHide = 'A window failed to hide';
|
|
strAccessed = 'The following opcodes accessed the selected address';
|
|
strOpcodeRead = 'The following opcodes read from the selected address';
|
|
strOpcodeChanged = 'The following opcodes changed the selected address';
|
|
strAskToSave = 'You haven''t saved your last changes yet. Save Now?';
|
|
strScantextcaptiontotext = 'Text:';
|
|
strScantextcaptiontoValue = 'Value:';
|
|
strsearchForText = 'Search for text';
|
|
strSearchForArray = 'Search for this array';
|
|
rsValue = 'Value %';
|
|
rsBetween = 'between %';
|
|
rsAtLeastXx = 'at least xx%';
|
|
rsAnd = 'and';
|
|
strConfirmProcessTermination =
|
|
'This will close the current process. Are you sure you want to do this?';
|
|
strError = 'Error';
|
|
strErrorwhileOpeningProcess = 'Error while opening this process';
|
|
strErrorWhileOpeningProcessMac = '. Have you disabled ''System Integrity Protection''(SIP) yet?';
|
|
strKeepList = 'Keep the current address list/code list?';
|
|
strInfoAboutTable = 'Info about this table:';
|
|
|
|
strSaferPhysicalMemory = 'Safer memory access';
|
|
rsThereAreOneOrMoreAutoAssemblerEntriesOrCodeChanges =
|
|
'There are one or more auto assembler entries or code changes enabled in this table. Do you want them disabled? (without '
|
|
+ 'executing the disable part)';
|
|
rsLoadTheAssociatedTable = 'Load the associated table? (%s)';
|
|
rsGroup = 'Group %s';
|
|
rsGroups = 'Groups';
|
|
rsWhatDoYouWantTheGroupnameToBe = 'What do you want the groupname to be?';
|
|
rsDoYouWantTheGroupWithAddress = 'Do you want a header with address support ?';
|
|
rsAreYouSureYouWantToDeleteThisForm = 'Are you sure you want to delete this form?';
|
|
rsRenameFile = 'Rename file';
|
|
rsGiveTheNewFilename = 'Give the new filename';
|
|
rsRestoreAndShow = 'Restore and show';
|
|
rsEdit = 'Edit';
|
|
rsDelete = 'Delete';
|
|
rsRename = 'Rename';
|
|
rsSaveToDisk = 'Save to disk';
|
|
rsAreYouSureYouWantToDelete = 'Are you sure you want to delete %s?';
|
|
rsWhatWillBeTheNewNameForThisTab = 'What will be the new name for this tab?';
|
|
rsScan = 'Scan';
|
|
rsScanresult = 'Scanresult';
|
|
rsSaveScanResults = 'Save scan results';
|
|
rsWhatNameDoYouWantToGiveToTheseScanresults =
|
|
'What name do you want to give to these scanresults?';
|
|
strClickToGoHome = 'Click here to go to the '+strCheatEngine+' homepage';
|
|
rsLuaScriptCheatTable = 'Lua script: '+strCheatTable;
|
|
strChangeDescription1 = 'Description';
|
|
strChangeDescription2 = 'Change the description to:';
|
|
|
|
strNotTheSameSize1 = 'The text you entered isn''t the same size as the original. Continue?';
|
|
strNotTheSameSize2 = 'Not the same size!';
|
|
strAdd0 = 'Do you want to add a ''0''-terminator at the end?';
|
|
strNotAValidNotation = 'This is not a valid notation';
|
|
strNotSameAmmountofBytes =
|
|
'The number of bytes you typed is not the same as the previous ammount. Continue?';
|
|
strNotAValidBinaryNotation = ' is not a valid binary notation!';
|
|
|
|
strValue = 'Value';
|
|
strChange1Value = 'Change this value to:';
|
|
strChangeMoreValues = 'Change these values to:';
|
|
|
|
strSelectedAddressIsAPointer =
|
|
'The selected address is a pointer. Are you sure? (the base pointer will get the address)';
|
|
strMorePointers = 'There are more pointers selected. Do you want to change them as well?';
|
|
strMorePointers2 =
|
|
'You have selected one or more pointers. Do you want to change them as well?';
|
|
strNotAValidValue = 'This is not an valid value';
|
|
rsTheRecordWithDescriptionHasAsInterpretableAddressT =
|
|
'The record with description ''%s'' has as interpretable address ''%s''. The recalculation will change it to %s. Do you '
|
|
+ 'want to edit it to the new address?';
|
|
rsSavedScanResults = 'Saved scan results';
|
|
rsSelectTheSavedScanResultFromTheListBelow =
|
|
'Select the saved scan result from the list below';
|
|
rsSelectTheSavedScanResultToDeleteFromTheListBelow =
|
|
'Select the saved scan result to delete from the list below';
|
|
rsComparingTo = 'Comparing to %s';
|
|
rsHex = 'Hex';
|
|
rsDoYouWantToGoToTheCheatEngineWebsite =
|
|
'Do you want to go to the '+strCheatEngine+' website?';
|
|
|
|
strdeleteall = 'Are you sure you want to delete all addresses?';
|
|
stralreadyin = 'This address is already in the list';
|
|
stralreadyinlistmultiple = 'One or more addresses where already in the list';
|
|
strsethotkey = 'Set a hotkey';
|
|
strshowasdecimal = 'Show as decimal value';
|
|
strshowashex = 'Show as hexadecimal value';
|
|
strFreezeAddressInList = 'Freeze the address in this list';
|
|
strFreezeAllAddresses = 'Freeze all addresses in this list';
|
|
strUnfreezeAllAddresses = 'Unfreeze all addresses in this list';
|
|
strUnfreezeAddressInList = 'Unfreeze the address in this list';
|
|
strDeleteAddress = 'Delete this address';
|
|
strDeleteTheseAddresses = 'Delete these addresses';
|
|
strRecalculateAddress = 'Recalculate address';
|
|
strRecalculateSelectedAddresses = 'Recalculate selected addresses';
|
|
strRecalculateAllAddresses = 'Recalculate all addresses';
|
|
|
|
strRemoveFromGroup = 'Remove from group ';
|
|
|
|
strChangeScript = 'Change script';
|
|
strEnableCheat = 'Enable '+strCheat;
|
|
strDisableCheat = 'Disable '+strCheat;
|
|
|
|
strForceRecheck = 'Force recheck symbols';
|
|
rsSetChangeHotkeys = 'Set/Change hotkeys';
|
|
rsSetHotkeys = 'Set hotkeys';
|
|
rsShowAsDecimal = 'Show as decimal';
|
|
rsShowAsBinary = 'Show as binary';
|
|
rsShowAsHexadecimal = 'Show as hexadecimal';
|
|
rsRemoveSelectedAddresses = 'Remove selected addresses';
|
|
rsRemoveSelectedAddress = 'Remove selected address';
|
|
rsThisListIsHuge =
|
|
'This list is huge and deleting multiple items will require CE to traverse the whole list and can take a while. Are you sure?';
|
|
rsFindOutWhatAccessesThisPointer = 'Find out what accesses this pointer';
|
|
rsFindWhatAccessesTheAddressPointedAtByThisPointer =
|
|
'Find what accesses the address pointed at by this pointer';
|
|
rsFindOutWhatWritesThisPointer = 'Find out what writes this pointer';
|
|
rsFindWhatWritesTheAddressPointedAtByThisPointer =
|
|
'Find what writes the address pointed at by this pointer';
|
|
|
|
strconfirmUndo = 'Do you really want to go back to the results of the previous scan?';
|
|
|
|
strHideForeground = 'will hide the foreground window';
|
|
strHideAll = 'will hide all windows';
|
|
strUnHideForeground = 'will bring the foreground window back';
|
|
strUnhideAll = 'will bring all windows back';
|
|
rsBringsCheatEngineToFront = 'brings '+strCheatEngine+' to front';
|
|
|
|
strhappybirthday = 'Let''s sing Happy Birthday for Dark Byte today!';
|
|
strXMess = 'Merry christmas and happy new year';
|
|
strNewyear = 'And what are your good intentions for this year? ;-)';
|
|
strfuture = 'Wow,I never imagined people would use '+strCheatEngine+' up to today';
|
|
rsEXPIRED = 'EXPIRED';
|
|
strdontbother =
|
|
'Don''t even bother. '+strCheatEngine+' uses the main thread to receive messages when the scan is done, freeze it and CE will crash!';
|
|
rsTheProcessIsnTFullyOpenedIndicatingAInvalidProcess =
|
|
'The process isn''t fully opened. Indicating a invalid ProcessID. You still want to find out the EPROCESS? (BSOD is '
|
|
+ 'possible)';
|
|
rsUnrandomizerInfo =
|
|
'This will scan for and change some routines that are commonly used to generate a random value so they always return the same. Please be aware that there ' + 'is a chance it overwrites the wrong routines causing the program to crash, or that the program uses an unknown random generator. Continue?';
|
|
|
|
strUnknownExtension = 'Unknown extension';
|
|
rsDoYouWishToMergeTheCurrentTableWithThisTable =
|
|
'Do you wish to merge the current table with this table?';
|
|
rsDoYouWantToProtectThisTrainerFileFromEditing =
|
|
'Do you want to protect this trainer file from editing?';
|
|
rsAutoAssembleEdit = 'Auto Assemble edit: %s';
|
|
rsEditAddresses = 'Edit addresses';
|
|
rsScanError = 'Scan error:%s';
|
|
rsShown = 'shown';
|
|
rsTerminatingScan = 'Terminating scan...';
|
|
rsThisButtonWillForceCancelAScanExpectMemoryLeaks =
|
|
'This button will force cancel a scan. Expect memory leaks';
|
|
rsForceTermination = 'Force termination';
|
|
rsYouAreLowOnDiskspaceOnTheFolderWhereTheScanresults =
|
|
'You are low on diskspace on the folder where the scanresults are stored. Scanning might fail. Are you sure you want to '
|
|
+ 'continue?';
|
|
rsIsNotAValidSpeed = '%s is not a valid speed';
|
|
rsAreYouSureYouWantToEraseTheDataInTheCurrentTable =
|
|
'Are you sure you want to erase the data in the current table?';
|
|
|
|
|
|
rsSaved = 'Saved';
|
|
rsPrevious = 'Previous';
|
|
|
|
rsDecimal = 'Decimal';
|
|
rsHexadecimal = 'Hexadecimal';
|
|
rsIsNotAValidX = '%s is not a valid xml name';
|
|
rsMUGenerateGroupscanCommand = 'Generate groupscan command';
|
|
rsTryTutorial = 'Do you want to try out the tutorial?';
|
|
rsUnspecifiedError = 'Unspecified error';
|
|
rsGroupscanDataInvalid = 'groupscan data invalid';
|
|
rsGroupscanResultWithNoGroupscanparser = 'Groupscan result with no groupscanparser';
|
|
rsFailedToLoad = 'failed to load';
|
|
rsFailureSettingTheDebugPrivilege = 'Failure setting the debug privilege. Debugging may be limited.';
|
|
rsFailureSettingTheSeTcbPrivilegePrivilege = 'Failure setting the SeTcbPrivilege privilege. Debugging may be limited.';
|
|
rsFailureSettingTheLoadDriverPrivilege = 'Failure setting the load driver privilege. Debugging may be limited.';
|
|
rsFailureSettingTheCreateGlobalPrivilege = 'Failure setting the CreateGlobal privilege.';
|
|
rsCurrentProcess = 'Current process';
|
|
rsBusy = '<busy>';
|
|
rsFileInUse = '<File in use>';
|
|
rsPleaseWait = '<Processing>';
|
|
rsCEError = 'CE Error:';
|
|
rsPart = ' part ';
|
|
rsChangeValue = 'Change value';
|
|
rsGiveTheNewValueForTheSelectedAddressEs = 'Give the new value for the selected address(es)';
|
|
rsOverlay = 'overlay ';
|
|
rsWasClickedAtPositon = ' was clicked at positon ';
|
|
rsWidth = ' - width=';
|
|
rsHeight = ' , height=';
|
|
rsUnableToScanFixYourScanSettings = 'Unable to scan. Fix your scan settings and restart '+strCheatEngine;
|
|
rsCustomLuaType = 'Custom LUA type';
|
|
rsCustomTypeName = 'Custom Type Name';
|
|
rsLanguage = 'Language';
|
|
rsChooseLanguage = 'Which language do you wish to use?';
|
|
rsInvalidScanFolder = '%s is not accessible like it should. Please '
|
|
+'configure a proper location in the settings';
|
|
rsProcessing = '<Processing>';
|
|
rsCompareToSavedScan = 'Compare to first/saved scan';
|
|
rsModified = 'Modified';
|
|
rsRequiresDBVMCapableCPU = 'This function requires an CPU with '
|
|
+'virtualization support. If your system has that then make sure that '
|
|
+'you''re currently not running inside a virtual machine. (Windows has '
|
|
+'some security features that can run programs inside a VM)';
|
|
rsRequiresEPT = 'This function requires that your CPU supports ''Intel Extended '
|
|
+'Page Table (EPT) or AMD Nested Paging'' which your CPU lacks';
|
|
rsRequiresDBVMEPT = 'DBVM find routines needs DBVM for EPT/NP page hooking. '
|
|
+'Loading DBVM can potentially cause a system freeze. Are you sure?';
|
|
rsDbvmWatchFailed = 'dbvm_watch failed';
|
|
rsAreYouSure = 'Are you sure?';
|
|
rsClearRecentFiles = 'Empty Recent Files List';
|
|
rsFirst = 'First';
|
|
rsEnableSpeedHack = 'Enable '+strSpeedHack;
|
|
rsPreviousValueList = 'Previous value list';
|
|
rsSelectTheSavedResult = 'Select the saved results you wish to use';
|
|
rsNetworkOption = 'Network option :';
|
|
rsClearingMeansSlowness = 'Clearing the assigned memory for this process '
|
|
+'will cause it to obtain all the memory it needs again which can cause a '
|
|
+'temporary slowdown in the target. Make sure the value you''re interested '
|
|
+'in gets accessed once before you scan. Continue?';
|
|
|
|
const
|
|
VARTYPE_INDEX_BINARY=0;
|
|
VARTYPE_INDEX_BYTE=1;
|
|
VARTYPE_INDEX_WORD=2;
|
|
VARTYPE_INDEX_DWORD=3;
|
|
VARTYPE_INDEX_QWORD=4;
|
|
VARTYPE_INDEX_SINGLE=5;
|
|
VARTYPE_INDEX_DOUBLE=6;
|
|
VARTYPE_INDEX_TEXT=7;
|
|
VARTYPE_INDEX_AOB=8;
|
|
VARTYPE_INDEX_ALL=9;
|
|
VARTYPE_INDEX_GROUPED=10;
|
|
VARTYPE_INDEX_CUSTOMBASE=11;
|
|
|
|
|
|
var
|
|
ncol: TColor;
|
|
|
|
procedure TFlash.Col;
|
|
begin
|
|
if ncol=graphics.cldefault then
|
|
mainform.panel7.Color:=mainform.Color
|
|
else
|
|
mainform.panel7.Color := ncol;
|
|
end;
|
|
|
|
procedure TFlash.Execute;
|
|
var
|
|
red, green: byte;
|
|
decreasered: boolean;
|
|
begin
|
|
|
|
{$ifndef ceasinjecteddll}
|
|
decreasered := True;
|
|
red := 254;
|
|
green := 0;
|
|
while not terminated do
|
|
begin
|
|
if decreasered then
|
|
begin
|
|
Dec(red, 2);
|
|
Inc(green, 2);
|
|
if green >= 250 then
|
|
decreasered := False;
|
|
end
|
|
else
|
|
begin
|
|
Inc(red, 2);
|
|
Dec(green, 2);
|
|
if red >= 254 then
|
|
decreasered := True;
|
|
end;
|
|
ncol := (green shl 8) + red;
|
|
|
|
if not terminated then
|
|
synchronize(@col);
|
|
|
|
sleep(10);
|
|
end;
|
|
|
|
{$endif}
|
|
ncol := graphics.cldefault;
|
|
synchronize(@col);
|
|
end;
|
|
|
|
constructor TToggleWindows.Create(CreateSuspended: boolean);
|
|
begin
|
|
freeonterminate := True;
|
|
inherited Create(CreateSuspended);
|
|
end;
|
|
|
|
procedure TToggleWindows.Execute;
|
|
begin
|
|
toggleotherwindows;
|
|
togglewindows := nil;
|
|
end;
|
|
|
|
|
|
//--------------TFreezeThread------------
|
|
procedure TFreezeThread.applyFreeze;
|
|
begin
|
|
faddresslist.ApplyFreeze;
|
|
end;
|
|
|
|
procedure TFreezeThread.Execute;
|
|
begin
|
|
while not terminated do
|
|
begin
|
|
synchronize(@applyFreeze); //has to be synchronized as the addreslist records are accessed by treenode indexes, which are GUI based
|
|
sleep(freezeInterval);
|
|
end;
|
|
end;
|
|
|
|
constructor TFreezeThread.Create(AddressList: TAddresslist; interval: integer);
|
|
begin
|
|
fAddressList:=addressList;
|
|
freezeInterval:=interval;
|
|
inherited create(false);
|
|
end;
|
|
|
|
//--------------TMainThread------------
|
|
|
|
procedure TMainForm.recentFilesUpdate(filepath: string);
|
|
var i: integer;
|
|
begin
|
|
i:=recentfiles.IndexOf(filepath);
|
|
if i<>-1 then
|
|
begin
|
|
//move the old entry to the top
|
|
recentfiles.Delete(i);
|
|
recentfiles.Insert(0,filepath);
|
|
end
|
|
else
|
|
begin
|
|
//new entry
|
|
recentfiles.insert(0, filepath);
|
|
while recentfiles.count>20 do
|
|
recentfiles.Delete(recentfiles.count-1);
|
|
end;
|
|
cereg.writeStrings('Recent Files', recentfiles);
|
|
end;
|
|
|
|
function TMainForm.getUseThreadToFreeze: boolean;
|
|
begin
|
|
result:=freezeThread<>nil;
|
|
end;
|
|
|
|
procedure TMainForm.setUseThreadToFreeze(state: boolean);
|
|
begin
|
|
if freezethread<>nil then
|
|
begin
|
|
if state then //update?
|
|
begin
|
|
if freezethread.freezeInterval<>freezetimer.interval then
|
|
freezethread.freezeInterval:=freezetimer.interval;
|
|
end
|
|
else
|
|
freeandnil(freezethread);
|
|
end
|
|
else
|
|
begin
|
|
if state then
|
|
freezethread:=TFreezeThread.Create(addresslist,freezetimer.interval);
|
|
end;
|
|
|
|
|
|
|
|
freezetimer.enabled:=not state;
|
|
end;
|
|
|
|
procedure TMainForm.setIsProtected(p: boolean); //super unhackable protection yeeeeeh
|
|
//I'll sue you for DMCA violations if you edit this code!!!! Really! I mean it! I do!!!!
|
|
var
|
|
i: integer;
|
|
begin
|
|
fIsProtected := p;
|
|
|
|
if p then
|
|
begin
|
|
|
|
//It's fucking time!!!!
|
|
FreeAndNil(advancedoptions);
|
|
FreeAndNil(actionlist1);
|
|
|
|
for i := 0 to ControlCount - 1 do
|
|
Controls[i].Visible := False;
|
|
|
|
mainform.menu := nil;
|
|
|
|
addresslist.PopupMenu := nil;
|
|
addresslist.Enabled := False;
|
|
|
|
Visible := False;
|
|
|
|
miTable.Enabled := False;
|
|
while miTable.Count > 0 do
|
|
miTable.Delete(0);
|
|
|
|
FreeAndNil(changescript1);
|
|
|
|
frmLuaTableScript.assemblescreen.ClearAll;
|
|
frmLuaTableScript.assemblescreen.Text:='wut?';
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.CheckForSpeedhackKey(sender: TObject);
|
|
var
|
|
s: integer;
|
|
down: boolean;
|
|
begin
|
|
// if speed
|
|
s:=ttimer(sender).tag;
|
|
down:=false;
|
|
|
|
case s of
|
|
1: down:=CheckKeyCombo(speedhackspeed1.keycombo);
|
|
2: down:=CheckKeyCombo(speedhackspeed2.keycombo);
|
|
3: down:=CheckKeyCombo(speedhackspeed3.keycombo);
|
|
4: down:=CheckKeyCombo(speedhackspeed4.keycombo);
|
|
5: down:=CheckKeyCombo(speedhackspeed5.keycombo);
|
|
end;
|
|
|
|
if not down then
|
|
begin
|
|
editsh2.Text := '1';
|
|
btnSetSpeedhack2.Click;
|
|
ttimer(sender).enabled:=false;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Hotkey2(command: integer);
|
|
type
|
|
PNotifyEvent = ^TNotifyEvent;
|
|
var
|
|
i: integer;
|
|
a, b: single;
|
|
s: string;
|
|
|
|
hk: TMemoryRecordHotkey;
|
|
gh: TGenericHotkey;
|
|
|
|
hOtherWin : THandle;
|
|
OtherThreadID : DWORD;
|
|
CurrentThreadID : DWORD;
|
|
lockTimeOut: DWORD;
|
|
pid: dword;
|
|
begin
|
|
|
|
case command of
|
|
0:
|
|
begin
|
|
{$ifdef windows}
|
|
GetWindowThreadProcessId(GetForegroundWindow, pid);
|
|
ce_openProcess(pid);
|
|
{$endif}
|
|
end;
|
|
1:
|
|
begin
|
|
//popup/hide CE
|
|
{$ifdef windows}
|
|
if advancedoptions.Pausebutton.Down then
|
|
begin
|
|
errorbeep;
|
|
exit;
|
|
end;
|
|
|
|
hOtherWin := GetForegroundWindow;
|
|
GetWindowThreadProcessID( hOtherWin, OtherThreadID);
|
|
CurrentThreadID := GetCurrentThreadID;
|
|
|
|
if CurrentThreadID<>OtherThreadID then
|
|
begin
|
|
AttachThreadInput( CurrentThreadID, OtherThreadID, true );
|
|
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @lockTimeOut, 0);
|
|
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, 0);
|
|
AllowSetForegroundWindow(ASFW_ANY);
|
|
end;
|
|
|
|
beep;
|
|
|
|
if formsettings.frameHotkeyConfig.cbHideAllWindows.Checked then
|
|
begin
|
|
ToggleWindow;
|
|
|
|
if formsettings.frameHotkeyConfig.cbCenterOnPopup.Checked then
|
|
if not allwindowsareback then
|
|
setwindowpos(mainform.Handle, HWND_NOTOPMOST, (screen.Width div 2) -
|
|
(mainform.Width div 2), (screen.Height div 2) -
|
|
(mainform.Height div 2), mainform.Width, mainform.Height,
|
|
SWP_NOZORDER or SWP_NOACTIVATE);
|
|
|
|
if not allwindowsareback then
|
|
begin
|
|
application.BringToFront;
|
|
if CurrentThreadID<>OtherThreadID then
|
|
begin
|
|
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, @lockTimeOut, 0);
|
|
AttachThreadInput( CurrentThreadID, OtherThreadID, false );
|
|
end;
|
|
end
|
|
else
|
|
setforegroundwindow(lastforeground);
|
|
|
|
adjustbringtofronttext;
|
|
exit;
|
|
end;
|
|
|
|
application.BringToFront;
|
|
SetForegroundWindow(mainform.Handle);
|
|
|
|
mainform.SetFocus;
|
|
|
|
if CurrentThreadID<>OtherThreadID then
|
|
begin
|
|
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, @lockTimeOut, 0);
|
|
AttachThreadInput( CurrentThreadID, OtherThreadID, false );
|
|
end;
|
|
|
|
if formsettings.frameHotkeyConfig.cbCenterOnPopup.Checked then
|
|
setwindowpos(mainform.Handle, HWND_NOTOPMOST, (screen.Width div 2) -
|
|
(mainform.Width div 2), (screen.Height div 2) -
|
|
(mainform.Height div 2), mainform.Width, mainform.Height,
|
|
SWP_NOZORDER or SWP_NOACTIVATE);
|
|
|
|
formstyle := fsStayOnTop;
|
|
{$endif}
|
|
end;
|
|
|
|
2: //Pause
|
|
begin
|
|
with advancedoptions do
|
|
begin
|
|
pausedbyhotkey := True;
|
|
pausebutton.down := not pausebutton.down;
|
|
pausebutton.Click;
|
|
pausedbyhotkey := False;
|
|
end;
|
|
end;
|
|
|
|
3: //speedhack
|
|
begin
|
|
if cbSpeedhack.Enabled then
|
|
begin
|
|
try
|
|
cbSpeedhack.Checked := not cbSpeedhack.Checked;
|
|
btnSetSpeedhack2.Click;
|
|
beep;
|
|
except
|
|
errorbeep;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//3..7=set speedhack speed
|
|
4:
|
|
begin
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
try
|
|
cbspeedhack.Checked := True;
|
|
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
editsh2.Text := format('%.3f', [speedhackspeed1.speed]); //Just rebuild. I wish this would get fixed in fpc someday...
|
|
btnSetSpeedhack2.Click;
|
|
|
|
if speedhackspeed1.disablewhenreleased then
|
|
begin
|
|
//spawn a timer
|
|
if speedhackDisableTimer=nil then
|
|
begin
|
|
speedhackDisableTimer:=TTimer.create(self);
|
|
speedhackDisableTimer.OnTimer:=@CheckForSpeedhackKey;
|
|
end;
|
|
|
|
speedhackDisableTimer.Interval:=hotkeyPollInterval;
|
|
speedhackDisableTimer.Tag:=1;
|
|
speedhackDisableTimer.enabled:=true;
|
|
end;
|
|
|
|
end;
|
|
except
|
|
errorbeep;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
5:
|
|
begin
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
cbspeedhack.Checked := True;
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
editsh2.Text := format('%.3f', [speedhackspeed2.speed]);
|
|
btnSetSpeedhack2.Click;
|
|
|
|
if speedhackspeed2.disablewhenreleased then
|
|
begin
|
|
//spawn a timer
|
|
if speedhackDisableTimer=nil then
|
|
begin
|
|
speedhackDisableTimer:=TTimer.create(self);
|
|
speedhackDisableTimer.OnTimer:=@CheckForSpeedhackKey;
|
|
end;
|
|
|
|
speedhackDisableTimer.Interval:=hotkeyPollInterval;
|
|
speedhackDisableTimer.Tag:=2;
|
|
speedhackDisableTimer.enabled:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
6:
|
|
begin
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
cbspeedhack.Checked := True;
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
editsh2.Text := format('%.3f', [speedhackspeed3.speed]);
|
|
btnSetSpeedhack2.Click;
|
|
|
|
if speedhackspeed3.disablewhenreleased then
|
|
begin
|
|
//spawn a timer
|
|
if speedhackDisableTimer=nil then
|
|
begin
|
|
speedhackDisableTimer:=TTimer.create(self);
|
|
speedhackDisableTimer.OnTimer:=@CheckForSpeedhackKey;
|
|
end;
|
|
|
|
speedhackDisableTimer.Interval:=hotkeyPollInterval;
|
|
speedhackDisableTimer.Tag:=3;
|
|
speedhackDisableTimer.enabled:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
7:
|
|
begin
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
cbspeedhack.Checked := True;
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
editsh2.Text := format('%.3f', [speedhackspeed4.speed]);
|
|
btnSetSpeedhack2.Click;
|
|
|
|
if speedhackspeed4.disablewhenreleased then
|
|
begin
|
|
//spawn a timer
|
|
if speedhackDisableTimer=nil then
|
|
begin
|
|
speedhackDisableTimer:=TTimer.create(self);
|
|
speedhackDisableTimer.OnTimer:=@CheckForSpeedhackKey;
|
|
end;
|
|
|
|
speedhackDisableTimer.Interval:=hotkeyPollInterval;
|
|
speedhackDisableTimer.Tag:=4;
|
|
speedhackDisableTimer.enabled:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
8:
|
|
begin
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
cbspeedhack.Checked := True;
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
editsh2.Text := format('%.3f', [speedhackspeed5.speed]);
|
|
btnSetSpeedhack2.Click;
|
|
|
|
if speedhackspeed5.disablewhenreleased then
|
|
begin
|
|
//spawn a timer
|
|
if speedhackDisableTimer=nil then
|
|
begin
|
|
speedhackDisableTimer:=TTimer.create(self);
|
|
speedhackDisableTimer.OnTimer:=@CheckForSpeedhackKey;
|
|
end;
|
|
|
|
speedhackDisableTimer.Interval:=hotkeyPollInterval;
|
|
speedhackDisableTimer.Tag:=5;
|
|
speedhackDisableTimer.enabled:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
9:
|
|
begin
|
|
//increase speed
|
|
try
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
cbspeedhack.Checked := True;
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
a := strtofloat(editsh2.Text);
|
|
a := a + speedupdelta;
|
|
editsh2.Text := format('%.3f', [a]);
|
|
btnSetSpeedhack2.Click;
|
|
end;
|
|
end;
|
|
except
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
10:
|
|
begin
|
|
//decrease speed
|
|
try
|
|
if cbspeedhack.Enabled then
|
|
begin
|
|
cbspeedhack.Checked := True;
|
|
if cbspeedhack.Checked then
|
|
begin
|
|
b := strtofloat(editsh2.Text);
|
|
b := b - slowdowndelta;
|
|
editsh2.Text := format('%.3f', [b]);
|
|
btnSetSpeedhack2.Click;
|
|
end;
|
|
end;
|
|
except
|
|
|
|
end;
|
|
end;
|
|
|
|
11..19: //Change type (if possible)
|
|
begin
|
|
if vartype.Enabled then
|
|
vartype.ItemIndex := command-11
|
|
else
|
|
begin
|
|
errorbeep;
|
|
end;
|
|
end;
|
|
|
|
20://new scan
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit; //only when no process is opened
|
|
|
|
i := vartype.ItemIndex;
|
|
|
|
if btnNewScan.Caption = strNewScan then
|
|
btnNewScan.Click; //start new scan
|
|
|
|
vartype.ItemIndex := i;
|
|
vartype.OnChange(vartype); //set previous type
|
|
end;
|
|
|
|
21: //new scan Exact value
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
i := vartype.ItemIndex;
|
|
s := scanvalue.Text;
|
|
if s = '' then
|
|
exit;
|
|
|
|
if btnNewScan.Caption = strNewScan then
|
|
btnNewScan.Click; //start new scan
|
|
|
|
vartype.ItemIndex := i;
|
|
vartype.OnChange(vartype); //set previous type
|
|
|
|
scanvalue.Text := s;
|
|
btnNewScan.Click;
|
|
end;
|
|
|
|
22: //new scan unknown initial value
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
i := vartype.ItemIndex;
|
|
|
|
if btnNewScan.Caption = strNewScan then
|
|
btnNewScan.Click; //start new scan
|
|
|
|
vartype.ItemIndex := i;
|
|
vartype.OnChange(vartype);
|
|
|
|
scantype.ItemIndex := scantype.Items.IndexOf(StrUnknownInitialValue);
|
|
scantype.OnChange(scantype);
|
|
|
|
btnNewScan.Click;
|
|
end;
|
|
|
|
23: //next scan Exact value
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
|
|
if btnNextScan.Enabled then
|
|
begin
|
|
scantype.ItemIndex := scantype.Items.IndexOf(StrExactValue);
|
|
scantype.OnChange(scantype);
|
|
|
|
btnNextScan.click;
|
|
end
|
|
else
|
|
Errorbeep;
|
|
end;
|
|
|
|
24: //next scan IncreasedValue
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
|
|
if btnNextScan.Enabled then
|
|
begin
|
|
scantype.ItemIndex := scantype.Items.IndexOf(StrIncreasedValue);
|
|
scantype.OnChange(scantype);
|
|
|
|
btnNextScan.click;
|
|
end
|
|
else
|
|
Errorbeep;
|
|
end;
|
|
|
|
25: //next scan DecreasedValue
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
|
|
if btnNextScan.Enabled then
|
|
begin
|
|
scantype.ItemIndex := scantype.Items.IndexOf(StrDecreasedValue);
|
|
scantype.OnChange(scantype);
|
|
|
|
btnNextScan.click;
|
|
end
|
|
else
|
|
Errorbeep;
|
|
end;
|
|
|
|
26: //next scan ChangedValue
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
|
|
if btnNextScan.Enabled then
|
|
begin
|
|
i:=scantype.Items.IndexOf(StrChangedValue);
|
|
if i<>-1 then
|
|
begin
|
|
scantype.ItemIndex := i;
|
|
scantype.OnChange(scantype);
|
|
|
|
btnNextScan.click;
|
|
end;
|
|
end
|
|
else
|
|
Errorbeep;
|
|
end;
|
|
|
|
27: //next scan unchangedValue
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
|
|
if btnNextScan.Enabled then
|
|
begin
|
|
i:=scantype.Items.IndexOf(StrUnchangedValue);
|
|
if i<>-1 then
|
|
begin
|
|
scantype.ItemIndex := i;
|
|
scantype.OnChange(scantype);
|
|
|
|
btnNextScan.click;
|
|
end;
|
|
end
|
|
else
|
|
Errorbeep;
|
|
end;
|
|
|
|
28: //next scan same as first
|
|
begin
|
|
if cbCompareToSavedScan.enabled then
|
|
cbCompareToSavedScan.checked:=not cbCompareToSavedScan.checked;
|
|
end;
|
|
|
|
29: //undo lastscan
|
|
begin
|
|
|
|
if not btnNewScan.Enabled then
|
|
exit;
|
|
|
|
|
|
if undoscan.Enabled then
|
|
UndoScanClick(nil)
|
|
else
|
|
Errorbeep;
|
|
end;
|
|
|
|
30: //cancel current scan
|
|
begin
|
|
if cancelbutton <> nil then
|
|
cancelbutton.Click;
|
|
end;
|
|
|
|
31: //debug->run
|
|
begin
|
|
|
|
if memorybrowser.miDebugRun.enabled then
|
|
MemoryBrowser.miDebugRun.Click;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.hotkey(var Message: TMessage);
|
|
//stays because the old hotkeyhandler is still used in some places
|
|
begin
|
|
{$ifdef windows}
|
|
|
|
if (formhotkey <> nil) and (formhotkey.Visible) then
|
|
exit;
|
|
|
|
if Message.wparam = 0 then
|
|
begin
|
|
//bring to front
|
|
try
|
|
unregisterhotkey(mainform.handle, 0);
|
|
|
|
if advancedoptions.Pausebutton.Down then
|
|
begin
|
|
beep;
|
|
sleep(100);
|
|
beep;
|
|
sleep(100);
|
|
beep;
|
|
sleep(100);
|
|
exit;
|
|
end;
|
|
|
|
beep;
|
|
|
|
if formsettings.frameHotkeyConfig.cbHideAllWindows.Checked then
|
|
begin
|
|
ToggleWindow;
|
|
|
|
// ToggleOtherWindows;
|
|
|
|
if formsettings.frameHotkeyConfig.cbCenterOnPopup.Checked then
|
|
if not allwindowsareback then
|
|
setwindowpos(mainform.Handle, HWND_NOTOPMOST, (screen.Width div 2) -
|
|
(mainform.Width div 2), (screen.Height div 2) - (mainform.Height div
|
|
2), mainform.Width, mainform.Height, SWP_NOZORDER or SWP_NOACTIVATE);
|
|
|
|
if not allwindowsareback then
|
|
application.BringToFront
|
|
else
|
|
begin
|
|
setforegroundwindow(lastforeground);
|
|
// setactivewindow(lastactive);
|
|
end;
|
|
|
|
adjustbringtofronttext;
|
|
exit;
|
|
end;
|
|
|
|
|
|
// if length(windowlist)<>0 then
|
|
application.BringToFront;
|
|
|
|
if formsettings.frameHotkeyConfig.cbCenterOnPopup.Checked then
|
|
setwindowpos(mainform.Handle, HWND_NOTOPMOST, (screen.Width div 2) -
|
|
(mainform.Width div 2), (screen.Height div 2) - (mainform.Height div
|
|
2), mainform.Width, mainform.Height, SWP_NOZORDER or SWP_NOACTIVATE);
|
|
|
|
formstyle := fsStayOnTop;
|
|
|
|
finally
|
|
registerhotkey(mainform.handle, 0, message.lparamlo, message.LParamHi);
|
|
//restore the hotkey
|
|
end;
|
|
end;
|
|
|
|
|
|
if message.WParam = 2 then //toggle speedhack
|
|
begin
|
|
|
|
try
|
|
unregisterhotkey(mainform.handle, 2);
|
|
if cbSpeedhack.Enabled then
|
|
begin
|
|
beep;
|
|
cbSpeedhack.Checked := not cbSpeedhack.Checked;
|
|
end;
|
|
finally
|
|
registerhotkey(mainform.handle, 2, message.lparamlo, message.LParamHi);
|
|
//restore the hotkey
|
|
end;
|
|
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
procedure TMainForm.PluginSync(var m: TMessage);
|
|
var
|
|
func: TPluginFunc;
|
|
params: pointer;
|
|
begin
|
|
func := TPluginFunc(pointer(m.wparam));
|
|
params := pointer(m.lparam);
|
|
|
|
|
|
m.Result := ptruint(func(params));
|
|
end;
|
|
|
|
procedure TMainForm.ShowError;
|
|
var fn: string;
|
|
nosaveerror: boolean;
|
|
s: string;
|
|
path: string;
|
|
begin
|
|
|
|
try
|
|
nosaveerror:=false;
|
|
fn:=ExtractFileName(SaveDialog1.filename);
|
|
if fn='' then
|
|
begin
|
|
fn:='noname.ct';
|
|
path:=opendialog1.InitialDir;
|
|
end
|
|
else
|
|
begin
|
|
if lowercase(ExtractFileExt(fn))<>'.ct' then
|
|
fn:=fn+'.ct';
|
|
|
|
path:=ExtractFilePath(SaveDialog1.filename);
|
|
end;
|
|
|
|
|
|
|
|
fn:='ExceptionAutoSave_'+fn;
|
|
fn:=path+fn;
|
|
SaveTable(fn);
|
|
nosaveerror:=true;
|
|
except
|
|
end;
|
|
|
|
if nosaveerror then
|
|
begin
|
|
s:=currentexceptionerror+#13#10+'The current table has been saved to '+fn;
|
|
MessageDlg(s, mterror,[mbok],0);
|
|
end
|
|
else
|
|
begin
|
|
MessageDlg(currentexceptionerror, mterror,[mbok],0);
|
|
end;
|
|
|
|
end;
|
|
|
|
//----------------------------------
|
|
|
|
function TMainForm.getSelectedVariableType: TVariableType;
|
|
{wrapper for the new getVarType2 in the new scanroutine}
|
|
begin
|
|
Result := getVarType2;
|
|
end;
|
|
|
|
function TMainForm.getScanStart: ptruint;
|
|
begin
|
|
try
|
|
Result := symhandler.getAddressFromName(FromAddress.Text);
|
|
except
|
|
raise Exception.Create(Format(rsInvalidStartAddress, [FromAddress.Text]));
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.setScanStart(newscanstart: ptruint);
|
|
begin
|
|
FromAddress.Text := inttohex(newscanstart, 8);
|
|
end;
|
|
|
|
function TMainForm.getScanStop: ptruint;
|
|
begin
|
|
try
|
|
Result := symhandler.getAddressFromName(ToAddress.Text);
|
|
except
|
|
raise Exception.Create(Format(rsInvalidStopAddress, [ToAddress.Text]));
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.setScanStop(newscanstop: ptruint);
|
|
begin
|
|
ToAddress.Text := inttohex(newscanstop, 8);
|
|
end;
|
|
|
|
|
|
function TMainForm.getFastscan: boolean;
|
|
begin
|
|
Result := cbFastscan.Enabled and cbFastscan.Checked;
|
|
end;
|
|
|
|
procedure TMainForm.setFastScan(state: boolean);
|
|
begin
|
|
cbFastscan.Checked := state;
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TMainForm.GetRoundingType: TRoundingType;
|
|
{Property function to get the current rounding type}
|
|
begin
|
|
Result := rtTruncated;
|
|
if rt1.Checked then
|
|
Result := rtRounded
|
|
else
|
|
if rt2.Checked then
|
|
Result := rtExtremerounded
|
|
else
|
|
if rt3.Checked then
|
|
Result := rtTruncated;
|
|
end;
|
|
|
|
procedure TMainForm.SetRoundingType(rt: TRoundingType);
|
|
{Property function to set the current rounding type}
|
|
begin
|
|
case rt of
|
|
rtRounded: rt1.Checked;
|
|
rtExtremerounded: rt2.Checked;
|
|
rtTruncated: rt3.Checked;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.setfoundcount(x: int64);
|
|
var
|
|
xdouble: double;
|
|
begin
|
|
ffoundcount := x;
|
|
xdouble := x;
|
|
foundcountlabel.Caption := Format('%.0n', [xdouble]);
|
|
end;
|
|
|
|
procedure TMainForm.DestroyCancelButton;
|
|
begin
|
|
if cancelbutton <> nil then
|
|
FreeAndNil(cancelbutton);
|
|
if cancelbuttonenabler <> nil then
|
|
FreeAndNil(cancelbuttonenabler);
|
|
end;
|
|
|
|
procedure TMainForm.SpawnCancelButton;
|
|
begin
|
|
cancelbutton := TButton.Create(self);
|
|
with cancelbutton do
|
|
begin
|
|
Anchors := btnNewScan.Anchors;
|
|
top := btnNewScan.top;
|
|
left := btnNewScan.left;
|
|
Width := (btnNextScan.left + btnNextScan.Width) - left;
|
|
Height := btnNewScan.Height;
|
|
Caption := rsCancel;
|
|
onclick := @cancelbuttonclick;
|
|
Enabled := False;
|
|
tag := 0; //0=normal 1=force
|
|
|
|
Hint := rsThisButtonWillTryToCancelTheCurrentScanClickTwiceT;
|
|
ParentShowHint := False;
|
|
ShowHint := True;
|
|
|
|
|
|
cancelbutton.Anchors:=[];
|
|
cancelbutton.AnchorSideLeft.Control:=btnNewScan;
|
|
cancelbutton.AnchorSideLeft.Side:=asrLeft;
|
|
cancelbutton.Anchors:=[akLeft, akTop];
|
|
cancelbutton.name:='CancelButton';
|
|
|
|
parent := panel5;
|
|
end;
|
|
|
|
cancelbuttonenabler := TTimer.Create(self);
|
|
|
|
with cancelbuttonenabler do
|
|
begin
|
|
interval := 2000; //2 seconds
|
|
OnTimer := @cancelbuttonenablerinterval;
|
|
Enabled := True;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.disableGui;
|
|
{
|
|
This procedure will disable the gui. E.g while scanning the memory with no wait
|
|
screen.
|
|
}
|
|
begin
|
|
setGbScanOptionsEnabled(False);
|
|
|
|
scanvalue.Enabled := False;
|
|
if scanvalue2 <> nil then
|
|
begin
|
|
scanvalue2.Enabled := False;
|
|
andlabel.Enabled := False;
|
|
scantext2.Enabled := False;
|
|
end;
|
|
|
|
vartype.Enabled := False;
|
|
scantype.Enabled := False;
|
|
scantext.Enabled := False;
|
|
lblScanType.Enabled := False;
|
|
lblValueType.Enabled := False;
|
|
cbHexadecimal.Enabled := False;
|
|
cbCaseSensitive.Enabled := False;
|
|
|
|
btnNewScan.Enabled := False;
|
|
btnNextScan.Enabled := False;
|
|
undoscan.Enabled := False;
|
|
|
|
cbNot.Enabled:=false;
|
|
cbLuaFormula.enabled:=false;
|
|
cbNewLuaState.enabled:=false;
|
|
|
|
miAddTab.enabled:=false;
|
|
if scantablist<>nil then
|
|
scantablist.Enabled:=false;
|
|
end;
|
|
|
|
procedure TMainForm.enableGui(isnextscan: boolean);
|
|
{
|
|
Enables the gui options according to what type of scan is currently used
|
|
no scan, enable everything
|
|
already scanning, disable the group and type
|
|
}
|
|
var
|
|
scanstarted: boolean;
|
|
begin
|
|
|
|
scanstarted := btnNewScan.Caption = strnewscan;
|
|
|
|
if not scanstarted then
|
|
begin
|
|
setGbScanOptionsEnabled(True);
|
|
end;
|
|
|
|
scanvalue.Enabled := True;
|
|
if scanvalue2 <> nil then
|
|
begin
|
|
scanvalue2.Enabled := True;
|
|
andlabel.Enabled := True;
|
|
scantext2.Enabled := True;
|
|
end;
|
|
btnNewScan.Enabled := True;
|
|
|
|
undoscan.Enabled := isnextscan and memscan.canUndo; //nextscan was already enabled
|
|
btnNextScan.Enabled := scanstarted;
|
|
vartype.Enabled := not scanstarted;
|
|
scantype.Enabled := True;
|
|
scantext.Enabled := True;
|
|
lblScanType.Enabled := True;
|
|
lblValueType.Enabled := True;
|
|
cbHexadecimal.Enabled := True;
|
|
cbCaseSensitive.Enabled := True;
|
|
cbNot.enabled:=true;
|
|
cbLuaFormula.enabled:=true;
|
|
cbNewLuaState.enabled:=true;
|
|
|
|
|
|
scanvalue.Visible := True;
|
|
scantext.Visible := True;
|
|
|
|
Updatescantype;
|
|
Scantype.ItemIndex := 0;
|
|
|
|
//-----------------------
|
|
//Get the expectedFilename
|
|
//-----------------------
|
|
SetExpectedTableName;
|
|
|
|
cbspeedhack.Enabled := True;
|
|
cbunrandomizer.Enabled := True;
|
|
|
|
miAddTab.enabled:=true;
|
|
if scantablist<>nil then
|
|
scantablist.Enabled:=true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.toggleWindow;
|
|
var
|
|
c: integer;
|
|
begin
|
|
togglewindows := TTogglewindows.Create(False);
|
|
c := 0;
|
|
while togglewindows <> nil do
|
|
begin
|
|
if c = 500 then
|
|
begin
|
|
freeandnil(togglewindows);
|
|
raise Exception.Create(strWindowFailedToHide);
|
|
end;
|
|
sleep(10);
|
|
Inc(c);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.exceptionhandler(Sender: TObject; E: Exception);
|
|
var
|
|
s: string;
|
|
op: string;
|
|
begin
|
|
//unhandled exeption. Also clean lua stack
|
|
s:={$ifdef THREADNAMESUPPORT}GetThreadName+': '+{$endif}'Unhandled exception: '+e.message+' (Exception class '+ e.ClassName+')';
|
|
|
|
|
|
{$ifdef windows}
|
|
if e is EAccessViolation then
|
|
begin
|
|
case EAccessViolation(e).ExceptionRecord^.ExceptionInformation[0] of
|
|
0: op:='read';
|
|
1: op:='write to';
|
|
8: op:='execute';
|
|
else op:='do something weird with';
|
|
end;
|
|
|
|
s:=s+' (tried to '+op+' address '+inttohex(qword(EAccessViolation(e).ExceptionRecord^.ExceptionInformation[1]),8)+')';
|
|
end;
|
|
{$endif}
|
|
|
|
|
|
if TraceExceptions then
|
|
begin
|
|
DebugLn(s);
|
|
|
|
|
|
DumpExceptionBackTrace;
|
|
|
|
s:=s+#13#10'Please send the cedebug.txt file to Dark Byte. Thanks';
|
|
end;
|
|
|
|
if showingException then exit; //don't bother showing another one. Just read the log
|
|
|
|
if exceptionerrorcs.TryEnter then //it's not important if it's already showing another error
|
|
begin
|
|
if showingException=false then //should be the case, but check anyhow
|
|
begin
|
|
currentexceptionerror:=s;
|
|
|
|
showingException:=true;
|
|
if MainThreadID=GetCurrentThreadId then
|
|
showerror
|
|
else
|
|
tthread.Synchronize(nil, @showerror);
|
|
|
|
showingException:=false;
|
|
end;
|
|
|
|
exceptionerrorcs.leave;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
function TMainForm.CheckIfSaved: boolean;
|
|
var
|
|
help: word;
|
|
begin
|
|
//result:=true;
|
|
Result := not editedsincelastsave;
|
|
|
|
|
|
if itemshavechanged then
|
|
Result := False;
|
|
|
|
if Result = False then
|
|
begin
|
|
help := messagedlg(strAskToSave, mtConfirmation, mbYesNoCancel, 0);
|
|
case help of
|
|
mrCancel: Result := False;
|
|
mrYes:
|
|
begin
|
|
|
|
SaveButton.click;
|
|
result:=not savegotcanceled;
|
|
end;
|
|
else
|
|
Result := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
//--------------------------cbpercentage--------------
|
|
procedure TMainForm.cbPercentageOnChange(Sender: TObject);
|
|
begin
|
|
if cbpercentage.Checked then
|
|
begin
|
|
//turn this into a double value scan like "value between"
|
|
CreateScanValue2;
|
|
ScanText.Caption := rsValue;
|
|
ScanText2.Caption := rsValue;
|
|
end
|
|
else
|
|
begin
|
|
if ScanType.Text <> strValueBetween then
|
|
begin
|
|
//single value scan
|
|
ScanText.Caption := strScantextcaptiontoValue;
|
|
DestroyScanValue2;
|
|
end
|
|
else
|
|
begin
|
|
ScanText.Caption := strScantextcaptiontoValue;
|
|
ScanText2.Caption := strScantextcaptiontoValue;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.CreateCbPercentage;
|
|
begin
|
|
cbpercentage.visible:=true;
|
|
|
|
if ScanType.Text = strValueBetween then
|
|
cbpercentage.Caption := rsBetween
|
|
else
|
|
cbpercentage.Caption := rsAtLeastXx;
|
|
|
|
UpdateFloatRelatedPositions;
|
|
end;
|
|
|
|
procedure TMainForm.DestroyCbPercentage;
|
|
begin
|
|
cbpercentage.Visible:=false;
|
|
end;
|
|
//------------------
|
|
|
|
procedure TMainForm.CreateScanValue2;
|
|
begin
|
|
scantext2.Caption := scantext.Caption;
|
|
|
|
andlabel.Visible:=true;
|
|
scanvalue2.visible:=true;
|
|
scantext2.visible:=true;
|
|
|
|
panel5.OnResize(panel5);
|
|
end;
|
|
|
|
procedure TMainForm.DestroyScanValue2;
|
|
begin
|
|
scanvalue2.visible:=false;
|
|
scantext2.visible:=false;
|
|
andlabel.visible:=false;
|
|
end;
|
|
|
|
procedure TMainForm.UpdateScanType;
|
|
var
|
|
OldText: string;
|
|
OldIndex: integer;
|
|
hexvis: boolean;
|
|
floatvis: boolean;
|
|
t: TStringList;
|
|
old, old2: TNotifyEvent;
|
|
ct: Tcustomtype;
|
|
begin
|
|
old := scantype.OnChange;
|
|
old2 := scantype.OnSelect;
|
|
scantype.OnChange := nil;
|
|
scantype.OnSelect := nil;
|
|
ct:=TCustomtype(vartype.Items.Objects[vartype.itemindex]);
|
|
|
|
try
|
|
OldIndex := Scantype.ItemIndex;
|
|
OldText := Scantype.Text;
|
|
hexvis := True;
|
|
floatvis := False;
|
|
|
|
ScanType.Items.Clear;
|
|
|
|
ScanText.Caption := strScantextcaptiontoValue;
|
|
|
|
|
|
|
|
if (varType.ItemIndex in [VARTYPE_INDEX_BYTE, VARTYPE_INDEX_WORD, VARTYPE_INDEX_DWORD, VARTYPE_INDEX_QWORD,
|
|
VARTYPE_INDEX_SINGLE, VARTYPE_INDEX_DOUBLE, VARTYPE_INDEX_ALL,VARTYPE_INDEX_GROUPED]) or
|
|
(vartype.ItemIndex >= VARTYPE_INDEX_CUSTOMBASE) then
|
|
//byte-word-dword--8bytes-float-double-all - custom
|
|
begin
|
|
if (ct<>nil) and ct.scriptUsesString then
|
|
begin
|
|
//same as stringscan
|
|
ScanText.Caption := strScanTextCaptionToText;
|
|
ScanType.Items.Add(strSearchForText);
|
|
hexvis := False;
|
|
end
|
|
else
|
|
begin
|
|
|
|
if (vartype.ItemIndex in [VARTYPE_INDEX_SINGLE, VARTYPE_INDEX_DOUBLE, VARTYPE_INDEX_ALL, VARTYPE_INDEX_GROUPED]) or (vartype.ItemIndex >= VARTYPE_INDEX_CUSTOMBASE) then //float/all/grouped, custom
|
|
begin
|
|
|
|
if (ct=nil) or (ct.scriptUsesFloat) then
|
|
begin
|
|
//handle as a float value
|
|
if oldindex = 0 then
|
|
floatvis := True;
|
|
|
|
if vartype.ItemIndex <> VARTYPE_INDEX_ALL then
|
|
hexvis := False;
|
|
end;
|
|
end;
|
|
|
|
ScanType.Items.Add(strExactValue);
|
|
ScanType.Items.Add(strBiggerThan);
|
|
ScanType.Items.Add(strsmallerThan);
|
|
ScanType.Items.Add(strValueBetween);
|
|
|
|
if btnNextScan.Enabled then
|
|
begin
|
|
scantype.Items.Add(strIncreasedValue);
|
|
Scantype.Items.Add(strIncreasedValueBy);
|
|
ScanType.Items.Add(strDecreasedValue);
|
|
ScanType.Items.Add(strDecreasedValueBy);
|
|
ScanType.Items.add(strChangedValue);
|
|
ScanType.Items.Add(strUnchangedValue);
|
|
ScanType.Items.Add(strIgnoreValue);
|
|
|
|
|
|
cbCompareToSavedScan.visible:=true;
|
|
t:=tstringlist.create;
|
|
if memscan.getsavedresults(t)>1 then
|
|
cbCompareToSavedScan.caption:=rsCompareToSavedScan
|
|
else
|
|
cbCompareToSavedScan.caption:=strCompareToFirstScan;
|
|
|
|
t.free;
|
|
end
|
|
else
|
|
begin
|
|
ScanType.Items.Add(strUnknownInitialValue);
|
|
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
|
|
case varType.ItemIndex of
|
|
VARTYPE_INDEX_BINARY:
|
|
begin
|
|
ScanType.Items.Add(strExact);
|
|
|
|
end;
|
|
|
|
|
|
|
|
VARTYPE_INDEX_TEXT:
|
|
begin //text
|
|
ScanText.Caption := strScanTextCaptionToText;
|
|
ScanType.Items.Add(strSearchForText);
|
|
//perhaps also a changed value and unchanged value scan
|
|
|
|
hexvis := False;
|
|
end;
|
|
|
|
VARTYPE_INDEX_AOB:
|
|
begin //array of bytes
|
|
ScanText.Caption := vartype.Items[8];
|
|
ScanType.Items.Add(strSearchforarray);
|
|
|
|
end;
|
|
|
|
end;
|
|
Scantype.DropDownCount := Scantype.items.Count;
|
|
|
|
|
|
|
|
if (oldtext = strUnknownInitialValue) and (btnNextScan.Enabled) then
|
|
scantype.ItemIndex := 0
|
|
else
|
|
scantype.ItemIndex := oldindex;
|
|
|
|
if (scantype.Text = strIncreasedValueBy) or (scantype.Text = strDecreasedValueBy) or
|
|
(scantype.Text = strValueBetween) then
|
|
begin
|
|
if btnNextScan.Enabled then
|
|
createCbPercentage;
|
|
|
|
end
|
|
else
|
|
begin
|
|
destroyCbPercentage;
|
|
|
|
end;
|
|
|
|
if scantype.Text = strValueBetween then
|
|
CreateScanValue2
|
|
else
|
|
DestroyScanValue2;
|
|
|
|
|
|
if (scantype.Text = strIncreasedValue) or (scantype.Text = strDecreasedValue) or
|
|
(scantype.Text = strChangedValue) or (scantype.Text = strUnchangedValue) or
|
|
(scantype.Text = strUnknownInitialValue) or (scantype.Text = strIgnoreValue) then
|
|
begin
|
|
Scantext.Visible := False;
|
|
Scanvalue.Visible := False;
|
|
cbHexadecimal.Visible := False;
|
|
cbNot.visible:=false;
|
|
end
|
|
else
|
|
begin
|
|
Scantext.Visible := True;
|
|
Scanvalue.Visible := True;
|
|
cbHexadecimal.Visible := hexvis;
|
|
|
|
cbNot.Visible:=not ((vartype.itemindex in [VARTYPE_INDEX_BINARY,VARTYPE_INDEX_TEXT,VARTYPE_INDEX_AOB,VARTYPE_INDEX_GROUPED]) or ((ct<>nil) and ct.scriptUsesString ));
|
|
end;
|
|
|
|
pnlfloat.Visible := floatvis;
|
|
|
|
if rbBit.Visible then
|
|
cbHexadecimal.Visible := False;
|
|
|
|
pnlScanValueOptions.visible:=(cbHexadecimal.Visible or rbDec.visible or rbBit.Visible);
|
|
|
|
|
|
//save the last scantype (if it wasn't the option to change between first/last)
|
|
if (scantype.ItemIndex <> -1) and (scantype.ItemIndex < scantype.Items.Count) then
|
|
begin
|
|
if not ((scantype.items[scantype.ItemIndex] = strcompareToSavedScan) or
|
|
(scantype.items[scantype.ItemIndex] = strCompareToLastScan)) then
|
|
lastscantype := scantype.ItemIndex;
|
|
end;
|
|
|
|
if (not cbHexadecimal.Visible) and (cbHexadecimal.checked) then //not visible but checked
|
|
begin
|
|
cbHexadecimal.checked:=hexvis;
|
|
end;
|
|
|
|
UpdateFloatRelatedPositions;
|
|
|
|
|
|
cbRepeatUntilStopped.visible:=GetScanType=soUnchanged;
|
|
|
|
cbLuaFormula.visible:=(GetScanType=soExactValue) and (getVarType in [vtByte, vtWord, vtDword, vtQword, vtSingle, vtDouble, vtCustom, vtAll]) and ((ct=nil) or (ct.scriptUsesString=false));
|
|
cbNewLuaState.visible:=cbLuaFormula.checked;
|
|
finally
|
|
scantype.OnChange := old;
|
|
scantype.OnSelect := old2;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.reinterpretaddresses;
|
|
begin
|
|
if addresslist <> nil then
|
|
addresslist.ReinterpretAddresses;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.AddAutoAssembleScript(script: string);
|
|
begin
|
|
addresslist.addAutoAssembleScript(script);
|
|
end;
|
|
|
|
procedure TMainForm.AddToRecord(Line: integer; node: TTreenode = nil;
|
|
attachmode: TNodeAttachMode = naAdd);
|
|
var
|
|
Address: ptrUint;
|
|
startbit: integer;
|
|
i,l: integer;
|
|
|
|
vt: TVariableType;
|
|
tempvartype: TVariableType;
|
|
addressstring: string;
|
|
newaddresstring: string;
|
|
|
|
ct: TCustomType;
|
|
customname: string;
|
|
m: TMemoryRecord;
|
|
ga: PGroupAddress;
|
|
|
|
gcp: TGroupscanCommandParser;
|
|
|
|
extra: dword;
|
|
value: string;
|
|
begin
|
|
|
|
//first check if this address is already in the list!
|
|
customname := '';
|
|
l := 0;
|
|
startbit := 0;
|
|
extra:=0;
|
|
ct:=nil;
|
|
gcp:=nil;
|
|
ga:=nil;
|
|
|
|
vt := getvartype;
|
|
if vt = vtBinary then //binary
|
|
begin
|
|
startbit := foundlist.getstartbit(line);
|
|
l := memscan.Getbinarysize;
|
|
end
|
|
else
|
|
if vt = vtAll then //all
|
|
begin
|
|
address:=foundlist.GetAddress(line, extra, Value);
|
|
|
|
if extra >= $1000 then
|
|
begin
|
|
ct:=TCustomType(customTypes[extra - $1000]);
|
|
customname := ct.Name;
|
|
vt:=vtCustom;
|
|
end
|
|
else
|
|
begin
|
|
ct:=nil;
|
|
vt := TVariableType(foundlist.getstartbit(line));
|
|
end;
|
|
|
|
|
|
end
|
|
else
|
|
if vt=vtCustom then //custom
|
|
begin
|
|
ct := TCustomType(vartype.items.objects[vartype.ItemIndex]);
|
|
customname := ct.Name;
|
|
end
|
|
else
|
|
begin
|
|
startbit := 0;
|
|
l := foundlist.GetVarLength;
|
|
end;
|
|
address := foundlist.GetAddress(line);
|
|
|
|
if foundlist.inmodule(line) then
|
|
addressString := foundlist.GetModuleNamePlusOffset(line)
|
|
else
|
|
addressstring := inttohex(address, 8);
|
|
|
|
|
|
if vt=vtGrouped then
|
|
begin
|
|
//add as a group
|
|
ga:=foundlist.GetGroupAddress(line);
|
|
if ga=nil then
|
|
raise exception.create(rsGroupscanDataInvalid);
|
|
|
|
gcp:=foundlist.getGCP;
|
|
if gcp=nil then
|
|
raise exception.create(rsGroupscanResultWithNoGroupscanparser);
|
|
|
|
|
|
for i:=0 to length(gcp.elements)-1 do
|
|
begin
|
|
if gcp.elements[i].picked then
|
|
begin
|
|
if gcp.elements[i].customtype<>nil then
|
|
customname:=gcp.elements[i].customtype.name
|
|
else
|
|
customname:='';
|
|
|
|
l:=gcp.elements[i].bytesize;
|
|
|
|
vt:=gcp.elements[i].vartype;
|
|
if vt=vtUnicodeString then
|
|
begin
|
|
vt:=vtString;
|
|
l:=l div 2;
|
|
end;
|
|
|
|
newaddresstring:=addressstring+'+'+inttohex(ga^.offsets[i],1);
|
|
addresslist.addaddress(strNoDescription, newaddresstring, [], 0, vt, customname, l, 0, gcp.elements[i].vartype=vtUnicodeString, node, attachmode);
|
|
end;
|
|
end;
|
|
|
|
end
|
|
else
|
|
begin
|
|
m := addresslist.addaddress(strNoDescription, addressString, [], 0,
|
|
vt, customname, l, startbit, False, node, attachmode);
|
|
|
|
m.showAsHex:=foundlist.isHexadecimal;
|
|
|
|
if m.VarType = vtBinary then
|
|
m.Extra.bitData.showasbinary := rbBit.Checked
|
|
else
|
|
if (m.VarType = vtString) then
|
|
begin
|
|
m.Extra.stringData.unicode := foundlist.isUnicode;
|
|
m.Extra.stringData.codepage := memscan.codePage;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.SetExpectedTableName;
|
|
var
|
|
fname: string;
|
|
expectedfilename: string;
|
|
begin
|
|
if UserDefinedTableName<>'' then exit;
|
|
|
|
|
|
Fname := copy(processlabel.Caption, pos('-', processlabel.Caption) + 1,
|
|
length(processLabel.Caption));
|
|
|
|
|
|
if (length(fname)>3) and (FName[length(FName) - 3] = '.') then //it's a filename
|
|
expectedFilename := copy(FName, 1, length(FName) - 4)
|
|
else //it's a normal title;
|
|
expectedFilename := FName;
|
|
|
|
savedialog1.FileName := expectedFilename;
|
|
Opendialog1.FileName := expectedFilename;
|
|
end;
|
|
|
|
|
|
|
|
function TMainForm.openprocessPrologue: boolean;
|
|
begin
|
|
if (processid<>0) and Globals.SyncSymbols then
|
|
SyncSymbolsNow;
|
|
|
|
Result := False;
|
|
|
|
if flashprocessbutton <> nil then
|
|
begin
|
|
flashprocessbutton.Terminate;
|
|
FreeAndNil(flashprocessbutton);
|
|
end;
|
|
|
|
|
|
canceled := False;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TMainForm.openProcessEpilogue(oldprocessname: string; oldprocess: dword; oldprocesshandle: dword; autoattachopen: boolean);
|
|
var
|
|
i, j: integer;
|
|
fname, expectedfilename: string;
|
|
path: string;
|
|
|
|
wasActive: boolean;
|
|
DoNotOpenAssociatedTable: boolean;
|
|
//set to true if the table had AA scripts enabled or the code list had nopped instruction
|
|
begin
|
|
if MainThreadID <> GetCurrentThreadId then
|
|
begin
|
|
currentexceptionerror:='openProcessEpilogue wasn''t called from the main GUI thread. Do not do this!';
|
|
tthread.Synchronize(nil, @ShowError);
|
|
exit;
|
|
end;
|
|
|
|
if getConnection<>nil then
|
|
updateNetworkOptions;
|
|
|
|
{$ifdef windows}
|
|
if aprilfools then decreaseCheatECoinCount;
|
|
{$endif}
|
|
|
|
DoNotOpenAssociatedTable:=false;
|
|
|
|
outputdebugstring('openProcessEpilogue called');
|
|
|
|
if (oldprocess<>processid) and SyncSymbols and symsync_ClearSymbolListWhenOpeningADifferentProcess then
|
|
symhandler.DeleteAllUserdefinedSymbols;
|
|
|
|
if SyncSymbols then
|
|
SyncSymbolsNow(true); //get the latest symbols
|
|
|
|
symhandler.reinitialize(true);
|
|
// symhandler.waitforsymbolsloaded;
|
|
|
|
reinterpretaddresses;
|
|
|
|
miNetwork.visible:=processhandler.isNetwork;
|
|
|
|
if oldprocess = 0 then //set disassembler and hexview of membrowser to what the main header says
|
|
memorybrowser.setcodeanddatabase;
|
|
|
|
outputdebugstring('After setcodeanddatabase');
|
|
|
|
if processid = $FFFFFFFF then
|
|
begin
|
|
if ProcessHandler.ProcessHandle<>QWORD(-2) then
|
|
processlabel.Caption := strPhysicalMemory;
|
|
|
|
cbPauseWhileScanning.visible:=false;
|
|
|
|
if cbsaferPhysicalMemory=nil then
|
|
begin
|
|
cbsaferPhysicalMemory:=tcheckbox.create(self);
|
|
cbsaferPhysicalMemory.Caption:=strSaferPhysicalMemory;
|
|
cbsaferPhysicalMemory.Checked:={$ifdef windows}dbk32functions.saferQueryPhysicalMemory{$else}false{$endif};
|
|
cbsaferPhysicalMemory.AnchorSame(akTop,cbPauseWhileScanning); // trick with AnchorSame
|
|
cbsaferPhysicalMemory.AnchorSame(akLeft,cbPauseWhileScanning);
|
|
cbsaferPhysicalMemory.AnchorSame(akRight,cbPauseWhileScanning);
|
|
cbsaferPhysicalMemory.AnchorSame(akBottom,cbPauseWhileScanning);
|
|
cbsaferPhysicalMemory.BorderSpacing.Assign(cbPauseWhileScanning.BorderSpacing); // clone spacing
|
|
cbsaferPhysicalMemory.OnChange:=@cbSaferPhysicalMemoryChange;
|
|
cbsaferPhysicalMemory.Parent:=cbPauseWhileScanning.Parent;
|
|
cbsaferPhysicalMemory.Name:='cbsaferPhysicalMemory';
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//restore cbPauseWhileScanning if it was replaced
|
|
if cbSaferPhysicalMemory<>nil then
|
|
begin
|
|
freeandnil(cbsaferPhysicalMemory);
|
|
cbPauseWhileScanning.Visible:=true;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
if (processhandle = 0) then
|
|
begin
|
|
outputdebugstring('processhandle is 0, so disabling gui');
|
|
|
|
if btnNewScan.Caption = strNewScan then
|
|
btnNewScan.click;
|
|
|
|
//disable everything
|
|
|
|
foundcount := 0;
|
|
if foundlist<>nil then
|
|
foundlist.Clear;
|
|
|
|
btnNewScan.Caption := strFirstScan;
|
|
|
|
setGbScanOptionsEnabled(False);
|
|
|
|
|
|
scanvalue.Enabled := False;
|
|
btnNewScan.Enabled := False;
|
|
btnNextScan.Enabled := False;
|
|
vartype.Enabled := False;
|
|
scantype.Enabled := False;
|
|
scantext.Enabled := False;
|
|
lblScanType.Enabled := False;
|
|
lblValueType.Enabled := False;
|
|
|
|
scanvalue.Visible := False;
|
|
scantext.Visible := False;
|
|
scanvalue.Text := '';
|
|
cbHexadecimal.Enabled := False;
|
|
cbCaseSensitive.Enabled := False;
|
|
cbNot.Visible:=false;
|
|
|
|
Updatescantype;
|
|
Scantype.ItemIndex := 0;
|
|
|
|
cbSpeedhack.Enabled := False;
|
|
cbUnrandomizer.Enabled := False;
|
|
|
|
if processid <> $FFFFFFFF then
|
|
begin
|
|
processlabel.Caption := strError;
|
|
MessageDlg(strErrorWhileOpeningProcess{$ifdef darwin}+strErrorwhileOpeningProcessMac{$endif}, mtError,[mbok],0);
|
|
exit;
|
|
end
|
|
else
|
|
begin
|
|
if processhandle<>qword(-2) then
|
|
processlabel.Caption := strPhysicalMemory;
|
|
end;
|
|
|
|
UpdateScanType;
|
|
|
|
|
|
//apply this for all tabs
|
|
if scantablist <> nil then
|
|
for i := 0 to scantablist.Count - 1 do
|
|
SaveCurrentState(PScanState(scantablist.TabData[i]), true);
|
|
|
|
end;
|
|
|
|
if (processID = oldProcess) then
|
|
exit;
|
|
|
|
outputdebugstring('oldprocessid != processid');
|
|
|
|
//a new process has been selected
|
|
cbspeedhack.Enabled := True;
|
|
cbunrandomizer.Enabled := True;
|
|
|
|
if not autoattachopen then
|
|
begin
|
|
if (addresslist.Count > 0) or (AdvancedOptions.count > 0) then
|
|
begin
|
|
if formsettings.cbAskToClearListOnOpen.checked and (messagedlg(strKeepList, mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
|
|
begin
|
|
UserDefinedTableName:='';
|
|
ClearList;
|
|
end
|
|
else
|
|
begin
|
|
//yes, so keep the list
|
|
//go through the list and chek for auto assemble entries, and check if one is enabled. If so, ask to disable (withotu actually disabling)
|
|
wasActive := False;
|
|
DoNotOpenAssociatedTable:=true; //user kept the list, do not load the associated table
|
|
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if (addresslist[i].VarType = vtAutoAssembler) and (addresslist[i].active) then
|
|
begin
|
|
wasActive := True;
|
|
break;
|
|
end;
|
|
|
|
if not wasActive then
|
|
begin
|
|
for i := 0 to AdvancedOptions.count - 1 do
|
|
if (AdvancedOptions.code[i]<>nil) and AdvancedOptions.code[i].changed then
|
|
begin
|
|
wasActive := True;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
if wasactive then
|
|
begin
|
|
if (messagedlg(rsThereAreOneOrMoreAutoAssemblerEntriesOrCodeChanges,
|
|
mtConfirmation, [mbYes, mbNo], 0) = mrYes) then
|
|
begin
|
|
addresslist.disableAllWithoutExecute;
|
|
|
|
for i := 0 to AdvancedOptions.count - 1 do
|
|
if (AdvancedOptions.code[i]<>nil) then AdvancedOptions.code[i].changed := False;
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (oldprocess<>0) and (processid<>oldprocess) then
|
|
begin
|
|
cbSpeedhack.Checked:=false;
|
|
addresslist.disableAllWithoutExecute;
|
|
for i := 0 to AdvancedOptions.count - 1 do
|
|
if AdvancedOptions.code[i]<>nil then AdvancedOptions.code[i].changed := False;
|
|
end;
|
|
end;
|
|
|
|
enablegui(btnNextScan.Enabled);
|
|
|
|
Fname := copy(processlabel.Caption, pos('-', processlabel.Caption) +
|
|
1, length(processLabel.Caption));
|
|
|
|
if (length(fname)>3) and (FName[length(FName) - 3] = '.') then //it's a filename
|
|
expectedFilename := copy(FName, 1, length(FName) - 4) + '.ct'
|
|
else //it's a normal title;
|
|
expectedFilename := FName + '.ct';
|
|
|
|
|
|
|
|
if not (autoattachopen or DoNotOpenAssociatedTable) then
|
|
begin
|
|
path:='';
|
|
|
|
if fileexists(TablesDir + pathdelim + expectedfilename) then
|
|
path:=TablesDir + pathdelim + expectedfilename
|
|
else
|
|
if fileexists(expectedfilename) then
|
|
path:=expectedfilename
|
|
else if fileexists(cheatenginedir + expectedfilename) then
|
|
path:=cheatenginedir + expectedfilename
|
|
else if fileexists( IncludeTrailingPathDelimiter(opendialog1.InitialDir)+expectedfilename) then
|
|
path:=IncludeTrailingPathDelimiter(opendialog1.InitialDir)+expectedfilename
|
|
else if fileexists( IncludeTrailingPathDelimiter(extractfilepath(opendialog1.FileName))+expectedfilename) then
|
|
path:=IncludeTrailingPathDelimiter(extractfilepath(opendialog1.FileName))+expectedfilename;
|
|
|
|
if path<>'' then
|
|
begin
|
|
if messagedlg(Format(rsLoadTheAssociatedTable, [expectedFilename]),
|
|
mtConfirmation, [mbYes, mbNo], 0) = mrYes then
|
|
begin
|
|
autoopen := True;
|
|
if fileexists(path) then
|
|
opendialog1.FileName := path;
|
|
|
|
LoadButton.Click;
|
|
end;
|
|
end;
|
|
end;
|
|
UpdateScanType;
|
|
|
|
if scantablist <> nil then
|
|
for i := 0 to scantablist.Count - 1 do
|
|
SaveCurrentState(PScanState(scantablist.TabData[i]),true);
|
|
|
|
|
|
{$ifdef darwin}
|
|
if formsettings.cbUseRosettaDebugserver.checked and formsettings.cbAttachDebuggerToRosettaOnProcessOpen.checked and isProcessTranslated(processid) then
|
|
begin
|
|
if (formsettings.cbaskToAttachToRosetta.Checked=false) or (MessageDlg('The selected process is running under Rosetta. To be able to edit programcode the debugger needs to be attached. Attach the debugger now?', mtConfirmation, [mbyes,mbno],0)=mryes) then
|
|
startdebuggerifneeded(false);
|
|
end;
|
|
{$endif}
|
|
|
|
|
|
outputdebugstring('openProcessEpilogue exit');
|
|
|
|
// miDotNET.visible:=symhandler.hasDotNetAccess; //too slow to use. You're free to uncomment it but don't bitch about having to wait 2 and a half hour
|
|
|
|
if assigned(fOnProcessOpened) then
|
|
fOnProcessOpened(processid, processhandle, processlabel.Caption);
|
|
end;
|
|
|
|
procedure TMainForm.ShowProcessListButtonClick(Sender: TObject);
|
|
var
|
|
oldprocess: Dword;
|
|
resu: integer;
|
|
oldprocesshandle: thandle;
|
|
oldprocessname: string;
|
|
begin
|
|
if not openprocessPrologue then
|
|
exit;
|
|
|
|
oldprocessname := copy(mainform.ProcessLabel.Caption, pos(
|
|
'-', mainform.ProcessLabel.Caption) + 1, length(mainform.ProcessLabel.Caption));
|
|
|
|
oldprocess := processID;
|
|
oldprocesshandle := processhandle;
|
|
|
|
if Processwindow = nil then
|
|
ProcessWindow := TProcessWindow.Create(application);
|
|
|
|
resu := ProcessWindow.ShowModal;
|
|
|
|
if resu = mrCancel then
|
|
exit;
|
|
|
|
openProcessEpilogue(oldprocessname, oldprocess, oldprocesshandle);
|
|
end;
|
|
|
|
|
|
procedure TMainForm.rbFsmAlignedChange(Sender: TObject);
|
|
begin
|
|
if rbfsmLastDigts.Checked then
|
|
alignsizechangedbyuser := False;
|
|
|
|
VarType.OnChange(vartype);
|
|
end;
|
|
|
|
procedure TMainForm.rtChange(Sender: TObject);
|
|
begin
|
|
cereg.writeInteger('Last Rounding Type',TComponent(sender).tag);
|
|
end;
|
|
|
|
|
|
procedure TMainForm.Save1Click(Sender: TObject);
|
|
var
|
|
protect: boolean;
|
|
begin
|
|
protect := False;
|
|
if (savedialog1.FileName = '') then
|
|
actSave.Execute
|
|
else
|
|
savetable(savedialog1.FileName);
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.Description1Click(Sender: TObject);
|
|
begin
|
|
addresslist.doDescriptionChange;
|
|
end;
|
|
|
|
procedure TMainForm.edtAlignmentKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
if rbFsmAligned.Checked then
|
|
alignsizechangedbyuser := True;
|
|
end;
|
|
|
|
procedure TMainForm.FormDropFiles(Sender: TObject; const FileNames: array of string);
|
|
var
|
|
merge: boolean;
|
|
app: word;
|
|
ext: string;
|
|
begin
|
|
merge:=false;
|
|
if length(filenames) > 0 then
|
|
begin
|
|
ext:=ExtractFileExt(filenames[0]);
|
|
if lowercase(ext)<>'.ct' then exit;
|
|
|
|
if not (fsVisible in formstate) then exit;
|
|
|
|
|
|
if CheckIfSaved then
|
|
begin
|
|
if ((addresslist.Count > 0) or (advancedoptions.count > 0) or (DissectedStructs.count>0) )then
|
|
begin
|
|
app := messagedlg(rsDoYouWishToMergeTheCurrentTableWithThisTable, mtConfirmation, mbYesNoCancel, 0);
|
|
case app of
|
|
mrCancel: exit;
|
|
mrYes: merge := True;
|
|
mrNo: merge := False;
|
|
end;
|
|
end;
|
|
|
|
LoadTable(filenames[0], merge);
|
|
reinterpretaddresses;
|
|
|
|
if not merge then
|
|
begin
|
|
Savedialog1.FileName := filenames[0];
|
|
Opendialog1.FileName := filenames[0];
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Foundlist3ColumnClick(Sender: TObject; Column: TListColumn);
|
|
begin
|
|
if column.index>=1 then
|
|
setActivePreviousResultColumn(column.index);
|
|
end;
|
|
|
|
procedure TMainForm.Foundlist3CustomDrawItem(Sender: TCustomListView;
|
|
Item: TListItem; State: TCustomDrawState; var DefaultDraw: boolean);
|
|
var
|
|
s: string;
|
|
begin
|
|
if foundlist <> nil then
|
|
begin
|
|
if foundlist.inmodule(item.index) then
|
|
foundlist3.Canvas.Font.Color := foundlistColors.StaticColor
|
|
else
|
|
foundlist3.Canvas.Font.Color := foundlistColors.DynamicColor;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Foundlist3CustomDrawSubItem(Sender: TCustomListView;
|
|
Item: TListItem; SubItem: Integer; State: TCustomDrawState;
|
|
var DefaultDraw: Boolean);
|
|
var r: trect;
|
|
ts: TTextStyle;
|
|
drawn:boolean;
|
|
|
|
fc: TColor;
|
|
|
|
_changed: boolean;
|
|
|
|
subitemCompareIndex: integer;
|
|
|
|
sic: integer;
|
|
begin
|
|
//apparently the SubItem field includes the main item as well at index 0 (lazarus bug? Will be fixed someday? If so, expect crashes here)
|
|
if subitem=0 then exit;
|
|
subitem:=subitem-1;
|
|
|
|
drawn:=false;
|
|
if miShowPreviousValue.checked and (PreviousResultList.count>0) then
|
|
begin
|
|
sic:=item.SubItems.count;
|
|
subitemCompareIndex:=ActivePreviousResultColumn-1;
|
|
|
|
if (subitemCompareIndex>=sic) or (subitem>=sic) or (sic=0) then
|
|
exit;
|
|
|
|
if subitem=0 then //current value
|
|
begin
|
|
//compare it against the currently selected compareto selection
|
|
_changed:=(item.subItems[subitemCompareIndex]<>rsPleaseWait) and (item.subitems[0]<>item.subitems[subitemCompareIndex]);
|
|
end
|
|
else
|
|
begin
|
|
//compare against the current value
|
|
_changed:=(item.subItems[subitem]<>rsPleaseWait) and (item.subitems[0]<>item.subitems[subitem]);
|
|
end;
|
|
|
|
if _changed then
|
|
begin
|
|
sender.Canvas.Font.color:=foundlistColors.changedValueColor;
|
|
sender.canvas.font.Style:=sender.canvas.font.Style+[fsBold];
|
|
sender.canvas.Refresh;
|
|
|
|
drawn:=true;
|
|
|
|
{$ifdef darwin}
|
|
//no color or customdrawn support
|
|
//item.subitems[0]:='* '+item.subitems[0]+' *';
|
|
{$endif}
|
|
end;
|
|
end;
|
|
if(not drawn)then
|
|
begin
|
|
sender.Canvas.Font.color:=foundlistColors.NormalValueColor;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Address1Click(Sender: TObject);
|
|
begin
|
|
addresslist.doAddressChange;
|
|
end;
|
|
|
|
procedure TMainForm.cbCompareToSavedScanChange(Sender: TObject);
|
|
var
|
|
s: tstringlist;
|
|
l: TfrmSelectionList;
|
|
i,selindex: integer;
|
|
|
|
str: string;
|
|
begin
|
|
if cbCompareToSavedScan.checked then
|
|
begin
|
|
s := TStringList.Create;
|
|
try
|
|
selindex:=-1;
|
|
if (memscan.getsavedresults(s) > 1) then
|
|
begin
|
|
//popup a window where the user can select the scanresults
|
|
//currentlySelectedSavedResultname
|
|
l := TfrmSelectionList.Create(self, s);
|
|
l.Caption := rsSavedScanResults;
|
|
l.label1.Caption := rsSelectTheSavedScanResultFromTheListBelow;
|
|
l.ItemIndex := 0;
|
|
|
|
selindex:=l.ItemIndex;
|
|
|
|
if (l.showmodal = mrOk) and (l.ItemIndex <> -1) then
|
|
currentlySelectedSavedResultname := l.selected
|
|
else
|
|
exit;
|
|
end
|
|
else
|
|
currentlySelectedSavedResultname := rsFirst;
|
|
|
|
//compareToSavedScan := True;
|
|
//lblcompareToSavedScan.Visible := s.Count>1;
|
|
//lblcompareToSavedScan.Caption := '('+currentlySelectedSavedResultname+')';
|
|
finally
|
|
freeandnil(s);
|
|
end;
|
|
|
|
for i:=0 to PreviousResultList.count-1 do
|
|
begin
|
|
str:=uppercase(TSavedScanHandler(PreviousResultList[i]).name);
|
|
if str=uppercase(currentlySelectedSavedResultname) then
|
|
begin
|
|
ActivePreviousResultColumn:=i+2;
|
|
foundlist3.Refresh;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
//language issues...
|
|
if selindex<>-1 then
|
|
ActivePreviousResultColumn:=2+selindex;
|
|
end
|
|
else
|
|
begin
|
|
//unchecked, so compare against the last scan results
|
|
compareToSavedScan := False;
|
|
lblcompareToSavedScan.Visible := False;
|
|
|
|
ActivePreviousResultColumn:=2; //the TMP one
|
|
foundlist3.Refresh;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.cbLuaFormulaChange(Sender: TObject);
|
|
begin
|
|
cbNewLuaState.visible:=cbLuaFormula.Visible and cbLuaFormula.Checked;
|
|
end;
|
|
|
|
procedure TMainForm.cbCodePageChange(Sender: TObject);
|
|
begin
|
|
if cbCodePage.checked then cbunicode.Checked:=false;
|
|
end;
|
|
|
|
procedure TMainForm.cbRepeatUntilStoppedChange(Sender: TObject);
|
|
begin
|
|
if (cbRepeatUntilStopped.checked=false) and (repeatscantimer<>nil) then
|
|
freeandnil(repeatscantimer);
|
|
end;
|
|
|
|
procedure TMainForm.cbUnicodeChange(Sender: TObject);
|
|
begin
|
|
if cbunicode.checked then cbCodePage.checked:=false;
|
|
end;
|
|
|
|
procedure TMainForm.Copyselectedaddresses1Click(Sender: TObject);
|
|
var
|
|
i: ptruint;
|
|
address: ptruint;
|
|
temp: string;
|
|
begin
|
|
temp:='';
|
|
|
|
if foundlist3.SelCount = 1 then
|
|
begin
|
|
address := foundlist.GetAddress(foundlist3.itemIndex);
|
|
clipboard.AsText := symhandler.getNameFromAddress(address)
|
|
end
|
|
else
|
|
if foundlist3.SelCount > 1 then
|
|
begin
|
|
for i:=0 to foundlist3.Items.count-1 do
|
|
begin
|
|
if foundlist3.items[i].Selected then
|
|
begin
|
|
address := foundlist.GetAddress(i);
|
|
temp := temp + symhandler.getNameFromAddress(address) + sLineBreak;
|
|
end
|
|
end;
|
|
clipboard.AsText := temp;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.EnableLCLClick(Sender: TObject);
|
|
var llf: TLazLoggerFile;
|
|
begin
|
|
llf:=GetDebugLogger;
|
|
if llf<>nil then
|
|
begin
|
|
llf.CloseLogFileBetweenWrites:=true; // change LazLogger to use non-buffered output
|
|
if miEnableLCLDebug.checked then
|
|
begin
|
|
deletefile('cedebug.txt');
|
|
|
|
llf.LogName:='cedebug.txt';
|
|
llf.Init;
|
|
|
|
|
|
DebugLn('First log message: '+DateToStr(now));
|
|
end
|
|
else
|
|
llf.Finish;
|
|
end;
|
|
|
|
TraceExceptions:=miEnableLCLDebug.checked;
|
|
|
|
miTriggerAccessViolation.visible:=TraceExceptions;
|
|
miTestAccessViolationThread.visible:=TraceExceptions;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.actOpenDissectStructureExecute(Sender: TObject);
|
|
var address: ptruint;
|
|
i: integer;
|
|
f: TfrmStructures2;
|
|
found: boolean;
|
|
c: TStructColumn;
|
|
begin
|
|
|
|
if frmStructures2.count>0 then
|
|
begin
|
|
if addresslist.Focused and (addresslist.selectedRecord<>nil) and
|
|
(not addresslist.selectedRecord.isGroupHeader or addresslist.selectedRecord.isAddressGroupHeader) and
|
|
(addresslist.selectedRecord.VarType<>vtAutoAssembler)
|
|
then
|
|
begin
|
|
//add this address if it's not yet in the list
|
|
found:=false;
|
|
|
|
address:=addresslist.selectedRecord.GetRealAddress;
|
|
f:=TfrmStructures2(frmStructures2[0]);
|
|
for i:=0 to f.columnCount-1 do
|
|
if f.columns[i].Address=address then
|
|
begin
|
|
found:=true;
|
|
f.columns[i].focus;
|
|
break;
|
|
end;
|
|
|
|
if not found then
|
|
begin
|
|
c:=f.addColumn;
|
|
c.Address:=address;
|
|
c.focus;
|
|
end;
|
|
end;
|
|
|
|
TfrmStructures2(frmStructures2[0]).show;
|
|
end
|
|
else
|
|
begin
|
|
//create it
|
|
with tfrmstructures2.create(application) do
|
|
begin
|
|
//fill in the selected memoryrecord if there is one, else use the memoryview hexview address
|
|
initialaddress:=MemoryBrowser.hexview.address;
|
|
|
|
if (addresslist.selectedRecord<>nil) and
|
|
(not addresslist.selectedRecord.isGroupHeader or addresslist.selectedRecord.isAddressGroupHeader) and
|
|
(addresslist.selectedRecord.VarType<>vtAutoAssembler)
|
|
then
|
|
initialaddress:=addresslist.selectedRecord.GetRealAddress;
|
|
|
|
show;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.actOpenLuaEngineExecute(Sender: TObject);
|
|
begin
|
|
MemoryBrowser.miLuaEngine.Click;
|
|
end;
|
|
|
|
procedure TMainForm.cbFastScanChange(Sender: TObject);
|
|
begin
|
|
edtAlignment.Enabled := cbFastScan.Checked and cbfastscan.Enabled;
|
|
rbFsmAligned.Enabled := edtAlignment.Enabled;
|
|
rbfsmLastDigts.Enabled := edtAlignment.Enabled;
|
|
|
|
alignsizechangedbyuser := False;
|
|
VarType.OnChange(vartype);
|
|
end;
|
|
|
|
|
|
procedure TMainForm.CreateGroupClick(Sender: TObject);
|
|
var
|
|
groupname: string;
|
|
i: integer;
|
|
Count: integer;
|
|
withAddress: boolean;
|
|
begin
|
|
//in rare cases you can use the treeview data data if you request so
|
|
Count := 0;
|
|
for i := 0 to addresslist.Items.Count - 1 do
|
|
if TMemoryRecord(addresslist.Items[i].Data).isGroupHeader then
|
|
Inc(Count);
|
|
|
|
groupname := Format(rsGroup, [IntToStr(Count + 1)]);
|
|
|
|
if InputQuery(rsGroups, rsWhatDoYouWantTheGroupnameToBe, groupname) then
|
|
begin
|
|
withAddress:=(messagedlg(rsDoYouWantTheGroupWithAddress, mtConfirmation, [mbYes, mbNo], 0)=mrYes);
|
|
addresslist.CreateGroup(groupname, withAddress);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.gbScanOptionsChangeBounds(Sender: TObject);
|
|
begin
|
|
spawnBoundsUpdater;
|
|
end;
|
|
|
|
procedure TMainForm.Label3Click(Sender: TObject);
|
|
begin
|
|
|
|
end;
|
|
|
|
|
|
procedure triggerAV(AData : Pointer);
|
|
var p: pbyte;
|
|
begin
|
|
p:=pbyte($ce);
|
|
p^:=p^+$ce;
|
|
|
|
beep;
|
|
|
|
end;
|
|
|
|
type TTestThread=class(tthread)
|
|
procedure Execute; override;
|
|
end;
|
|
|
|
|
|
procedure TTestThread.Execute;
|
|
begin
|
|
SetThreadDebugName(ThreadID,'Crashy thread');
|
|
triggerav(nil);
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miTestAccessViolationThreadClick(Sender: TObject);
|
|
var m: Tmethod;
|
|
|
|
t: TTestthread;
|
|
begin
|
|
t:=ttestthread.Create(true);
|
|
|
|
|
|
//t.FreeOnTerminate:=true;
|
|
t.Start;
|
|
{
|
|
while t.Finished=false do
|
|
sleep(100);
|
|
|
|
if t.FatalException=nil then
|
|
showmessage('all ok')
|
|
else
|
|
showmessage('error'); }
|
|
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miTriggerAccessViolationClick(Sender: TObject);
|
|
begin
|
|
triggerAV(nil);
|
|
showmessage('Weeee! Fuck You!');
|
|
end;
|
|
|
|
|
|
procedure TMainForm.MenuItem16Click(Sender: TObject);
|
|
{$ifdef darwin}
|
|
var p: TProcessUTF8;
|
|
path: string;
|
|
{$endif}
|
|
begin
|
|
{$ifdef darwin}
|
|
p:=TProcessUTF8.Create(self);
|
|
path:=ExtractFilePath(application.ExeName)+'tutorial-aarch64.app/Contents/MacOS/tutorial-aarch64';
|
|
//OutputDebugString('path='+path);
|
|
p.Executable:=(path);
|
|
p.Execute;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miClearWorkingSetClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if assigned(EmptyWorkingSet) then
|
|
begin
|
|
if messagedlg(rsClearingMeansSlowness, mtInformation, [mbyes, mbno], 0)=
|
|
mryes then
|
|
EmptyWorkingSet(processhandle);
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miTutorial64Click(Sender: TObject);
|
|
{$ifdef darwin}
|
|
var p: TProcessUTF8;
|
|
path: string;
|
|
{$endif}
|
|
begin
|
|
{$ifdef darwin}
|
|
p:=TProcessUTF8.Create(self);
|
|
path:=ExtractFilePath(application.ExeName)+'tutorial-x86_64.app/Contents/MacOS/tutorial-x86_64';
|
|
|
|
OutputDebugString('path='+path);
|
|
p.Executable:=(path);
|
|
p.Execute;
|
|
{$else}
|
|
shellexecute(0, 'open', pchar(cheatenginedir+{$ifdef altname}'rtmtutorial-x86_64.exe'{$else}'Tutorial-x86_64.exe'{$endif}), nil, nil, sw_show);
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.MenuItem15Click(Sender: TObject);
|
|
var nexttut: string;
|
|
filename: string;
|
|
begin
|
|
filename:='gtutorial-'+{$ifdef cpu32}'i386'{$else}'x86_64'{$endif}+'.exe';
|
|
nexttut:=ExtractFilePath(application.ExeName)+filename;
|
|
|
|
if fileexists(nexttut) then
|
|
begin
|
|
//launch the graphical tutorial
|
|
ShellExecute(0, PChar('open'), PChar(nexttut),PChar(''), PChar(extractfilepath(nexttut)), SW_SHOW);
|
|
exit;
|
|
end;
|
|
|
|
|
|
nexttut:=ExtractFileDir(application.ExeName);
|
|
|
|
if ExtractFileName(nexttut)='bin' then
|
|
begin
|
|
nexttut:=ExtractFilePath(nexttut)+'tutorial\graphical\'+filename;
|
|
|
|
if fileexists(nexttut) then
|
|
begin
|
|
//launch the graphical tutorial
|
|
ShellExecute(0, PChar('open'), PChar(nexttut),PChar(''), PChar(extractfilepath(nexttut)), SW_SHOW);
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.miDeleteSavedScanResultsClick(Sender: TObject);
|
|
var
|
|
s: tstringlist;
|
|
l: TfrmSelectionList;
|
|
i: integer;
|
|
|
|
tobedeleted: string;
|
|
begin
|
|
tobedeleted:='';
|
|
s:=tstringlist.create;
|
|
i:=memscan.getsavedresults(s);
|
|
if i=1 then exit;
|
|
|
|
|
|
s.Delete(0);
|
|
l := TfrmSelectionList.Create(self, s);
|
|
l.Caption := rsSavedScanResults;
|
|
l.label1.Caption := rsSelectTheSavedScanResultFromTheListBelow;
|
|
l.ItemIndex := 0;
|
|
|
|
if (l.showmodal = mrOk) and (l.ItemIndex <> -1) then
|
|
tobedeleted := l.selected;
|
|
|
|
s.free;
|
|
|
|
if compareToSavedScan and (currentlySelectedSavedResultname=tobedeleted) then
|
|
cbCompareToSavedScan.checked:=false;
|
|
|
|
if tobedeleted<>'' then
|
|
memscan.deleteSavedResult(tobedeleted);
|
|
|
|
reloadPreviousResults;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miFoundListPreferencesClick(Sender: TObject);
|
|
var
|
|
f: TfrmFoundlistPreferences;
|
|
reg: TRegistry;
|
|
begin
|
|
f:=TfrmFoundlistPreferences.Create(self);
|
|
|
|
f.Font.assign(foundlist3.font);
|
|
f.NormalValueColor:=foundlistColors.NormalValueColor;
|
|
f.ChangedValueColor:=foundlistColors.ChangedValueColor;
|
|
f.BackgroundColor:=foundlist3.color;
|
|
f.StaticColor:=foundlistColors.StaticColor;
|
|
f.DynamicColor:=foundlistColors.DynamicColor;
|
|
f.ShowStaticAsStatic:=showStaticAsStatic;
|
|
f.CompareToHeaderColor:=foundlistColors.compareToHeadercolor;
|
|
f.UseThisFontSize:=AddressListOverrideFontSize;
|
|
if f.showmodal=mrok then
|
|
begin
|
|
foundlist3.font.Assign(f.font);
|
|
foundlist3.Color:=f.BackgroundColor;
|
|
|
|
foundlistColors.NormalValueColor:=f.NormalValueColor;
|
|
foundlistColors.ChangedValueColor:=f.ChangedValueColor;
|
|
foundlistColors.StaticColor:=f.StaticColor;
|
|
foundlistColors.DynamicColor:=f.DynamicColor;
|
|
foundlistcolors.compareToHeadercolor:=f.CompareToHeaderColor;;
|
|
showStaticAsStatic:=f.ShowStaticAsStatic;
|
|
AddressListOverrideFontSize:=f.UseThisFontSize;
|
|
|
|
|
|
|
|
reg := Tregistry.Create;
|
|
try
|
|
Reg.RootKey := HKEY_CURRENT_USER;
|
|
|
|
if Reg.OpenKey('\Software\'+strCheatEngine+'\FoundList'+darkmodestring, True) then
|
|
begin
|
|
reg.WriteInteger('FoundList.NormalValueColor', foundlistcolors.NormalValueColor);
|
|
reg.WriteInteger('FoundList.ChangedValueColor', foundlistcolors.ChangedValueColor);
|
|
reg.WriteInteger('FoundList.StaticColor', foundlistcolors.StaticColor);
|
|
reg.WriteInteger('FoundList.DynamicColor', foundlistcolors.DynamicColor);
|
|
reg.WriteInteger('FoundList.BackgroundColor',foundlist3.Color);
|
|
reg.WriteInteger('FoundList.CompareToHeaderColor', foundlistcolors.CompareToHeaderColor);
|
|
reg.WriteBool('FoundList.ShowStaticAsStatic',ShowStaticAsStatic);
|
|
reg.WriteBool('FoundList.OverrideFontSize',AddressListOverrideFontSize);
|
|
|
|
SaveFontToRegistry(foundlist3.font, reg);
|
|
end;
|
|
finally
|
|
reg.free;
|
|
end;
|
|
end;
|
|
|
|
f.free;
|
|
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miAutoAssembleErrorMessageClick(Sender: TObject);
|
|
begin
|
|
clipboard.AsText:=miAutoAssembleErrorMessage.Caption;
|
|
addresslist.doValueChange;
|
|
end;
|
|
|
|
procedure TMainForm.miHelpClick(Sender: TObject);
|
|
begin
|
|
miEnableLCLDebug.visible:=miEnableLCLDebug.checked or (ssCtrl in GetKeyShiftState);
|
|
end;
|
|
|
|
procedure TMainForm.miLuaDocumentationClick(Sender: TObject);
|
|
begin
|
|
{$ifdef darwin}
|
|
OpenDocument(pchar(ExtractFilePath(application.ExeName)+'../Lua/celua.txt'));
|
|
{$else}
|
|
ShellExecute(0,'open',pchar(ExtractFilePath(application.ExeName)+'celua.txt'),nil,nil,SW_SHOW);
|
|
{$endif}
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miForgotScanClick(Sender: TObject);
|
|
begin
|
|
if (foundlist.count=0) or (memscan.lastScanWasRegionScan) then exit;
|
|
|
|
cleanupPreviousResults;
|
|
|
|
foundlist.Deinitialize; //unlock file handles
|
|
|
|
if cbPauseWhileScanning.Checked then
|
|
begin
|
|
advancedoptions.Pausebutton.down := True;
|
|
advancedoptions.Pausebutton.Click;
|
|
end;
|
|
|
|
ProgressBar.min := 0;
|
|
ProgressBar.max := 1000;
|
|
ProgressBar.position := 0;
|
|
|
|
lastscantype := scantype.ItemIndex;
|
|
memscan.nextscan(soForgot, rtRounded,'','', false, false,false,false,false,false,'');
|
|
DisableGui;
|
|
SpawnCancelButton;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miGetDotNetObjectListClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if frmDotNetObjectList=nil then
|
|
frmDotNetObjectList:=TfrmDotNetObjectList.create(self);
|
|
|
|
frmDotNetObjectList.show;
|
|
frmDotNetObjectList.loadlist;
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.miSignTableClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if Opendialog1.Execute then
|
|
signTablefile(opendialog1.filename);
|
|
{$endif}
|
|
end;
|
|
|
|
{$ifdef windows}
|
|
var t: TRemoteMemoryManager;
|
|
{$endif}
|
|
|
|
procedure TMainForm.miScanDirtyOnlyClick(Sender: TObject);
|
|
begin
|
|
scan_dirtyonly:=miScanDirtyOnly.checked;
|
|
end;
|
|
|
|
procedure TMainForm.miCompressionClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if frmNetworkDataCompression=nil then
|
|
frmNetworkDataCompression:=tfrmNetworkDataCompression.create(self);
|
|
|
|
frmNetworkDataCompression.show;
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miManualExpandCollapseClick(Sender: TObject);
|
|
begin
|
|
miManualExpandCollapse.Checked := not miManualExpandCollapse.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miManualExpandCollapse.Checked then
|
|
addresslist.selectedRecord.options :=
|
|
addresslist.selectedRecord.options + [moManualExpandCollapse]
|
|
else
|
|
addresslist.selectedRecord.options :=
|
|
addresslist.selectedRecord.options - [moManualExpandCollapse];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miSaveClick(Sender: TObject);
|
|
begin
|
|
if fileexists(savedialog1.FileName) then
|
|
begin
|
|
savetable(savedialog1.FileName, false);
|
|
|
|
recentFilesUpdate(savedialog1.filename);
|
|
end
|
|
else
|
|
actSave.Execute;
|
|
end;
|
|
|
|
procedure TMainForm.mi3dClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
miHookD3D.checked:=(D3DHook<>nil) and (D3DHook.processid=processid);
|
|
|
|
miLockMouseInGame.enabled:=miHookD3D.checked;
|
|
miSetCrosshair.enabled:=miHookD3D.checked;
|
|
|
|
if miHookD3D.checked=false then
|
|
miLockMouseInGame.checked:=false;
|
|
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miChangeDisplayTypeClick(Sender: TObject);
|
|
begin
|
|
//set the display type to override the default with
|
|
foundlistDisplayOverride:=TMenuItem(sender).Tag;
|
|
foundlist3.Refresh;
|
|
end;
|
|
|
|
procedure TMainForm.miOpenFileClick(Sender: TObject);
|
|
var
|
|
oldprocess: Dword;
|
|
resu: integer;
|
|
oldprocesshandle: thandle;
|
|
oldprocessname: string;
|
|
begin
|
|
if not openprocessPrologue then
|
|
exit;
|
|
|
|
oldprocessname := copy(mainform.ProcessLabel.Caption, pos(
|
|
'-', mainform.ProcessLabel.Caption) + 1, length(mainform.ProcessLabel.Caption));
|
|
|
|
oldprocess := processID;
|
|
oldprocesshandle := processhandle;
|
|
|
|
if Processwindow = nil then
|
|
ProcessWindow := TProcessWindow.Create(application);
|
|
|
|
ProcessWindow.miOpenFile.click;
|
|
|
|
if ProcessWindow.modalresult=mrOK then
|
|
openProcessEpilogue(oldprocessname, oldprocess, oldprocesshandle);
|
|
end;
|
|
|
|
procedure TMainForm.miScanPagedOnlyClick(Sender: TObject);
|
|
begin
|
|
scan_pagedonly:=miScanPagedOnly.checked;
|
|
end;
|
|
|
|
procedure TMainForm.miSetDropdownOptionsClick(Sender: TObject);
|
|
var f: TFrmMemoryRecordDropdownSettings;
|
|
memrec: TMemoryRecord;
|
|
begin
|
|
if addresslist.selectedrecord<>nil then
|
|
begin
|
|
memrec:=addresslist.SelectedRecord;
|
|
//random text here
|
|
f:=TFrmMemoryRecordDropdownSettings.create(memrec, addresslist);
|
|
f.ShowModal;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miShowAsSignedClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
newstate: boolean;
|
|
begin
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
newstate := not addresslist.selectedRecord.showAsSigned;
|
|
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if addresslist[i].isSelected then
|
|
addresslist[i].showAsSigned := newstate;
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.MenuItem1Click(Sender: TObject);
|
|
begin
|
|
addresslist.SelectAll;
|
|
end;
|
|
|
|
procedure TMainForm.miShowLuaScriptClick(Sender: TObject);
|
|
begin
|
|
frmLuaTableScript.Show;
|
|
end;
|
|
|
|
procedure TMainForm.miAddAddressClick(Sender: TObject);
|
|
begin
|
|
SpeedButton3.Click;
|
|
end;
|
|
|
|
procedure TMainForm.miAllowCollapseClick(Sender: TObject);
|
|
begin
|
|
miAllowCollapse.Checked := not miAllowCollapse.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miAllowCollapse.Checked then
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options + [moAllowManualCollapseAndExpand]
|
|
else
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options - [moAllowManualCollapseAndExpand];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.updated3dgui;
|
|
begin
|
|
{$ifdef windows}
|
|
miSetCrosshair.Enabled := d3dhook<>nil;
|
|
miWireframe.Enabled := d3dhook<>nil;
|
|
miZbuffer.Enabled := d3dhook<>nil;
|
|
miLockMouseInGame.enabled := d3dhook<>nil;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miHookD3DClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if MessageDlg('Are you sure you wish to hook Direct3D?', mtConfirmation, [mbyes,mbno],0)=mryes then
|
|
begin
|
|
safed3dhook;
|
|
updated3dgui;
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miSnapshothandlerClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if frmSnapshotHandler=nil then
|
|
begin
|
|
frmSnapshotHandler:=tfrmSnapshotHandler.Create(application);
|
|
frmSnapshotHandler.show;
|
|
if D3DHook<>nil then
|
|
frmSnapshotHandler.miConfig.click; //configure it if needed
|
|
end
|
|
else
|
|
frmSnapshotHandler.show;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miLockMouseInGameClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
safed3dhook;
|
|
updated3dgui;
|
|
|
|
if d3dhook<>nil then
|
|
d3dhook.setMouseClip(miLockMouseInGame.checked);
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miPresetAllClick(Sender: TObject);
|
|
begin
|
|
cbWritable.State := cbGrayed;
|
|
cbCopyOnWrite.state := cbGrayed;
|
|
cbExecutable.state := cbGrayed;
|
|
{$ifdef darwin}
|
|
cbDirty.state := cbGrayed;
|
|
{$endif}
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miAddFileClick(Sender: TObject);
|
|
var
|
|
f: TOpendialog;
|
|
|
|
lf: TLuafile;
|
|
s: TMemorystream;
|
|
i: integer;
|
|
begin
|
|
f := TOpendialog.Create(self);
|
|
try
|
|
f.Options:=f.options+[ofAllowMultiSelect, ofFileMustExist];
|
|
if f.Execute then
|
|
begin
|
|
s := TMemorystream.Create;
|
|
|
|
for i:=0 to f.Files.Count-1 do
|
|
begin
|
|
s.clear;
|
|
s.LoadFromFile(f.Files[i]);
|
|
lf := TLuaFile.Create(extractfilename(f.files[i]), s);
|
|
LuaFiles.add(lf);
|
|
end;
|
|
freeandnil(s);
|
|
end;
|
|
|
|
finally
|
|
if f<>nil then
|
|
freeandnil(f);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.MenuItem9Click(Sender: TObject);
|
|
|
|
begin
|
|
{$ifdef windows}
|
|
if frmTrainerGenerator = nil then
|
|
frmTrainerGenerator := tfrmTrainerGenerator.Create(self);
|
|
|
|
if frmTrainerGenerator.canceled then
|
|
begin
|
|
frmTrainerGenerator.Close;
|
|
exit;
|
|
end;
|
|
|
|
frmTrainerGenerator.Show;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miPresetWritableClick(Sender: TObject);
|
|
begin
|
|
cbWritable.State := cbchecked;
|
|
cbCopyOnWrite.state := cbGrayed;
|
|
cbExecutable.state := cbGrayed;
|
|
{$ifdef darwin}
|
|
cbDirty.state := cbGrayed;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miResyncFormsWithLuaClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
for i := 0 to LuaForms.Count - 1 do
|
|
TCEForm(LuaForms[i]).ResyncWithLua;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.DeleteFormClick(Sender: TObject);
|
|
var
|
|
f: tceform;
|
|
begin
|
|
if messagedlg(rsAreYouSureYouWantToDeleteThisForm, mtConfirmation,
|
|
[mbYes, mbNo], 0) = mrYes then
|
|
begin
|
|
if LuaForms.Count = 1 then //close the designerform when it's the last object
|
|
if FormDesigner <> nil then
|
|
FormDesigner.Close;
|
|
|
|
|
|
f := TCEForm(LuaForms[TMenuItem(Sender).Tag]);
|
|
f.Free;
|
|
|
|
LuaForms.Delete(TMenuItem(Sender).Tag);
|
|
|
|
UpdateMenu;
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.EditFormClick(Sender: TObject);
|
|
var
|
|
f: tceform;
|
|
begin
|
|
f := TCEForm(LuaForms[TMenuItem(Sender).Tag]);
|
|
|
|
|
|
if formdesigner = nil then
|
|
createFormdesigner;
|
|
|
|
formdesigner.designForm(f); //opendialog my .ss
|
|
|
|
formdesigner.Show;
|
|
|
|
f.Show;
|
|
end;
|
|
|
|
procedure TMainForm.RestoreAndShowFormClick(Sender: TObject);
|
|
var
|
|
f: tceform;
|
|
begin
|
|
f := TCEForm(LuaForms[TMenuItem(Sender).Tag]);
|
|
if f.designsurface <> nil then
|
|
f.designsurface.Active := False;
|
|
|
|
f.RestoreToDesignState;
|
|
f.Show;
|
|
end;
|
|
|
|
procedure TMainForm.FormDesignerClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
var
|
|
i: integer;
|
|
f: TCEForm;
|
|
begin
|
|
for i := 0 to LuaForms.Count - 1 do
|
|
begin
|
|
f := TCEForm(LuaForms[i]);
|
|
f.Active := False;
|
|
if f.designsurface <> nil then
|
|
FreeAndNil(f.designsurface);
|
|
end;
|
|
|
|
closeAction := caFree;
|
|
FormDesigner := nil;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.RenameFileClick(Sender: TObject);
|
|
var
|
|
lf: TLuafile;
|
|
newname: string;
|
|
begin
|
|
lf := LuaFiles[TMenuItem(Sender).Tag];
|
|
newname:=lf.Name;
|
|
InputQuery(rsRenameFile, rsGiveTheNewFilename, newname);
|
|
|
|
if IsXmlName(newname, true) then
|
|
lf.name:=newname
|
|
else
|
|
MessageDlg(Format(rsIsNotAValidX, [newname]), mtError, [mbok], 0);
|
|
end;
|
|
|
|
procedure TMainForm.SaveFileClick(Sender: TObject);
|
|
var
|
|
lf: TLuafile;
|
|
f: TSavedialog;
|
|
begin
|
|
lf := LuaFiles[TMenuItem(Sender).Tag];
|
|
|
|
f := tsavedialog.Create(self);
|
|
try
|
|
f.filename := lf.Name;
|
|
if f.Execute then
|
|
lf.stream.SaveToFile(f.filename);
|
|
finally
|
|
freeandnil(f);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.DeleteFileClick(Sender: TObject);
|
|
var
|
|
lf: TLuafile;
|
|
begin
|
|
lf := LuaFiles[TMenuItem(Sender).Tag];
|
|
LuaFiles.Delete(TMenuItem(Sender).Tag);
|
|
|
|
lf.Free;
|
|
UpdateMenu;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.UpdateMenu;
|
|
var
|
|
i: integer;
|
|
mi: tmenuitem;
|
|
f: tceform;
|
|
lf: TLuafile;
|
|
|
|
submenu: TMenuItem;
|
|
|
|
m: tmemorystream;
|
|
b: tbitmap;
|
|
begin
|
|
miLuaFormsSeperator.Visible := True; //LuaForms.Count>0;
|
|
|
|
|
|
while miTable.Count > 5 do
|
|
begin
|
|
if miTable.Items[4] <> miLuaFormsSeperator then
|
|
miTable[4].Free
|
|
else
|
|
break;
|
|
end;
|
|
|
|
for i := 0 to LuaForms.Count - 1 do
|
|
begin
|
|
mi := tmenuitem.Create(miTable);
|
|
|
|
f := tceform(LuaForms[i]);
|
|
{
|
|
//this currently won't work
|
|
if f.icon<>nil then
|
|
begin
|
|
b:=tbitmap.create;
|
|
b.Width := f.Icon.Width;
|
|
b.Height := f.Icon.Height;
|
|
b.Canvas.Draw(0, 0, f.Icon ) ;
|
|
|
|
m:=tmemorystream.create;
|
|
b.SaveToStream(m);
|
|
m.position:=0;
|
|
mi.Bitmap.LoadFromStream(m);
|
|
m.free;
|
|
b.free;
|
|
end;}
|
|
|
|
|
|
mi.Caption := f.Name;
|
|
mi.ImageIndex:=16;
|
|
miTable.Insert(4, mi);
|
|
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := rsRestoreAndShow;
|
|
submenu.OnClick := @RestoreAndShowFormClick;
|
|
submenu.Tag := i;
|
|
submenu.Default := True;
|
|
mi.Add(submenu);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := rsEdit;
|
|
submenu.ImageIndex:=17;
|
|
submenu.OnClick := @EditFormClick;
|
|
submenu.Tag := i;
|
|
mi.Add(submenu);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := '-';
|
|
submenu.Tag := i;
|
|
mi.Add(submenu);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := rsDelete;
|
|
submenu.ImageIndex:=22;
|
|
submenu.OnClick := @DeleteFormClick;
|
|
submenu.Tag := i;
|
|
mi.Add(submenu);
|
|
end;
|
|
|
|
|
|
//and now the files
|
|
while miTable.Count > miTable.indexOf(miAddFile) + 1 do
|
|
miTable[miTable.indexOf(miAddFile) + 1].free;
|
|
|
|
for i := 0 to luafiles.Count - 1 do
|
|
begin
|
|
mi := tmenuitem.Create(miTable);
|
|
lf := luafiles[i];
|
|
mi.Caption := lf.Name;
|
|
|
|
miTable.add(mi);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := rsRename;
|
|
submenu.ImageIndex:=17;
|
|
submenu.OnClick := @RenameFileClick;
|
|
submenu.Tag := i;
|
|
mi.Add(submenu);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := rsSaveToDisk;
|
|
submenu.ImageIndex:=4;
|
|
submenu.OnClick := @SaveFileClick;
|
|
submenu.Tag := i;
|
|
mi.Add(submenu);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := '-';
|
|
mi.Add(submenu);
|
|
|
|
submenu := tmenuitem.Create(mi);
|
|
submenu.Caption := rsDelete;
|
|
submenu.ImageIndex:=22;
|
|
submenu.OnClick := @DeleteFileClick;
|
|
submenu.Tag := i;
|
|
mi.Add(submenu);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.createFormdesigner;
|
|
begin
|
|
if FormDesigner = nil then
|
|
begin
|
|
FormDesigner := TFormDesigner.Create(self);
|
|
formdesigner.autosize := False;
|
|
FormDesigner.OnClose2 := @FormDesignerClose;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miCreateLuaFormClick(Sender: TObject);
|
|
var
|
|
f: tceform;
|
|
i, j, k: integer;
|
|
|
|
s: string;
|
|
|
|
br: TRect;
|
|
begin
|
|
f := tceform.CreateNew(nil);
|
|
f.DesignTimePPI:=screen.PixelsPerInch;
|
|
f.autosize := False;
|
|
|
|
j := 1;
|
|
//found out a unique name for this form
|
|
for i := 0 to LuaForms.Count - 1 do
|
|
begin
|
|
s := copy(tceform(LuaForms[i]).Name, 1, 3);
|
|
if s = 'UDF' then
|
|
begin
|
|
s := tceform(LuaForms[i]).Name;
|
|
s := copy(s, 4, length(s));
|
|
if TryStrToInt(s, k) then
|
|
begin
|
|
if k >= j then
|
|
j := k + 1;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
f.Name := 'UDF' + IntToStr(j);
|
|
luaforms.add(f);
|
|
|
|
|
|
|
|
|
|
if formdesigner = nil then
|
|
createFormdesigner;
|
|
|
|
formdesigner.designForm(f);
|
|
|
|
formdesigner.Show;
|
|
|
|
f.clientwidth:=ScaleX(200,96);
|
|
f.clientheight:=ScaleY(200,96);
|
|
|
|
f.Show;
|
|
|
|
f.left := formdesigner.left;
|
|
|
|
LCLIntf.GetWindowRect(formdesigner.handle, br);
|
|
f.top := br.Bottom + 5;
|
|
|
|
updatemenu;
|
|
end;
|
|
|
|
procedure TMainForm.MenuItem7Click(Sender: TObject);
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TMainForm.miSetCrosshairClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if frmSetCrosshair = nil then
|
|
frmSetCrosshair := TfrmSetCrosshair.Create(self);
|
|
|
|
frmSetCrosshair.Show;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miTableClick(Sender: TObject);
|
|
begin
|
|
UpdateMenu;
|
|
end;
|
|
|
|
procedure TMainForm.miResetRangeClick(Sender: TObject);
|
|
begin
|
|
{$ifdef cpu64}
|
|
FromAddress.Text := '0000000000000000';
|
|
ToAddress.Text := '00007fffffffffff';
|
|
{$else}
|
|
FromAddress.Text := '00000000';
|
|
if Is64bitOS then
|
|
ToAddress.Text := 'ffffffff' //games with 3GB aware will use this in 64-bit os's
|
|
else
|
|
ToAddress.Text := '7fffffff';
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miChangeColorClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
if (addresslist.SelCount > 0) then
|
|
begin
|
|
colordialog1.Color:=addresslist.selectedRecord.Color;
|
|
if (colordialog1.Execute) then
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if addresslist[i].isSelected then
|
|
addresslist[i].color := colordialog1.Color;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.miBindActivationClick(Sender: TObject);
|
|
begin
|
|
miBindActivation.Checked := not miBindActivation.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miBindActivation.Checked then
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options + [moActivateChildrenAsWell]
|
|
else
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options - [moActivateChildrenAsWell];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miBindDeactivationClick(Sender: TObject);
|
|
begin
|
|
miBindDeactivation.Checked := not miBindDeactivation.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miBindDeactivation.Checked then
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options + [moDeactivateChildrenAsWell]
|
|
else
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options - [moDeactivateChildrenAsWell];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miDisassembleClick(Sender: TObject);
|
|
begin
|
|
if addresslist.selectedrecord <> nil then
|
|
begin
|
|
memorybrowser.disassemblerview.SelectedAddress := addresslist.selectedrecord.GetRealAddress;
|
|
memorybrowser.Show;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.miHideChildrenClick(Sender: TObject);
|
|
begin
|
|
miHideChildren.Checked := not miHideChildren.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miHideChildren.Checked then
|
|
addresslist.selectedRecord.options :=
|
|
addresslist.selectedRecord.options + [moHideChildren]
|
|
else
|
|
addresslist.selectedRecord.options :=
|
|
addresslist.selectedRecord.options - [moHideChildren];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.setGbScanOptionsEnabled(state: boolean);
|
|
procedure setstaterecursive(c: TWinControl);
|
|
var i: integer;
|
|
begin
|
|
c.enabled:=state;
|
|
for i:=0 to c.ControlCount-1 do
|
|
begin
|
|
if (c.Controls[i] is TWinControl) then
|
|
setstaterecursive(twincontrol(c.controls[i]))
|
|
else
|
|
c.controls[i].enabled:=state;
|
|
end;
|
|
|
|
end;
|
|
begin
|
|
setstaterecursive(gbScanOptions);
|
|
end;
|
|
|
|
procedure TMainForm.LoadCustomTypesFromRegistry;
|
|
var
|
|
reg: TRegistry;
|
|
customtypes: TStringList;
|
|
i: integer;
|
|
islua: boolean;
|
|
oldpos: integer;
|
|
begin
|
|
reg := tregistry.Create;
|
|
oldpos:=vartype.ItemIndex;
|
|
vartype.OnChange := nil;
|
|
//disable the onchange event so CreateCustomType doesn't keep setting it
|
|
try
|
|
if reg.OpenKey('\Software\'+strCheatEngine+'\CustomTypes\', False) then
|
|
begin
|
|
CustomTypes := TStringList.Create;
|
|
try
|
|
reg.GetKeyNames(CustomTypes);
|
|
|
|
for i := 0 to CustomTypes.Count - 1 do
|
|
begin
|
|
if reg.OpenKey('\Software\'+strCheatEngine+'\CustomTypes\' + CustomTypes[i], False) then
|
|
begin
|
|
try
|
|
islua := False;
|
|
if reg.ValueExists('lua') then
|
|
islua := reg.ReadBool('lua');
|
|
|
|
CreateCustomType(nil, reg.ReadString('Script'), True, islua);
|
|
except
|
|
outputdebugstring('The custom type script ''' + CustomTypes[i] +
|
|
''' could not be loaded');
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
except
|
|
//empty customtype
|
|
end;
|
|
freeandnil(CustomTypes);
|
|
end;
|
|
freeandnil(reg);
|
|
RefreshCustomTypes;
|
|
finally
|
|
vartype.itemindex:=oldpos;
|
|
vartype.OnChange := @VarTypeChange; //set the onchange event back
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.RefreshCustomTypes;
|
|
{
|
|
In short: remove all custom scan types and add them back
|
|
}
|
|
var
|
|
i: integer;
|
|
begin
|
|
vartype.items.BeginUpdate;
|
|
try
|
|
while VarType.Items.Count > 11 do
|
|
vartype.items.Delete(11);
|
|
|
|
|
|
for i := 0 to customTypes.Count - 1 do
|
|
vartype.Items.AddObject(TCustomType(customTypes[i]).Name, tobject(customTypes[i]));
|
|
|
|
//set to default (4 bytes) if not selected anything anymore
|
|
if (vartype.ItemIndex = -1) or (vartype.ItemIndex >= VarType.Items.Count) then
|
|
vartype.ItemIndex := 3;
|
|
|
|
|
|
finally
|
|
vartype.items.EndUpdate;
|
|
end;
|
|
|
|
vartype.DropDownCount := vartype.items.Count;
|
|
|
|
addresslist.refreshcustomtypes;
|
|
end;
|
|
|
|
procedure TMainForm.miDeleteCustomTypeClick(Sender: TObject);
|
|
var
|
|
reg: TRegistry;
|
|
ct: TCustomType;
|
|
begin
|
|
ct := TCustomType(vartype.Items.Objects[vartype.ItemIndex]);
|
|
if (ct <> nil) and ((ct.CustomTypeType = cttAutoAssembler) or
|
|
(ct.CustomTypeType = cttLuaScript)) then
|
|
begin
|
|
if messagedlg(Format(rsAreYouSureYouWantToDelete, [ct.Name]),
|
|
mtConfirmation, [mbNo, mbYes], 0) = mrYes then
|
|
begin
|
|
reg := tregistry.Create;
|
|
reg.DeleteKey('\Software\'+strCheatEngine+'\CustomTypes\' + ct.Name);
|
|
ct.remove;
|
|
RefreshCustomTypes;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.CreateCustomType(customtype: TCustomtype;
|
|
script: string; scriptchanged: boolean; lua: boolean = False);
|
|
var
|
|
reg: TRegistry;
|
|
ct: TCustomType;
|
|
oldname: string;
|
|
i: integer;
|
|
begin
|
|
|
|
ct := nil;
|
|
if scriptchanged then
|
|
begin
|
|
if customtype = nil then
|
|
begin
|
|
if not lua then
|
|
ct := TCustomType.CreateTypeFromAutoAssemblerScript(script)
|
|
else
|
|
ct := TcustomType.CreateTypeFromLuaScript(script);
|
|
end
|
|
else
|
|
begin
|
|
//edited script
|
|
|
|
ct := customtype;
|
|
oldname := ct.Name;
|
|
ct.setScript(script, lua);
|
|
|
|
//if the new script has a different name then delete the old one
|
|
if oldname <> ct.Name then
|
|
begin
|
|
//delete the old one
|
|
reg := Tregistry.Create;
|
|
reg.DeleteKey('\Software\'+strCheatEngine+'\CustomTypes\' + oldname);
|
|
freeandnil(reg);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
//Add/change this to the registry
|
|
reg := Tregistry.Create;
|
|
if Reg.OpenKey('\Software\'+strCheatEngine+'\CustomTypes\' + ct.Name, True) then
|
|
begin
|
|
reg.WriteString('Script', script);
|
|
if lua then
|
|
reg.WriteBool('lua', True);
|
|
|
|
end;
|
|
|
|
freeandnil(reg);
|
|
|
|
RefreshCustomTypes;
|
|
|
|
//now set the type to the current type
|
|
if (ct <> nil) then
|
|
begin
|
|
for i := 0 to vartype.Items.Count - 1 do
|
|
if TCustomType(vartype.items.objects[i]) = ct then
|
|
begin
|
|
vartype.ItemIndex := i;
|
|
if assigned(vartype.OnChange) then //force an onchange (lazarus bug)
|
|
vartype.OnChange(vartype);
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.miEditCustomTypeClick(Sender: TObject);
|
|
var
|
|
ct: TCustomType;
|
|
begin
|
|
ct := TCustomType(vartype.Items.Objects[vartype.ItemIndex]);
|
|
if (ct <> nil) and ((ct.CustomTypeType = cttAutoAssembler) or
|
|
(ct.CustomTypeType = cttLuaScript)) then
|
|
begin
|
|
|
|
with TfrmAutoInject.Create(self) do
|
|
begin
|
|
injectintomyself := True;
|
|
CustomTypeScript := True;
|
|
CustomTypeCallback := @CreateCustomType;
|
|
CustomType := ct;
|
|
if ct.CustomTypeType = cttLuaScript then
|
|
ScriptMode :=smLua;
|
|
|
|
assemblescreen.Lines.Text := CustomType.script;
|
|
|
|
Show;
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miDefineNewCustomTypeLuaClick(Sender: TObject);
|
|
var
|
|
fbn, n: string;
|
|
begin
|
|
n := 'Custom LUA type';
|
|
fbn := 'customvaluetype';
|
|
if customTypes.Count > 0 then
|
|
begin
|
|
n := n + ' ' + IntToStr(customtypes.Count + 1);
|
|
fbn := fbn + IntToStr(customtypes.Count + 1);
|
|
end;
|
|
|
|
with TfrmAutoInject.Create(self) do
|
|
begin
|
|
injectintomyself := True;
|
|
CustomTypeScript := True;
|
|
CustomTypeCallback := @CreateCustomType;
|
|
CustomType := nil;
|
|
ScriptMode:= smLua;
|
|
|
|
with assemblescreen.Lines do
|
|
begin
|
|
Add('--Note: keep the function base name unique.');
|
|
Add('local typename="' + n + '" --shown as the typename in ce');
|
|
Add('local bytecount=4 --number of bytes of this type');
|
|
Add('local functionbasename="' + fbn + '"');
|
|
Add('local usesfloat=false');
|
|
Add('local usesstring=false');
|
|
Add('');
|
|
Add('function ' + fbn + '_bytestovalue(b1,b2,b3,b4,address)');
|
|
Add('--Add extra byte parameters as required');
|
|
Add('return 123');
|
|
Add('');
|
|
Add('end');
|
|
Add('');
|
|
Add('function ' + fbn + '_valuetobytes(i,address)');
|
|
Add('');
|
|
Add('--return the bytes to write (usually only used when you change the value)');
|
|
Add('return 0,0,0,0');
|
|
Add('');
|
|
Add('end');
|
|
Add('return typename, bytecount, functionbasename, usesfloat, usesstring');
|
|
end;
|
|
Show;
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miDefineNewCustomTypeClick(Sender: TObject);
|
|
var
|
|
fbn, n: string;
|
|
begin
|
|
n := 'Custom Type Name';
|
|
if customTypes.Count > 0 then
|
|
n := n + ' ' + IntToStr(customtypes.Count + 1);
|
|
|
|
with TfrmAutoInject.Create(self) do
|
|
begin
|
|
injectintomyself := True;
|
|
CustomTypeScript := True;
|
|
CustomTypeCallback := @CreateCustomType;
|
|
CustomType := nil;
|
|
|
|
with assemblescreen.Lines do
|
|
begin
|
|
Add('alloc(ConvertRoutine,1024)');
|
|
Add('alloc(ConvertBackRoutine,1024)');
|
|
Add('alloc(TypeName,256)');
|
|
Add('alloc(ByteSize,4)');
|
|
Add('alloc(UsesFloat,1)');
|
|
Add('alloc(UsesString,1)');
|
|
Add('alloc(MaxStringSize,2)');
|
|
Add('alloc(CallMethod,1)');
|
|
Add('');
|
|
Add('TypeName:');
|
|
Add('db ''' + n + ''',0');
|
|
Add('');
|
|
Add('ByteSize:');
|
|
Add('dd 4');
|
|
Add('');
|
|
Add('UsesFloat:');
|
|
Add('db 0 //Change to 1 if this custom type should be treated as a float');
|
|
Add('');
|
|
Add('UsesString:');
|
|
Add('db 0');
|
|
Add('');
|
|
Add('MaxStringSize:');
|
|
Add('dw #100');
|
|
Add('');
|
|
Add('CallMethod:');
|
|
Add('db 1 //Remove or change to 0 for legacy call mechanism');
|
|
Add('');
|
|
Add('//The convert routine should hold a routine that converts the data to an integer (in eax)');
|
|
Add('//function declared as: cdecl int ConvertRoutine(unsigned char *input, PTR_UINT address);');
|
|
Add('//Note: Keep in mind that this routine can be called by multiple threads at the same time.');
|
|
Add('ConvertRoutine:');
|
|
Add('//jmp dllname.functionname');
|
|
add('[64-bit]');
|
|
Add('//or manual:');
|
|
Add('//parameters: (64-bit)');
|
|
{$ifdef windows}
|
|
Add('//rcx=address of input');
|
|
Add('//rdx=address');
|
|
Add('mov eax,[rcx] //eax now contains the bytes ''input'' pointed to');
|
|
{$else}
|
|
Add('//rdi=address of input');
|
|
Add('//rsi=address');
|
|
Add('mov eax,[rdi] //eax now contains the bytes ''input'' pointed to');
|
|
{$endif}
|
|
Add('');
|
|
Add('ret');
|
|
add('[/64-bit]');
|
|
add('');
|
|
{$ifndef darwin}
|
|
add('[32-bit]');
|
|
Add('//jmp dllname.functionname');
|
|
Add('//or manual:');
|
|
Add('//parameters: (32-bit)'); //[esp]=return [esp+4]=input
|
|
Add('push ebp'); //[esp]=ebp , [esp+4]=return [esp+8]=input
|
|
Add('mov ebp,esp'); //[ebp]=ebp , [esp+4]=return [esp+8]=input
|
|
Add('//[ebp+8]=address of input');
|
|
Add('//[ebp+c]=address');
|
|
Add('//example:');
|
|
Add('mov eax,[ebp+8] //place the address that contains the bytes into eax');
|
|
Add('mov eax,[eax] //place the bytes into eax so it''s handled as a normal 4 byte value');
|
|
Add('');
|
|
Add('pop ebp');
|
|
Add('ret');
|
|
add('[/32-bit]');
|
|
{$endif}
|
|
|
|
Add('');
|
|
Add('//The convert back routine should hold a routine that converts the given integer back to a row of bytes (e.g when the user wats to write a new value)');
|
|
Add('//function declared as: cdecl void ConvertBackRoutine(int i, PTR_UINT address, unsigned char *output);');
|
|
Add('ConvertBackRoutine:');
|
|
Add('//jmp dllname.functionname');
|
|
Add('//or manual:');
|
|
Add('[64-bit]');
|
|
Add('//parameters: (64-bit)');
|
|
{$ifdef windows}
|
|
Add('//ecx=input (integer)');
|
|
Add('//rdx=address');
|
|
Add('//r8=address of output');
|
|
Add('//example:');
|
|
Add('mov [r8],ecx //place the integer at the 4 bytes pointed to by r8');
|
|
{$else}
|
|
Add('//edi=input (integer)');
|
|
Add('//rsi=address');
|
|
Add('//rdx=address of output');
|
|
Add('//example:');
|
|
Add('mov [rsi],edi //place the integer at the 4 bytes pointed to by rdx');
|
|
{$endif}
|
|
|
|
Add('');
|
|
Add('ret');
|
|
Add('[/64-bit]');
|
|
add('');
|
|
{$ifndef darwin}
|
|
Add('[32-bit]');
|
|
Add('//parameters: (32-bit)'); //[esp]=return [esp+4]=input
|
|
Add('push ebp'); //[esp]=ebp , [esp+4]=return [esp+8]=input
|
|
Add('mov ebp,esp'); //[ebp]=ebp , [esp+4]=return [esp+8]=input
|
|
Add('//[ebp+8]=input');
|
|
Add('//[ebp+c]=address');
|
|
Add('//[ebp+10]=address of output');
|
|
Add('//example:');
|
|
Add('push eax');
|
|
Add('push ebx');
|
|
Add('mov eax,[ebp+8] //load the value into eax');
|
|
Add('mov ebx,[ebp+10] //load the output address into ebx');
|
|
Add('mov [ebx],eax //write the value into the address');
|
|
Add('pop ebx');
|
|
Add('pop eax');
|
|
|
|
Add('');
|
|
Add('pop ebp');
|
|
Add('ret');
|
|
add('[/32-bit]');
|
|
{$endif}
|
|
Add('');
|
|
end;
|
|
|
|
Show;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miRecursiveSetValueClick(Sender: TObject);
|
|
begin
|
|
miRecursiveSetValue.Checked := not miRecursiveSetValue.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miRecursiveSetValue.Checked then
|
|
addresslist.selectedRecord.options :=
|
|
addresslist.selectedRecord.options + [moRecursiveSetValue]
|
|
else
|
|
addresslist.selectedRecord.options :=
|
|
addresslist.selectedRecord.options - [moRecursiveSetValue];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miRenameTabClick(Sender: TObject);
|
|
var
|
|
s: string;
|
|
begin
|
|
s := scantablist.TabText[scantablist.SelectedTab];
|
|
if InputQuery(rsCheatEngine, rsWhatWillBeTheNewNameForThisTab, s) then
|
|
scantablist.TabText[scantablist.SelectedTab] := s;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.SaveCurrentState(scanstate: PScanState; skipuservalues: boolean=false);
|
|
begin
|
|
//save the current state
|
|
scanstate^.alignsizechangedbyuser := alignsizechangedbyuser;
|
|
|
|
scanstate^.compareToSavedScan := comparetosavedscan;
|
|
scanstate^.currentlySelectedSavedResultname := currentlySelectedSavedResultname;
|
|
scanstate^.compareToColumn := ActivePreviousResultColumn;
|
|
|
|
scanstate^.cbCompareToSavedScan.visible := cbCompareToSavedScan.Visible;
|
|
|
|
scanstate^.lblcompareToSavedScan.Caption := lblcompareToSavedScan.Caption;
|
|
scanstate^.lblcompareToSavedScan.Visible := lblcompareToSavedScan.Visible;
|
|
|
|
|
|
|
|
if not skipuservalues then
|
|
begin
|
|
scanstate^.FromAddress.Text := fromaddress.Text;
|
|
scanstate^.ToAddress.Text := toaddress.Text;
|
|
end;
|
|
|
|
|
|
scanstate^.cbfastscan.Checked := cbFastScan.Checked;
|
|
|
|
if not skipuservalues then
|
|
scanstate^.edtAlignment.Text := edtAlignment.Text;
|
|
|
|
scanstate^.edtAlignment.enabled:=edtAlignment.enabled;
|
|
|
|
scanstate^.rbFsmAligned.checked:=rbFsmAligned.checked;
|
|
|
|
if not skipuservalues then
|
|
scanstate^.scanvalue.Text := scanvalue.Text;
|
|
|
|
scanstate^.scanvalue.Visible := scanvalue.Visible;
|
|
|
|
if scanvalue2 <> nil then
|
|
begin
|
|
scanstate^.scanvalue2.exists := True;
|
|
if not skipuservalues then
|
|
scanstate^.scanvalue2.Text := scanvalue2.Text;
|
|
end
|
|
else
|
|
scanstate^.scanvalue2.exists := False;
|
|
|
|
scanstate^.scantype.options := scantype.Items.Text;
|
|
scanstate^.scantype.Enabled := scantype.Enabled;
|
|
scanstate^.scantype.ItemIndex := scantype.ItemIndex;
|
|
scanstate^.scantype.dropdowncount := scantype.DropDownCount;
|
|
|
|
//scanstate^.vartype.options := vartype.Items;
|
|
scanstate^.vartype.Enabled := vartype.Enabled;
|
|
scanstate^.vartype.ItemIndex := vartype.ItemIndex;
|
|
|
|
|
|
scanstate^.firstscanstate.Caption := btnNewScan.Caption;
|
|
scanstate^.firstscanstate.Enabled := btnNewScan.Enabled;
|
|
scanstate^.nextscanstate.Enabled := btnNextScan.Enabled;
|
|
|
|
|
|
scanstate^.gbScanOptionsEnabled := gbScanOptions.Enabled;
|
|
|
|
scanstate^.floatpanel.Visible := pnlfloat.Visible;
|
|
scanstate^.floatpanel.rounded := rt1.Checked;
|
|
scanstate^.floatpanel.roundedextreme := rt2.Checked;
|
|
scanstate^.floatpanel.truncated := rt3.Checked;
|
|
|
|
|
|
scanstate^.rbbit.Visible := rbbit.Visible;
|
|
scanstate^.rbbit.Enabled := rbbit.Enabled;
|
|
scanstate^.rbbit.Checked := rbbit.Checked;
|
|
|
|
scanstate^.rbdec.Visible := rbdec.Visible;
|
|
scanstate^.rbdec.Enabled := rbdec.Enabled;
|
|
scanstate^.rbdec.Checked := rbdec.Checked;
|
|
|
|
scanstate^.cbHexadecimal.Visible := cbHexadecimal.Visible;
|
|
scanstate^.cbHexadecimal.Checked := cbHexadecimal.Checked;
|
|
scanstate^.cbHexadecimal.Enabled := cbHexadecimal.Enabled;
|
|
|
|
scanstate^.cbunicode.Visible := cbunicode.visible;
|
|
scanstate^.cbunicode.checked := cbunicode.checked;
|
|
|
|
scanstate^.cbRepeatUntilStopped.visible:=cbRepeatUntilStopped.visible;
|
|
scanstate^.cbRepeatUntilStopped.checked:=cbRepeatUntilStopped.Checked;
|
|
|
|
scanstate^.cbcodepage.Visible := cbcodepage.visible;
|
|
scanstate^.cbcodepage.checked := cbcodepage.checked;
|
|
scanstate^.cbCaseSensitive.Visible := cbCaseSensitive.visible;
|
|
scanstate^.cbCaseSensitive.checked := cbCaseSensitive.checked;
|
|
scanstate^.cbNot.visible:=cbNot.visible;
|
|
scanstate^.cbnot.checked:=cbNot.checked;
|
|
scanstate^.cbLuaformula.visible:=cbLuaFormula.Visible;
|
|
scanstate^.cbLuaformula.checked:=cbLuaFormula.Checked;
|
|
scanstate^.cbNewLuaState.visible:=cbNewLuaState.Visible;
|
|
scanstate^.cbNewLuaState.checked:=cbNewLuaState.checked;
|
|
|
|
if cbpercentage <> nil then
|
|
begin
|
|
scanstate^.cbpercentage.exists := False;
|
|
scanstate^.cbpercentage.Checked := cbpercentage.Checked;
|
|
end
|
|
else
|
|
scanstate^.cbpercentage.exists := False;
|
|
|
|
scanstate^.btnFirst.tag := btnFirst.tag;
|
|
scanstate^.foundlist3.ItemIndex := foundlist3.ItemIndex;
|
|
|
|
scanstate^.foundlistDisplayOverride:=foundlistDisplayOverride;
|
|
|
|
scanstate^.cbNot.Checked:=cbNot.checked;
|
|
scanstate^.cbfloatSimple.Checked:=cbFloatSimple.checked
|
|
|
|
|
|
{
|
|
if foundlist3.TopItem<>nil then
|
|
scanstate^.foundlist3.topitemindex:=foundlist3.topitem.Index
|
|
else
|
|
scanstate^.foundlist3.topitemindex:=-1; }
|
|
end;
|
|
|
|
procedure TMainForm.SetupInitialScanTabState(scanstate: PScanState;
|
|
IsFirstEntry: boolean);
|
|
begin
|
|
ZeroMemory(scanstate, sizeof(TScanState));
|
|
|
|
if IsFirstEntry then
|
|
begin
|
|
scanstate^.memscan := memscan;
|
|
scanstate^.foundlist := foundlist;
|
|
end
|
|
else
|
|
begin
|
|
scanstate^.memscan := tmemscan.Create(ProgressBar);
|
|
scanstate^.memscan.GuiScanner:=true;
|
|
scanstate^.memscan.OnGuiUpdate:=@MemscanGuiUpdate;
|
|
scanstate^.foundlist := TFoundList.Create(foundlist3, scanstate^.memscan); //build again
|
|
scanstate^.memscan.OnInitialScanDone:=memscan.OnInitialScanDone;
|
|
scanstate^.memscan.OnScanDone:=memscan.OnScanDone;
|
|
scanstate^.memscan.OnScanStart:=memscan.OnScanStart;
|
|
end;
|
|
|
|
savecurrentstate(scanstate);
|
|
reloadPreviousResults;
|
|
ActivePreviousResultColumn:=2;
|
|
end;
|
|
|
|
procedure TMainForm.ScanTabListTabChange(Sender: TObject; oldselection: integer);
|
|
var
|
|
oldstate, newstate: PScanState;
|
|
begin
|
|
oldstate := scantablist.TabData[oldselection];
|
|
newstate := scantablist.TabData[scantablist.SelectedTab];
|
|
|
|
savecurrentstate(oldstate);
|
|
|
|
//load the new state
|
|
if newstate <> nil then
|
|
begin
|
|
//load
|
|
mainform.BeginFormUpdate;
|
|
foundlist3.beginupdate;
|
|
foundlist.Deinitialize;
|
|
|
|
foundlistDisplayOverride:=0;
|
|
|
|
scantype.OnChange := nil;
|
|
vartype.onchange := nil;
|
|
rbbit.OnClick := nil;
|
|
rbdec.Onclick := nil;
|
|
cbHexadecimal.OnClick := nil;
|
|
|
|
//cleanupPreviousResults;
|
|
|
|
|
|
|
|
scanvalue.Text := newstate^.scanvalue.Text;
|
|
scanvalue.Visible := newstate^.scanvalue.Visible;
|
|
|
|
if newstate^.scanvalue2.exists then
|
|
begin
|
|
CreateScanValue2;
|
|
scanvalue2.Text := newstate^.scanvalue2.Text;
|
|
end
|
|
else
|
|
begin
|
|
//destroy if it exists
|
|
DestroyScanValue2;
|
|
end;
|
|
|
|
alignsizechangedbyuser := newstate^.alignsizechangedbyuser;
|
|
comparetosavedscan := newstate^.compareToSavedScan;
|
|
currentlySelectedSavedResultname := newstate^.currentlySelectedSavedResultname;
|
|
//I love long variable names
|
|
|
|
cbCompareToSavedScan.visible := newstate^.cbCompareToSavedScan.visible;
|
|
|
|
lblcompareToSavedScan.Caption := newstate^.lblcompareToSavedScan.Caption;
|
|
lblcompareToSavedScan.Visible := newstate^.lblcompareToSavedScan.Visible;
|
|
|
|
|
|
scantype.items.Text := newstate^.scantype.options;
|
|
scantype.Enabled := newstate^.scantype.Enabled;
|
|
scantype.ItemIndex := newstate^.scantype.ItemIndex;
|
|
scantype.DropDownCount := newstate^.scantype.dropdowncount;
|
|
|
|
// vartype.items.Text := newstate^.vartype.options;
|
|
vartype.Enabled := newstate^.vartype.Enabled;
|
|
vartype.ItemIndex := newstate^.vartype.ItemIndex;
|
|
|
|
|
|
btnNewScan.Caption := newstate^.firstscanstate.Caption;
|
|
btnNewScan.Enabled := newstate^.firstscanstate.Enabled;
|
|
|
|
btnNextScan.Enabled := newstate^.nextscanstate.Enabled;
|
|
|
|
setGbScanOptionsEnabled(newstate^.gbScanOptionsEnabled);
|
|
|
|
cbFastScan.OnChange:=nil;
|
|
cbFastScan.Checked := newstate^.cbfastscan.Checked;
|
|
cbFastScan.OnChange:=@cbFastScanChange;
|
|
|
|
edtAlignment.Text := newstate^.edtAlignment.Text;
|
|
edtAlignment.Enabled:=newstate^.edtAlignment.enabled;
|
|
rbFsmAligned.checked:=newstate^.rbFsmAligned.checked;
|
|
if rbFsmAligned.checked=false then
|
|
rbfsmLastDigts.checked:=true;
|
|
|
|
|
|
pnlfloat.Visible := newstate^.floatpanel.Visible;
|
|
rt1.Checked := newstate^.floatpanel.rounded;
|
|
rt2.Checked := newstate^.floatpanel.roundedextreme;
|
|
rt3.Checked := newstate^.floatpanel.truncated;
|
|
|
|
|
|
|
|
|
|
|
|
rbbit.Visible := newstate^.rbbit.Visible;
|
|
rbbit.Enabled := newstate^.rbbit.Enabled;
|
|
rbbit.Checked := newstate^.rbbit.Checked;
|
|
|
|
rbdec.Visible := newstate^.rbdec.Visible;
|
|
rbdec.Enabled := newstate^.rbdec.Enabled;
|
|
rbdec.Checked := newstate^.rbdec.Checked;
|
|
|
|
cbHexadecimal.Visible := newstate^.cbHexadecimal.Visible;
|
|
cbHexadecimal.Checked := newstate^.cbHexadecimal.Checked;
|
|
cbHexadecimal.Enabled := newstate^.cbHexadecimal.Enabled;
|
|
|
|
if newstate^.cbpercentage.exists then
|
|
begin
|
|
CreateCbPercentage;
|
|
cbpercentage.Checked := newstate^.cbpercentage.Checked;
|
|
end
|
|
else
|
|
DestroyCbPercentage;
|
|
|
|
btnFirst.tag := newstate^.btnFirst.tag;
|
|
|
|
scantype.OnChange := @ScanTypeChange;
|
|
VarType.OnChange := @VarTypeChange;
|
|
rbbit.OnClick := @rbBitClick;
|
|
rbdec.Onclick := @rbDecClick;
|
|
cbHexadecimal.OnClick := @cbHexadecimalClick;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memscan := newstate^.memscan;
|
|
foundlist := newstate^.foundlist;
|
|
|
|
|
|
if VarType.itemindex=10 then
|
|
begin
|
|
createGroupConfigButton;
|
|
scantype.Visible:=false;
|
|
lblscantype.Visible:=false;
|
|
end
|
|
else
|
|
begin
|
|
destroyGroupConfigButton;
|
|
scantype.Visible:=true;
|
|
lblscantype.Visible:=true;
|
|
end;
|
|
|
|
UpdateScanType;
|
|
|
|
|
|
|
|
foundcount := foundlist.Initialize(getvartype, memscan.customtype);
|
|
|
|
|
|
cbunicode.Visible := newstate^.cbunicode.visible;
|
|
cbunicode.checked := newstate^.cbunicode.checked;
|
|
cbCodePage.Visible := newstate^.cbCodePage.visible;
|
|
cbCodePage.checked := newstate^.cbCodePage.checked;
|
|
cbCaseSensitive.Visible := newstate^.cbCaseSensitive.visible;
|
|
cbCaseSensitive.checked := newstate^.cbCaseSensitive.checked;
|
|
|
|
|
|
cbRepeatUntilStopped.visible:=newstate^.cbRepeatUntilStopped.visible;
|
|
cbRepeatUntilStopped.Checked:=newstate^.cbRepeatUntilStopped.checked;
|
|
cbNot.visible:=newstate^.cbNot.visible;
|
|
cbNot.checked:=newstate^.cbNot.Checked;
|
|
cbLuaFormula.visible:=newstate^.cbLuaformula.visible;
|
|
cbLuaFormula.checked:=newstate^.cbLuaformula.checked;
|
|
cbNewLuaState.visible:=newstate^.cbNewLuaState.visible;
|
|
cbNewLuaState.Checked:=newstate^.cbNewLuaState.checked;
|
|
|
|
if newstate^.foundlist3.ItemIndex=-1 then
|
|
newstate^.foundlist3.ItemIndex:=0;
|
|
|
|
if (newstate^.foundlist3.ItemIndex < foundcount) then
|
|
begin
|
|
foundlist3.multiselect:=false; //laz2.0.0: If multiselect is true when itemindex gets set ALL entries get deselected one by one (+each one triggering ondata)
|
|
foundlist3.ItemIndex := newstate^.foundlist3.ItemIndex;
|
|
foundlist3.Items[newstate^.foundlist3.ItemIndex].Selected := True;
|
|
foundlist3.Items[newstate^.foundlist3.ItemIndex].MakeVisible(False);
|
|
foundlist3.Items[newstate^.foundlist3.ItemIndex].Top := 0;
|
|
foundlist3.multiselect:=true;
|
|
end;
|
|
|
|
|
|
|
|
foundlistDisplayOverride:=newstate^.foundlistDisplayOverride;
|
|
|
|
cbNot.Checked:=newstate^.cbNot.checked;
|
|
cbFloatSimple.checked:=newstate^.cbfloatSimple.Checked;
|
|
|
|
UpdateFloatRelatedPositions;
|
|
|
|
reloadPreviousResults;
|
|
ActivePreviousResultColumn:=newstate^.compareToColumn;
|
|
|
|
// Panel5Resize(nil);
|
|
foundlist3.endupdate;
|
|
|
|
mainform.EndFormUpdate;
|
|
|
|
// foundlist3.TopItem:=foundlist3.items[newstate^.foundlist.itemindex];
|
|
end;
|
|
//else leave empty
|
|
end;
|
|
|
|
procedure TMainForm.miAddTabClick(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
c: array of tcontrol;
|
|
foundlistheightdiff: integer;
|
|
newstate: PScanState;
|
|
|
|
scantabtopcontrol: TControl;
|
|
begin
|
|
|
|
if scantablist = nil then
|
|
begin
|
|
foundlistheightdiff := btnMemoryView.top - (foundlist3.top + foundlist3.Height);
|
|
|
|
scantablist := TTablist.Create(self);
|
|
scantablist.Name:='ScantabList';
|
|
|
|
scantabtopcontrol:=panel7;
|
|
if scantabtopcontrol.top+scantabtopcontrol.Height<ProgressBar.Top+ProgressBar.Height then
|
|
scantabtopcontrol:=ProgressBar;
|
|
|
|
scantablist.AnchorSideTop.Control:=scantabtopcontrol;
|
|
scantablist.AnchorSideTop.Side:=asrBottom;
|
|
|
|
scantablist.AnchorSideLeft.Control:=panel5;
|
|
scantablist.AnchorSideLeft.Side:=asrLeft;
|
|
|
|
scantablist.AnchorSideRight.Control:=logopanel;
|
|
if scantabtopcontrol.Top+scantabtopcontrol.Height<(logopanel.Height-4) then
|
|
scantablist.AnchorSideRight.Side:=asrLeft
|
|
else
|
|
scantablist.AnchorSideRight.Side:=asrRight; //it can go under the logo
|
|
|
|
scantablist.BorderSpacing.Top:=4;
|
|
|
|
|
|
scantablist.PopupMenu := pmTablist;
|
|
scantablist.color := panel5.GetRGBColorResolvingParent; //Color;
|
|
scantablist.Parent:=panel5;
|
|
scantablist.Anchors := [akTop, akLeft, akRight];
|
|
|
|
scantablist.Height := scantablist.Canvas.TextHeight('WwJjDdQq')+4;
|
|
|
|
label6.AnchorSideTop.Control:=scantablist;
|
|
|
|
|
|
//lblcompareToSavedScan.AnchorSideTop.Control:=scantablist;
|
|
|
|
|
|
i := scantablist.AddTab(rsScan + ' 1'); //original scan
|
|
|
|
getmem(newstate, sizeof(TScanState));
|
|
SetupInitialScanTabState(newstate, True);
|
|
scantablist.TabData[i] := newstate;
|
|
|
|
i := scantablist.AddTab(rsScan + ' 2'); //first new scan
|
|
getmem(newstate, sizeof(TScanState));
|
|
SetupInitialScanTabState(newstate, False);
|
|
scantablist.TabData[i] := newstate;
|
|
|
|
scantablist.OnTabChange := @ScanTabListTabChange;
|
|
scantablist.SelectedTab := i;
|
|
|
|
|
|
tabcounter := 3;
|
|
|
|
|
|
//scantablist.Color := clBtnFace;
|
|
scantablist.Brush.Color := panel5.color;
|
|
|
|
|
|
|
|
foundlist3.Height := btnMemoryView.top - foundlist3.top - foundlistheightdiff;
|
|
|
|
scantype.Top:=scantype.top+scantablist.Height+4;
|
|
end
|
|
else
|
|
begin
|
|
i := scantablist.addtab(rsScan + ' ' + IntToStr(tabcounter));
|
|
getmem(newstate, sizeof(TScanState));
|
|
SetupInitialScanTabState(newstate, False);
|
|
scantablist.TabData[i] := newstate;
|
|
|
|
scantablist.SelectedTab := i;
|
|
Inc(tabcounter);
|
|
end;
|
|
|
|
if btnNextScan.Enabled then
|
|
btnNewScan.click;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miCloseTabClick(Sender: TObject);
|
|
var
|
|
oldscanstate: PScanState;
|
|
oldindex: integer;
|
|
begin
|
|
if (scantablist <> nil) and (scantablist.Count > 1) then
|
|
begin
|
|
//since rightclicking a tab selects it, delete the currently selected tab
|
|
oldindex := scantablist.SelectedTab;
|
|
oldscanstate := scantablist.TabData[scantablist.SelectedTab];
|
|
|
|
//switch the currently selected tab to the right one if possible, else the lef tone
|
|
if oldindex < scantablist.Count - 1 then
|
|
scantablist.SelectedTab := oldindex + 1
|
|
else
|
|
scantablist.SelectedTab := oldindex - 1;
|
|
|
|
scantablist.RemoveTab(oldindex);
|
|
|
|
//now we can delete the tabdata
|
|
freeandnil(oldscanstate^.foundlist);
|
|
freeandnil(oldscanstate^.memscan);
|
|
freememandnil(oldscanstate);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.UpdateFloatRelatedPositions;
|
|
begin
|
|
if pnlFloat.visible then
|
|
begin
|
|
// cbFloatSimple.Top:=pnlFloat.Top+pnlFloat.Height;
|
|
// cbUnrandomizer.top:=cbFloatSimple.Top+cbFloatSimple.Height;
|
|
cbFloatSimple.visible:=true;
|
|
end
|
|
else
|
|
begin
|
|
// cbFloatSimple.top:=pnlFloat.top;
|
|
// cbUnrandomizer.top:=gbScanOptions.top;
|
|
|
|
cbFloatSimple.visible:=(getVarType in [vtSingle, vtDouble, vtAll]) and (GetScanType<>soUnknownValue);
|
|
end;
|
|
|
|
// if cbpercentage<>nil then
|
|
// cbFloatSimple.Top:=cbpercentage.top+cbpercentage.Height;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miFreezeNegativeClick(Sender: TObject);
|
|
begin
|
|
addresslist.ActivateSelected(ftAllowDecrease);
|
|
end;
|
|
|
|
procedure TMainForm.miFreezePositiveClick(Sender: TObject);
|
|
begin
|
|
addresslist.ActivateSelected(ftAllowIncrease);
|
|
end;
|
|
|
|
procedure TMainForm.miSaveScanresultsClick(Sender: TObject);
|
|
var
|
|
n: string;
|
|
begin
|
|
if memscan.nextscanCount > 0 then
|
|
begin
|
|
n := rsScanresult + ' ' + IntToStr(memscan.nextscanCount + 1);
|
|
if inputquery(rsSaveScanResults, rsWhatNameDoYouWantToGiveToTheseScanresults, n) then
|
|
begin
|
|
memscan.saveresults(n);
|
|
cbCompareToSavedScan.caption:=rsCompareToSavedScan;
|
|
reloadPreviousResults;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miShowAsBinaryClick(Sender: TObject);
|
|
begin
|
|
if (addresslist.selectedrecord <> nil) and
|
|
(addresslist.selectedrecord.vartype = vtbinary) then
|
|
addresslist.selectedrecord.extra.bitData.showasbinary := not
|
|
addresslist.selectedrecord.extra.bitData.showasbinary;
|
|
end;
|
|
|
|
procedure TMainForm.miUndoValueClick(Sender: TObject);
|
|
begin
|
|
if (addresslist.selectedrecord <> nil) and (addresslist.selectedrecord.canUndo) then
|
|
addresslist.selectedrecord.UndoSetValue;
|
|
end;
|
|
|
|
procedure TMainForm.miWireframeClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
safed3dhook;
|
|
if d3dhook<>nil then
|
|
d3dhook.setWireframeMode(miWireframe.Checked);
|
|
|
|
updated3dgui;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miZbufferClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
safed3dhook;
|
|
if d3dhook<>nil then
|
|
d3dhook.setDisabledZBuffer(miZbuffer.Checked);
|
|
|
|
updated3dgui;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miZeroTerminateClick(Sender: TObject);
|
|
begin
|
|
if (addresslist.selectedRecord <> nil) and
|
|
(addresslist.selectedRecord.VarType = vtString) then
|
|
addresslist.selectedRecord.Extra.stringData.ZeroTerminate := not
|
|
addresslist.selectedRecord.Extra.stringData.ZeroTerminate;
|
|
end;
|
|
|
|
procedure TMainForm.Panel5Resize(Sender: TObject);
|
|
var
|
|
widthleft,w,aw: integer;
|
|
i: integer;
|
|
|
|
f: double;
|
|
begin
|
|
// scanvalue2.width:=(((panel5.width-5)-scanvalue.left+((andlabel.width+10) div 2)) div 2);
|
|
if sender<>nil then
|
|
begin
|
|
w:=(panel5.clientwidth-scanvalue.left)-5 ;
|
|
aw:=andlabel.width+8;
|
|
scanvalue2.width:=(w div 2) - (aw div 2);
|
|
end;
|
|
|
|
//resize the foundlist columns. Do NOT do this in the onresize of the foundlist
|
|
widthleft:=foundlist3.clientwidth-foundlist3.Columns[0].Width;
|
|
|
|
if miShowPreviousValue.checked then
|
|
begin
|
|
if miOnlyShowCurrentCompareToColumn.checked then
|
|
begin
|
|
//old method
|
|
w:=widthleft div 2;
|
|
foundlist3.columns[1].width:=ceil(w*1.1);
|
|
for i:=2 to foundlist3.columns.count-1 do
|
|
begin
|
|
if foundlist3.columns[i].visible then
|
|
foundlist3.columns[i].width:=trunc(w*0.9);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
|
|
if (widthleft>0) and (foundlist3.ColumnCount>1) then
|
|
w:=widthleft div (foundlist3.ColumnCount-1)
|
|
else
|
|
w:=4;
|
|
|
|
//column 1 will get a %10 longer size than the compare against columns
|
|
f:=w*1.1;
|
|
foundlist3.columns[1].width:=ceil(f);
|
|
|
|
widthleft:=widthleft-foundlist3.columns[1].width;
|
|
if (widthleft>0) and (foundlist3.ColumnCount>2) then
|
|
w:=widthleft div (foundlist3.ColumnCount-2)
|
|
else
|
|
w:=4;
|
|
|
|
for i:=2 to foundlist3.ColumnCount-1 do
|
|
foundlist3.columns[i].width:=TWidth(w);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
foundlist3.columns[1].width:=widthleft;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.pmTablistPopup(Sender: TObject);
|
|
var
|
|
x, y: integer;
|
|
begin
|
|
if scantablist <> nil then //should always be true
|
|
begin
|
|
x := scantablist.ScreenToClient(mouse.cursorpos).x;
|
|
y := scantablist.ScreenToClient(mouse.cursorpos).y;
|
|
miCloseTab.Visible := scantablist.GetTabIndexAt(x, y) <> -1;
|
|
miTablistSeperator.Visible := miCloseTab.Visible;
|
|
miRenameTab.Visible := miCloseTab.Visible;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.pmValueTypePopup(Sender: TObject);
|
|
begin
|
|
miEditCustomType.Visible := (vartype.ItemIndex <> -1) and
|
|
(vartype.items.objects[vartype.ItemIndex] <> nil);
|
|
miDeleteCustomType.Visible := miEditCustomType.Visible;
|
|
|
|
miShowCustomTypeDebug.visible:=miEditCustomType.Visible and (GetKeyState(VK_SHIFT) and 32768=32768);
|
|
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miShowCustomTypeDebugClick(Sender: TObject);
|
|
var ct: TCustomType;
|
|
begin
|
|
ct:=TCustomType(vartype.items.objects[vartype.ItemIndex]);
|
|
ct.showDebugInfo;
|
|
end;
|
|
|
|
procedure TMainForm.miShowPreviousValueClick(Sender: TObject);
|
|
var
|
|
reg: Tregistry;
|
|
i: integer;
|
|
begin
|
|
//Show/Hide the previousValue column
|
|
//
|
|
|
|
if miShowPreviousValue.checked then
|
|
begin
|
|
miOnlyShowCurrentCompareToColumn.enabled:=true;
|
|
if miOnlyShowCurrentCompareToColumn.checked then
|
|
begin
|
|
foundlist3.Column[2].visible:=true;
|
|
for i:=3 to foundlist3.columncount-1 do
|
|
foundlist3.column[i].Visible:=false;
|
|
end
|
|
else
|
|
begin
|
|
for i:=2 to foundlist3.columncount-1 do
|
|
foundlist3.column[i].Visible:=true;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
miOnlyShowCurrentCompareToColumn.checked:=false;
|
|
miOnlyShowCurrentCompareToColumn.enabled:=false;
|
|
for i:=2 to foundlist3.columncount-1 do
|
|
foundlist3.column[i].Visible:=false;
|
|
end;
|
|
|
|
|
|
Panel5Resize(nil);
|
|
|
|
cereg.writeBool('Show previous value column', miShowPreviousValue.checked);
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.doNewScan;
|
|
var c: TListColumn ;
|
|
begin
|
|
if SaveFirstScanThread <> nil then //stop saving the results of the fist scan
|
|
begin
|
|
SaveFirstScanThread.Terminate;
|
|
SaveFirstScanThread.WaitFor;
|
|
FreeAndNil(SaveFirstScanThread);
|
|
end;
|
|
|
|
cleanupPreviousResults;
|
|
//create a dummy previous column
|
|
c:=foundlist3.Columns.Add;
|
|
c.caption:=rsPrevious;
|
|
c.tag:=foundlistColors.CompareToHeaderColor;
|
|
fActivePreviousResultColumn:=2;
|
|
|
|
|
|
fastscan := formsettings.cbFastscan.Checked;
|
|
//close files in case of a bug i might have missed...
|
|
|
|
vartype.Visible := True;
|
|
|
|
foundcount := 0;
|
|
foundlist.Clear;
|
|
|
|
btnNewScan.Caption := strFirstScan;
|
|
|
|
btnNextScan.Enabled := False;
|
|
vartype.Enabled := True;
|
|
|
|
scanvalue.Visible := True;
|
|
scantext.Visible := True;
|
|
|
|
Updatescantype;
|
|
Scantype.ItemIndex := 0;
|
|
|
|
//enable the memory scan groupbox
|
|
setGbScanOptionsEnabled(True);
|
|
|
|
VartypeChange(vartype);
|
|
|
|
if scanvalue.Visible and scanvalue.Enabled then
|
|
begin
|
|
scanvalue.SetFocus;
|
|
scanvalue.SelectAll;
|
|
end;
|
|
|
|
compareToSavedScan := False;
|
|
lblcompareToSavedScan.Visible := False;
|
|
cbCompareToSavedScan.Checked:=false;
|
|
cbCompareToSavedScan.Caption:=strCompareToFirstScan;
|
|
cbCompareToSavedScan.Visible:=false;
|
|
|
|
miDisplayDefault.checked:=true;
|
|
foundlistDisplayOverride:=0;
|
|
|
|
{$ifdef windows}
|
|
if formsettings.cbPauseWhenScanningOnByDefault.checked then
|
|
cbPauseWhileScanning.Checked:=true;
|
|
{$endif}
|
|
|
|
cbpercentage.checked:=false;
|
|
end;
|
|
|
|
procedure TMainForm.btnNewScanClick(Sender: TObject);
|
|
begin
|
|
btnFirst.click; //now completely replaced
|
|
end;
|
|
|
|
procedure TMainForm.btnNextScanClick(Sender: TObject);
|
|
begin
|
|
btnNext.click;
|
|
end;
|
|
|
|
procedure TMainForm.btnMemoryViewClick(Sender: TObject);
|
|
begin
|
|
memorybrowser.Show;
|
|
if memorybrowser.WindowState=wsMinimized then
|
|
memorybrowser.WindowState:=wsNormal;
|
|
end;
|
|
|
|
|
|
|
|
function TMainForm.onhelp(Command: word; Data: PtrInt; var CallHelp: boolean): boolean;
|
|
var
|
|
wikipath: string;
|
|
wikiurl: string;
|
|
begin
|
|
callhelp := False;
|
|
Result := True;
|
|
|
|
wikipath:='https://wiki.cheatengine.org/index.php';
|
|
wikiurl:='';
|
|
|
|
if command = HELP_CONTEXT then
|
|
begin
|
|
case data of
|
|
1: wikiurl:='?';
|
|
2: wikiurl:='?title=Help_File:AboutLong';
|
|
4: wikiurl:='?title=Tutorials:AttachToProcess';
|
|
11: wikiurl:='?title=Help_File:Table_Extras';
|
|
12: wikiurl:='?title=Help_File:Memory_view';
|
|
19: wikiurl:='?title=Cheat_Engine:Lua';
|
|
1089: wikiurl:='?title=Cheat_Engine:Auto_Assembler';
|
|
end;
|
|
|
|
{$ifdef windows}
|
|
if wikiurl='' then //no wikilink given
|
|
HtmlHelpA(Win32WidgetSet.AppHandle, PChar(cheatenginedir + 'cheatengine.chm'), HH_HELP_CONTEXT, Data)
|
|
else
|
|
{$endif}
|
|
ShellExecute(0,'open',pchar(wikipath+wikiurl),nil,nil,SW_SHOW);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
procedure TMainForm.FormCreate(Sender: TObject);
|
|
var
|
|
tokenhandle: thandle;
|
|
{$ifdef windows}
|
|
tp: TTokenPrivileges;
|
|
prev: TTokenPrivileges;
|
|
{$endif}
|
|
|
|
ReturnLength: Dword;
|
|
|
|
differentWidth: integer;
|
|
x: array of integer;
|
|
|
|
errormode: dword;
|
|
minworkingsize, maxworkingsize: ptruint;
|
|
//reg: tregistry;
|
|
|
|
PODirectory, Lang, FallbackLang: string;
|
|
|
|
rs: TResourceStream;
|
|
|
|
i: integer;
|
|
|
|
dir: string;
|
|
createlog: boolean;
|
|
s: string;
|
|
begin
|
|
exceptionerrorcs:=TCriticalSection.Create;
|
|
mtid:=MainThreadID;
|
|
|
|
tthread.NameThreadForDebugging('Main GUI Thread', GetCurrentThreadId);
|
|
|
|
PreviousResultList:=Tlist.Create;
|
|
|
|
|
|
|
|
{$if (LCL_FULLVERSION > 1060400) and (lcl_fullversion <=1080200)}
|
|
Foundlist3.Dragmode:=dmManual; //perhaps this gets fixed in later lcl versions, but for now, it sucks
|
|
{$endif}
|
|
|
|
//Self.AutoAdjustLayout(lapAutoAdjustForDPI, Self.DesignTimeDPI, Screen.PixelsPerInch, Self.Width, ScaleX(Self.Width, Self.DesignTimeDPI));
|
|
// Self.AutoAdjustLayout(lapAutoAdjustForDPI, Self.DesignTimeDPI, 200, Self.Width, ScaleX(Self.Width, Self.DesignTimeDPI));
|
|
{ font.size:=20;
|
|
i:=FromAddress.Font.Size;
|
|
FromAddress.Font.Size:=font.size;
|
|
if i=0 then beep; }
|
|
|
|
lastAdded.vartype:=vtDword;
|
|
|
|
miSignTable.visible:={$ifdef windows}canSignTables{$else}false{$endif};
|
|
|
|
|
|
vartype.Items.Clear;
|
|
vartype.items.add(rs_vtBinary);
|
|
vartype.items.add(rs_vtByte);
|
|
vartype.items.add(rs_vtWord);
|
|
vartype.items.add(rs_vtDword);
|
|
vartype.items.add(rs_vtQword);
|
|
vartype.items.add(rs_vtSingle);
|
|
vartype.items.add(rs_vtDouble);
|
|
vartype.items.add(rs_vtString);
|
|
vartype.items.add(rs_vtByteArray);
|
|
vartype.items.add(rs_vtAll);
|
|
vartype.items.add(rs_vtGrouped);
|
|
|
|
|
|
{$ifdef windows}
|
|
{$ifdef cpu64}
|
|
//lazarus bug bypass
|
|
if WindowsVersion = wvVista then
|
|
foundlist3.OnCustomDrawItem := nil;
|
|
{$endif}
|
|
{$endif}
|
|
|
|
{$if defined(CPU386) or defined(CPUX86_64)}
|
|
Set8087CW($133f);
|
|
SetSSECSR($1f80);
|
|
{$endif}
|
|
|
|
//FormDropFiles fix for win7, win8 and later (window message filter update)
|
|
{$ifdef windows}
|
|
if (WindowsVersion>=wv7) and assigned(ChangeWindowMessageFilter) then
|
|
try
|
|
//WM_COPYGLOBALDATA = 73; MSGFLT_ADD = 1
|
|
ChangeWindowMessageFilter(73, 1);
|
|
ChangeWindowMessageFilter(WM_DROPFILES, 1);
|
|
except;
|
|
end;
|
|
{$endif}
|
|
|
|
LuaFiles := TLuaFileList.Create;
|
|
LuaForms := TList.Create;
|
|
try
|
|
LUA_DoScript('package.path = package.path .. [[;' + tablesdir + '\?.lua]]');
|
|
except
|
|
OutputDebugString('LUA_DoScript failure: package.path');
|
|
end;
|
|
|
|
InternalLuaFiles := TLuaFileList.Create;
|
|
|
|
rs := TResourceStream.Create(HInstance, 'BUILDIN_ACTIVATE', RT_RCDATA);
|
|
InternalLuaFiles.Add(TLuaFile.Create('Activate', rs));
|
|
freeandnil(rs);
|
|
|
|
|
|
rs := TResourceStream.Create(HInstance, 'BUILDIN_DEACTIVATE', RT_RCDATA);
|
|
InternalLuaFiles.Add(TLuaFile.Create('Deactivate', rs));
|
|
freeandnil(rs);
|
|
|
|
|
|
dir:=cereg.readString('Initial tables dir');
|
|
if dir='' then dir:=tablesdir;
|
|
|
|
SaveDialog1.InitialDir:=dir;
|
|
OpenDialog1.InitialDir:=dir;
|
|
|
|
|
|
|
|
|
|
|
|
// if FileExists();
|
|
s:=ChangeFileExt(application.exename,'.DBG');
|
|
if FileExists(s) then
|
|
begin
|
|
createlog:=true;
|
|
cedebugsymbolspresent:=true;
|
|
end
|
|
else
|
|
createlog:=false;
|
|
|
|
miEnableLCLDebug.Checked:=createlog;
|
|
|
|
if miEnableLCLDebug.Checked then
|
|
EnableLCLClick(miEnableLCLDebug);
|
|
|
|
|
|
application.OnHelp := @onhelp;
|
|
|
|
|
|
|
|
Forms.Application.ShowButtonGlyphs := sbgNever;
|
|
application.OnException := @exceptionhandler;
|
|
{$ifdef windows}
|
|
errormode := SetErrorMode(0);
|
|
setErrorMode(errormode or SEM_FAILCRITICALERRORS or SEM_NOOPENFILEERRORBOX);
|
|
{$endif}
|
|
|
|
|
|
frmLuaTableScript := TfrmAutoInject.Create(self);
|
|
frmLuaTableScript.ScriptMode := smLua;
|
|
|
|
frmLuaTableScript.Caption := rsLuaScriptCheatTable;
|
|
frmLuaTableScript.Save1.OnClick := miSave.onclick;
|
|
frmLuaTableScript.SaveAs1.OnClick:= save1.OnClick;
|
|
frmLuaTableScript.Name := 'frmLuaTableScript';
|
|
|
|
|
|
hotkeypressed := -1;
|
|
|
|
|
|
|
|
tokenhandle := 0;
|
|
{$ifdef windows}
|
|
if ownprocesshandle <> 0 then
|
|
begin
|
|
if OpenProcessToken(ownprocesshandle, TOKEN_QUERY or TOKEN_ADJUST_PRIVILEGES,
|
|
tokenhandle) then
|
|
begin
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
|
|
if lookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
if not AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp),
|
|
prev, returnlength) then
|
|
ShowMessage(rsFailureSettingTheDebugPrivilege);
|
|
end;
|
|
|
|
if lookupPrivilegeValue(nil, 'SeTcbPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
if not AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp),
|
|
prev, returnlength) then
|
|
ShowMessage(rsFailureSettingTheSeTcbPrivilegePrivilege);
|
|
end;
|
|
|
|
if lookupPrivilegeValue(nil, 'SeTcbPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
if not AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp),
|
|
prev, returnlength) then
|
|
ShowMessage(rsFailureSettingTheSeTcbPrivilegePrivilege);
|
|
end;
|
|
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
if lookupPrivilegeValue(nil, SE_LOAD_DRIVER_NAME, tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
if not AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp),
|
|
prev, returnlength) then
|
|
ShowMessage(rsFailureSettingTheLoadDriverPrivilege);
|
|
end;
|
|
|
|
|
|
|
|
|
|
if GetSystemType >= 7 then
|
|
begin
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
if lookupPrivilegeValue(nil, 'SeCreateGlobalPrivilege',
|
|
tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
if not AdjustTokenPrivileges(tokenhandle, False, tp,
|
|
sizeof(tp), prev, returnlength) then
|
|
ShowMessage(rsFailureSettingTheCreateGlobalPrivilege);
|
|
end;
|
|
|
|
|
|
|
|
{$ifdef cpu64}
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
|
|
if lookupPrivilegeValue(nil, SE_LOCK_MEMORY_NAME, tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
|
|
end;
|
|
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeIncreaseWorkingSetPrivilege',
|
|
tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
end;
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeSecurityPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeTakeOwnershipPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeManageVolumePrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeBackupPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeCreatePagefilePrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeShutdownPrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
ZeroMemory(@tp, sizeof(tp));
|
|
ZeroMemory(@prev, sizeof(prev));
|
|
if lookupPrivilegeValue(nil, 'SeRestorePrivilege', tp.Privileges[0].Luid) then
|
|
begin
|
|
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
|
|
tp.PrivilegeCount := 1; // One privilege to set
|
|
AdjustTokenPrivileges(tokenhandle, False, tp, sizeof(tp), prev, returnlength);
|
|
end;
|
|
|
|
|
|
if GetProcessWorkingSetSize(ownprocesshandle, minworkingsize, maxworkingsize) then
|
|
SetProcessWorkingSetSize(ownprocesshandle, 16 * 1024 * 1024, 64 * 1024 * 1024);
|
|
|
|
end;
|
|
|
|
{$endif}
|
|
|
|
|
|
tempbitmap := TBitmap.Create;
|
|
|
|
scanvalue.Text := '';
|
|
|
|
(* removed because it uses symhandler now
|
|
{$ifdef cpu64}
|
|
fromaddress.MaxLength := 16;
|
|
toaddress.MaxLength := 16;
|
|
{$else}
|
|
fromaddress.MaxLength := 8;
|
|
toaddress.MaxLength := 8;
|
|
{$endif}
|
|
*)
|
|
|
|
miResetRange.click;
|
|
|
|
isbit := False;
|
|
{$if defined(CPU386) or defined(CPUX86_64)}
|
|
old8087CW := Get8087CW;
|
|
Set8087CW($133f);
|
|
SetSSECSR($1f80);
|
|
{$endif}
|
|
|
|
|
|
|
|
debugproc := False;
|
|
|
|
//get current screen resolution (when switching back for debug)
|
|
originalwidth := screen.Width;
|
|
originalheight := screen.Height;
|
|
|
|
Memimage := TMemorystream.Create;
|
|
|
|
oldwidth := screen.Width;
|
|
oldheight := screen.Height;
|
|
|
|
ProcessHandler.ProcessHandle := 0;
|
|
|
|
logo.Hint := strClickToGoHome;
|
|
|
|
logo.ShowHint := True;
|
|
|
|
newaddress := 0;
|
|
|
|
VarType.ItemIndex := 3;
|
|
oldvartype := 3;
|
|
|
|
UpdateScantype;
|
|
ScanType.ItemIndex := 0;
|
|
|
|
btnNewScan.Caption := strFirstScan;
|
|
hookedin := False;
|
|
|
|
//allignment fixes for some window style's that mess up with thick borders (like vista)
|
|
differentWidth := logopanel.left - (clientwidth - logopanel.Width);
|
|
btnAddAddressManually.Left := clientwidth - btnAddAddressManually.Width;
|
|
commentbutton.left := clientwidth - commentbutton.Width;
|
|
logopanel.left := clientwidth - logopanel.Width;
|
|
ProgressBar.Width := ProgressBar.Width - differentwidth;
|
|
undoscan.left := undoscan.left - differentwidth;
|
|
|
|
//create object for the auto attach list
|
|
autoattachlist := TStringList.Create;
|
|
autoattachlist.CaseSensitive := False; //set it up as not case sensitive
|
|
autoattachlist.Delimiter := ';';
|
|
|
|
extraautoattachlist := TStringList.Create;
|
|
extraautoattachlist.CaseSensitive := False; //set it up as not case sensitive
|
|
extraautoattachlist.Delimiter := ';';
|
|
extraautoattachlist.Duplicates := dupIgnore;
|
|
|
|
randomize;
|
|
|
|
|
|
|
|
{$ifdef ceasinjectabledll}
|
|
//panel7.Visible:=false;
|
|
sbOpenProcess.Enabled := False;
|
|
processid := getcurrentprocessid;
|
|
processhandle := getcurrentprocess;
|
|
enableGui;
|
|
processlabel.Caption := Inttohex(processid, 8) + ' : ' + rsCurrentProcess;
|
|
{$endif}
|
|
|
|
|
|
|
|
oldhandle := mainform.handle;
|
|
|
|
addresslist := TAddresslist.Create(self);
|
|
addresslist.Width := 500;
|
|
addresslist.Height := 150;
|
|
addresslist.top := 50;
|
|
addresslist.parent := panel1;
|
|
addresslist.PopupMenu := popupmenu2;
|
|
addresslist.OnDropByListview := @AddresslistDropByListview;
|
|
addresslist.OnAutoAssemblerEdit := @AddressListAutoAssemblerEdit;
|
|
addresslist.Align := alClient;
|
|
addresslist.AutoSize:=true;
|
|
|
|
|
|
symhandler.loadCommonModuleList;
|
|
|
|
setlength(x, 7);
|
|
if loadformposition(self, x) then
|
|
begin
|
|
autosize:=false;
|
|
addresslist.headers.Sections[0].Width := x[0];
|
|
addresslist.headers.Sections[1].Width := x[1];
|
|
addresslist.headers.Sections[2].Width := x[2];
|
|
addresslist.headers.Sections[3].Width := x[3];
|
|
addresslist.headers.Sections[4].Width := x[4];
|
|
panel5.Height := x[5];
|
|
foundlist3.columns[0].Width := x[6];
|
|
end;
|
|
|
|
mainform:=self;
|
|
|
|
|
|
|
|
pluginhandler := TPluginhandler.Create;
|
|
|
|
//custom types
|
|
LoadCustomTypesFromRegistry;
|
|
|
|
|
|
{$ifdef windows}
|
|
XInputMessages(true);
|
|
{$endif}
|
|
|
|
luaclass_newClass(luavm, self);
|
|
lua_setglobal(luavm,'MainForm');
|
|
|
|
luaclass_newClass(luavm, addresslist);
|
|
lua_setglobal(luavm,'AddressList');
|
|
|
|
miEnableLCLDebug.checked:=createlog;
|
|
allocsAddToUnexpectedExceptionList:=cereg.readBool('Add Allocated Memory As Watched');
|
|
case cereg.readInteger('Unexpected Breakpoint Behaviour',0) of
|
|
0: UnexpectedExceptionAction:=ueaIgnore;
|
|
1: UnexpectedExceptionAction:=ueaBreak;
|
|
2: UnexpectedExceptionAction:=ueaBreakIfInRegion;
|
|
end;
|
|
|
|
|
|
RecentFiles:=tstringlist.Create;
|
|
cereg.readStrings('Recent Files', RecentFiles);
|
|
|
|
|
|
cbSpeedhack.caption:=rsEnableSpeedHack;
|
|
|
|
|
|
{$ifdef darwin}
|
|
cbDirty:=TCheckBox.create(self);
|
|
cbDirty.parent:=panel2;
|
|
cbDirty.AllowGrayed:=true;
|
|
|
|
cbDirty.AnchorSideTop.Control:=cbCopyOnWrite;
|
|
cbDirty.AnchorSideTop.Side:=asrTop;
|
|
|
|
cbDirty.AnchorSideLeft.Control:=cbExecutable;
|
|
cbDirty.AnchorSideLeft.Side:=asrLeft;
|
|
cbDirty.Caption:=rsModified;
|
|
cbDirty.State:=cbGrayed;
|
|
|
|
mi3d.Visible:=false;
|
|
|
|
cut1.ShortCut:=TextToShortCut('Meta+X');
|
|
copy1.ShortCut:=TextToShortCut('Meta+C');
|
|
paste1.ShortCut:=TextToShortCut('Meta+V');
|
|
menuitem1.ShortCut:=TextToShortCut('Meta+A');
|
|
|
|
miTutorial.Visible:=false;
|
|
menuitem15.Visible:=false;
|
|
|
|
|
|
if MacIsArm64 then
|
|
MenuItem16.visible:=true;
|
|
|
|
cbPresentMemoryOnly.Visible:=false;
|
|
sbClearActiveMemory.visible:=false;
|
|
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.ChangedHandle(Sender: TObject);
|
|
begin
|
|
// memscan.setScanDoneCallback(mainform.handle, wm_scandone);
|
|
|
|
//reset the hotkeys
|
|
hotkeyTargetWindowHandleChanged(oldhandle, mainform.handle);
|
|
oldhandle := mainform.handle;
|
|
end;
|
|
|
|
procedure TMainForm.AddressKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
hexadecimal(key);
|
|
end;
|
|
|
|
procedure TMainForm.FoundListDblClick(Sender: TObject);
|
|
var i: integer;
|
|
begin
|
|
if foundList3.SelCount > 0 then
|
|
begin
|
|
if FoundList3.itemindex<>-1 then
|
|
AddToRecord(FoundList3.ItemIndex)
|
|
else
|
|
begin
|
|
if foundlist3.selected<>nil then
|
|
AddToRecord(FoundList3.selected.Index)
|
|
else
|
|
begin
|
|
if foundList3.Items.Count<100 then
|
|
begin
|
|
for i:=0 to foundList3.items.count-1 do
|
|
if foundlist3.Items[i].Selected then
|
|
AddToRecord(i);
|
|
end
|
|
else
|
|
if foundList3.Items.Count>0 then
|
|
AddToRecord(0);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Browsethismemoryarrea1Click(Sender: TObject);
|
|
var
|
|
b: dword;
|
|
s: string;
|
|
begin
|
|
if (foundlist3.ItemIndex <> -1) then
|
|
begin
|
|
MemoryBrowser.memoryaddress := foundlist.GetAddress(foundlist3.ItemIndex, b, s);
|
|
memorybrowser.Show;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.tLuaGCActiveTimer(Sender: TObject);
|
|
begin
|
|
if (lua_gc(LuaVM,LUA_GCCOUNT,0)<luagc_MinSize) then exit;
|
|
|
|
lua_gc(LuaVM, LUA_GCCOLLECT,0);
|
|
lua_gc(LuaVM, LUA_GCCOLLECT,0);
|
|
end;
|
|
|
|
procedure TMainForm.tLuaGCPassiveTimer(Sender: TObject);
|
|
begin
|
|
lua_gc(LuaVM,LUA_GCSTEP,500);
|
|
end;
|
|
|
|
procedure TMainForm.UpdateTimerTimer(Sender: TObject);
|
|
begin
|
|
try
|
|
if addresslist <> nil then
|
|
addresslist.Refresh;
|
|
|
|
Inc(reinterpretcheck);
|
|
if reinterpretcheck mod 15 = 0 then
|
|
reinterpretaddresses;
|
|
except
|
|
on e: exception do
|
|
begin
|
|
UpdateTimer.Enabled:=false;
|
|
|
|
MessageDlg('UpdateTimer Error:'+e.Message, mtError, [mbok],0);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.FreezeTimerTimer(Sender: TObject);
|
|
var i: integer;
|
|
begin
|
|
try
|
|
if addresslist <> nil then
|
|
addresslist.ApplyFreeze;
|
|
except
|
|
on e:exception do
|
|
begin
|
|
OutputDebugString('FreezeTimerTimer:'+e.Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
//vars for changevalue
|
|
var
|
|
differentsizesanswer: boolean;
|
|
terminatewith0answer: boolean;
|
|
askfordifferentsizesonce: boolean;
|
|
asked: boolean;
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.Browsethismemoryregion1Click(Sender: TObject);
|
|
begin
|
|
if addresslist.selectedrecord <> nil then
|
|
begin
|
|
memorybrowser.hexview.address := addresslist.selectedrecord.GetRealAddress;
|
|
memorybrowser.Show;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Deletethisrecord1Click(Sender: TObject);
|
|
begin
|
|
addresslist.DeleteSelected;
|
|
end;
|
|
|
|
procedure TMainForm.ScanvalueoldKeyPress(Sender: TObject; var Key: char);
|
|
begin
|
|
checkpaste;
|
|
|
|
if key = chr(13) then
|
|
begin
|
|
if btnNextScan.Enabled then
|
|
btnNextScan.Click
|
|
else
|
|
btnNewScan.Click;
|
|
|
|
key := #0;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.Calculatenewvaluepart21Click(Sender: TObject);
|
|
var
|
|
_newaddress: ptrUint;
|
|
calculate: int64;
|
|
i, j, err: integer;
|
|
selectedi: integer;
|
|
|
|
firstispointer: boolean;
|
|
re: string;
|
|
ok: boolean;
|
|
|
|
res: integer;
|
|
|
|
sel: TMemoryRecord;
|
|
tempaddress: ptrUint;
|
|
|
|
updatelist: Tlist;
|
|
tn: TTreenode;
|
|
minlevel: integer; //if the scan for entries goes below this, it means it got outside the current node
|
|
|
|
begin
|
|
if (addresslist.Count = 0) or (addresslist.SelCount=0) then
|
|
exit;
|
|
|
|
|
|
res := -1;
|
|
|
|
//first find out how many where selected.
|
|
i := 0;
|
|
selectedi := addresslist.SelCount;
|
|
|
|
firstispointer := False;
|
|
|
|
sel := addresslist.selectedRecord;
|
|
if sel = nil then
|
|
sel := addresslist[0];
|
|
|
|
|
|
if sel.IsPointer then
|
|
if messagedlg(strSelectedAddressIsAPointer, mtConfirmation, [mbYes, mbNo], 0) <> mrYes then
|
|
exit
|
|
else
|
|
firstispointer := True;
|
|
|
|
|
|
if selectedi > 1 then
|
|
begin
|
|
//see if there are (other) pointers selected
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if (addresslist[i] <> sel) and (addresslist[i].isselected) and
|
|
(addresslist[i].IsPointer) then
|
|
begin
|
|
if firstispointer then
|
|
re := strMorePointers
|
|
else
|
|
re := strMorePointers2;
|
|
|
|
break;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//all addresses
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if (addresslist[i] <> sel) and (addresslist[i].IsPointer) then
|
|
begin
|
|
if firstispointer then
|
|
re := strMorePointers
|
|
else
|
|
re := strMorePointers2;
|
|
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
_newaddress := sel.GetRealAddress;
|
|
if (foundlist3.SelCount > 0) then
|
|
_newaddress := foundlist.GetAddress(foundlist3.ItemIndex);
|
|
|
|
|
|
changeoffset := TChangeOffset.Create(self);
|
|
|
|
changeoffset.FromAddress := sel.getBaseAddress;
|
|
|
|
changeoffset.toAddress := _newaddress;
|
|
if changeoffset.showmodal = mrCancel then
|
|
exit;
|
|
|
|
if changeoffset.error > 0 then
|
|
raise Exception.Create(strNotAValidValue);
|
|
calculate := changeoffset.offset;
|
|
|
|
|
|
|
|
updatelist:=TList.create;
|
|
if (addresslist.SelCount=1) then //recalculate all siblings and their children
|
|
begin
|
|
tn:=addresslist.selectedRecord.treenode.parent;
|
|
if tn=nil then //everything
|
|
begin
|
|
for i:=0 to addresslist.count-1 do
|
|
updatelist.Add(addresslist[i]);
|
|
end
|
|
else
|
|
begin
|
|
//only the siblings and children
|
|
|
|
tn:=tn.Items[0];
|
|
minlevel:=tn.level;
|
|
|
|
while (tn<>nil) and (tn.level>=minlevel) do
|
|
begin
|
|
updatelist.add(tn.data);
|
|
tn:=tn.GetNext;
|
|
end;
|
|
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//recalculate all the selected entries
|
|
for i:=0 to addresslist.count-1 do
|
|
if addresslist[i].isSelected then
|
|
updatelist.add(addresslist[i]);
|
|
end;
|
|
|
|
//now recalculate all the selected entries
|
|
for i:=0 to updatelist.count-1 do
|
|
begin
|
|
if not tmemoryrecord(updatelist[i]).isOffset then
|
|
begin
|
|
tempaddress := tmemoryrecord(updatelist[i]).getBaseAddress;
|
|
Inc(tempaddress, calculate);
|
|
tmemoryrecord(updatelist[i]).interpretableaddress := symhandler.getNameFromAddress(tempaddress, True, True, False);
|
|
end;
|
|
end;
|
|
|
|
freeandnil(updatelist);
|
|
addresslist.ReinterpretAddresses;
|
|
end;
|
|
|
|
procedure TMainForm.btnAddAddressManuallyClick(Sender: TObject);
|
|
var mr: Tmemoryrecord;
|
|
begin
|
|
mr:=addresslist.addAddressManually(lastAdded.Address, lastAdded.vartype, lastAdded.CustomTypeName);
|
|
if mr<>nil then
|
|
begin
|
|
lastAdded.Address:=mr.interpretableaddress; //store the last used string
|
|
lastAdded.vartype:=mr.VarType;
|
|
lastAdded.CustomTypeName:=mr.CustomTypeName;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.ScanTypeChange(Sender: TObject);
|
|
begin
|
|
updatescantype;
|
|
end;
|
|
|
|
procedure TMainForm.Value1Click(Sender: TObject);
|
|
begin
|
|
addresslist.doValueChange;
|
|
end;
|
|
|
|
function TMainForm.convertvalue(ovartype, nvartype: integer; oldvalue: string;
|
|
washexadecimal, ishexadecimal: boolean): string;
|
|
var
|
|
s: string;
|
|
oldvaluei: qword;
|
|
oldvaluef: double absolute oldvaluei;
|
|
oldvalueba: pbyte;
|
|
|
|
newvaluei: qword;
|
|
newvaluef: double absolute newvaluei;
|
|
newvalueba: pbyte;
|
|
|
|
i: integer;
|
|
|
|
ba: TBytes;
|
|
|
|
wasfloat: boolean;
|
|
wasaob: boolean;
|
|
|
|
hasbytes: boolean;
|
|
puretext: boolean;
|
|
begin
|
|
if ovartype = nvartype then
|
|
begin
|
|
Result := oldvalue;
|
|
exit;
|
|
end;
|
|
|
|
Result := '';
|
|
oldvalueba := @oldvaluei;
|
|
newvalueba := @newvaluei;
|
|
|
|
try
|
|
puretext := False;
|
|
wasfloat := False;
|
|
wasaob := False;
|
|
oldvaluei := 0;
|
|
|
|
try
|
|
case ovartype of
|
|
0:
|
|
begin
|
|
//binary
|
|
if rbdec.Checked then
|
|
oldvaluei := StrToQWordEx(scanvalue.Text)
|
|
else
|
|
begin
|
|
s := trim(oldvalue);
|
|
for i := 1 to length(s) do
|
|
if not (s[i] in ['0', '1']) then
|
|
s[i] := '0';
|
|
|
|
oldvaluei := parsers.BinToInt(s);
|
|
end;
|
|
end;
|
|
|
|
1..4:
|
|
begin
|
|
if washexadecimal then
|
|
begin
|
|
oldvaluei := StrToQWordEx('$' + oldvalue);
|
|
end
|
|
else
|
|
oldvaluei := StrToQWordEx(oldvalue);
|
|
end;
|
|
|
|
5, 6, 9:
|
|
begin
|
|
try
|
|
oldvaluei := StrToInt(oldvalue);
|
|
except
|
|
oldvaluef := strtofloat(oldvalue);
|
|
wasfloat := True;
|
|
end;
|
|
end;
|
|
|
|
7: //generic type, text or all
|
|
begin
|
|
try
|
|
oldvaluei := StrToQWordEx(oldvalue);
|
|
except
|
|
oldvaluef := StrToFloat(oldvalue);
|
|
wasfloat := True;
|
|
end;
|
|
|
|
end;
|
|
|
|
8:
|
|
begin //convert the aob to an integer if possible (max 8 bytes)
|
|
//aob
|
|
setlength(ba, 0);
|
|
ConvertStringToBytes(oldvalue, washexadecimal, ba);
|
|
|
|
oldvaluei := 0;
|
|
for i := 0 to min(7, length(ba) - 1) do
|
|
begin
|
|
if ba[i] < 0 then
|
|
ba[i] := 0;
|
|
|
|
oldvalueba[i] := ba[i];
|
|
end;
|
|
|
|
wasaob := True;
|
|
end;
|
|
|
|
else
|
|
begin
|
|
if ovartype>=11 then
|
|
begin
|
|
if washexadecimal then
|
|
begin
|
|
oldvaluei := StrToQWordEx('$' + oldvalue);
|
|
end
|
|
else
|
|
oldvaluei := StrToQWordEx(oldvalue);
|
|
end;
|
|
end;
|
|
end;
|
|
except
|
|
//could not get parsed, if the target is aob then convert the text to an aob, else give up
|
|
if nvartype = 8 then
|
|
puretext := True
|
|
else
|
|
begin
|
|
Result := '';
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
|
|
case nvartype of
|
|
0: //binary
|
|
begin
|
|
if wasfloat then
|
|
oldvaluei := trunc(oldvaluef); //convert the float to an integer
|
|
|
|
if rbdec.Checked then
|
|
Result := IntToStr(oldvaluei)
|
|
else
|
|
Result := parsers.IntToBin(oldvaluei);
|
|
|
|
end;
|
|
|
|
1..4: //integer or custom
|
|
begin
|
|
if wasfloat then
|
|
oldvaluei := trunc(oldvaluef); //convert the float to an integer
|
|
|
|
if ishexadecimal then
|
|
Result := inttohex(oldvaluei, 1)
|
|
else
|
|
Result := IntToStr(oldvaluei);
|
|
end;
|
|
|
|
5..6, 9: //float
|
|
begin
|
|
if wasfloat then
|
|
Result := oldvalue
|
|
else
|
|
begin
|
|
if wasaob then
|
|
begin
|
|
try
|
|
Result := floattostr(oldvaluef);
|
|
except
|
|
|
|
end;
|
|
end
|
|
else
|
|
Result := IntToStr(oldvaluei);
|
|
end;
|
|
end;
|
|
|
|
7:
|
|
begin
|
|
//text
|
|
if wasaob then
|
|
begin
|
|
//convert the aob to text
|
|
s := '';
|
|
//ba should still be intact:
|
|
for i := 0 to length(ba) - 1 do
|
|
begin
|
|
if ba[i] < 0 then
|
|
ba[i] := 0;
|
|
|
|
if ba[i] >= 32 then
|
|
s := s + chr(ba[i])
|
|
else
|
|
s := s + '.';
|
|
|
|
Result := s;
|
|
end;
|
|
end
|
|
else
|
|
Result := oldvalue;
|
|
end;
|
|
|
|
|
|
|
|
8:
|
|
begin
|
|
s := '';
|
|
|
|
if (puretext) then
|
|
begin
|
|
for i := 1 to length(oldvalue) do
|
|
begin
|
|
if ishexadecimal then
|
|
s := s + inttohex(pbyte(@oldvalue[i])^, 2) + ' '
|
|
else
|
|
s := s + IntToStr(pbyte(@oldvalue[i])^) + ' ';
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
|
|
hasbytes := False;
|
|
for i := 7 downto 0 do
|
|
begin
|
|
if hasbytes or (oldvalueba[i] <> 0) then
|
|
begin
|
|
hasBytes := True;
|
|
if ishexadecimal then
|
|
s := inttohex(oldvalueba[i], 2) + ' ' + s
|
|
else
|
|
s := IntToStr(oldvalueba[i]) + ' ' + s;
|
|
end;
|
|
end;
|
|
|
|
trim(s);
|
|
end;
|
|
|
|
|
|
|
|
Result := s;
|
|
end;
|
|
|
|
else
|
|
begin
|
|
if nvartype>=11 then
|
|
begin
|
|
if wasfloat then
|
|
oldvaluei := trunc(oldvaluef); //convert the float to an integer
|
|
|
|
if ishexadecimal then
|
|
Result := inttohex(oldvaluei, 1)
|
|
else
|
|
Result := IntToStr(oldvaluei);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
except
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.createGroupConfigButton;
|
|
begin
|
|
if groupconfigbutton=nil then
|
|
begin
|
|
groupconfigbutton:=Tbutton.create(self);
|
|
groupconfigbutton.Name:='groupconfigbutton';
|
|
groupconfigbutton.caption:=rsMUGenerateGroupscanCommand;
|
|
groupconfigbutton.parent:=scantype.Parent;
|
|
groupconfigbutton.Left:=scantype.left;
|
|
groupconfigbutton.top:=scantype.top;
|
|
groupconfigbutton.width:=scantype.width;
|
|
groupconfigbutton.height:=scantype.height;
|
|
|
|
groupconfigbutton.AnchorSideTop.Side:=asrBottom;
|
|
groupconfigbutton.AnchorSideTop.Control:=scanvalue;
|
|
groupconfigbutton.BorderSpacing.Top:=scantype.top-(scanvalue.Top+scanvalue.Height);
|
|
|
|
groupconfigbutton.AnchorSideLeft.Control:=VarType;
|
|
groupconfigbutton.AnchorSideLeft.Side:=asrLeft;
|
|
groupconfigbutton.AnchorSideRight.Control:=VarType;
|
|
groupconfigbutton.AnchorSideRight.Side:=asrRight;
|
|
|
|
|
|
groupconfigbutton.Anchors:=[akTop, akLeft, akRight];// scantype.anchors;
|
|
|
|
|
|
vartype.AnchorSideTop.Control:=groupconfigbutton;
|
|
panel9.AnchorSideTop.Control:=groupconfigbutton;
|
|
|
|
|
|
groupconfigbutton.OnClick:=@DoGroupconfigButtonClick;
|
|
|
|
foundlist3.BringToFront;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.destroyGroupConfigButton;
|
|
begin
|
|
if groupconfigbutton<>nil then
|
|
begin
|
|
vartype.AnchorSideTop.Control:=ScanType;
|
|
panel9.AnchorSideTop.Control:=ScanType;
|
|
freeandnil(groupconfigbutton);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.VarTypeChange(Sender: TObject);
|
|
var
|
|
a: int64;
|
|
pa: ^int64;
|
|
pb: ^dword;
|
|
b: double;
|
|
d: single;
|
|
i: integer;
|
|
hexvis: boolean;
|
|
decbitvis: boolean;
|
|
hextext: string;
|
|
casevis: boolean;
|
|
|
|
oldscantype: integer;
|
|
temp: string;
|
|
|
|
newvartype: integer;
|
|
unicodevis: boolean;
|
|
tc: tbitmap;
|
|
|
|
alignsize: integer;
|
|
|
|
//----new convertor:
|
|
_oldvartype, _newvartype: integer;
|
|
|
|
washex: boolean;
|
|
oldvalue: string;
|
|
|
|
ct: TCustomType;
|
|
begin
|
|
//todo: rewrite this
|
|
oldscantype := scantype.ItemIndex;
|
|
newvartype := vartype.ItemIndex;
|
|
|
|
_oldvartype := oldvartype;
|
|
_newvartype := newvartype;
|
|
washex := cbHexadecimal.Checked;
|
|
oldvalue := scanvalue.Text;
|
|
|
|
|
|
dontconvert := True;
|
|
|
|
hexvis := True;
|
|
unicodevis := False;
|
|
|
|
hextext := rsHex;
|
|
casevis := False;
|
|
|
|
decbitvis := False;
|
|
ct:=TCustomType(vartype.Items.Objects[vartype.ItemIndex]);
|
|
|
|
if rbFsmAligned.Checked and (not alignsizechangedbyuser) then
|
|
begin
|
|
if ct <> nil then
|
|
begin
|
|
//custom type is ALWAYS the decider
|
|
if rbFsmAligned.Checked then
|
|
edtAlignment.Text := inttohex(ct.preferedAlignment, 1);
|
|
end
|
|
else
|
|
begin
|
|
try
|
|
case newvartype of
|
|
VARTYPE_INDEX_BINARY, VARTYPE_INDEX_BYTE, VARTYPE_INDEX_TEXT, VARTYPE_INDEX_AOB, VARTYPE_INDEX_ALL: alignsize := 1; //byte, aob, string
|
|
VARTYPE_INDEX_WORD: alignsize := 2; //word
|
|
else
|
|
alignsize := 4; //dword, float, single, etc...
|
|
end;
|
|
|
|
if rbFsmAligned.Checked then
|
|
edtAlignment.Text := inttohex(alignsize, 1);
|
|
except
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
oldvartype := vartype.ItemIndex;
|
|
|
|
if not (oldscantype in [smallerthan, biggerthan, valueBetween,
|
|
exact_value, Advanced_Scan]) then
|
|
scantype.ItemIndex := 0;
|
|
|
|
|
|
|
|
if (newvartype in [VARTYPE_INDEX_BYTE, VARTYPE_INDEX_WORD, VARTYPE_INDEX_DWORD, VARTYPE_INDEX_QWORD, VARTYPE_INDEX_ALL]) or (newvartype >= VARTYPE_INDEX_CUSTOMBASE) then //if normal or custom type
|
|
begin
|
|
if (ct<>nil) and (ct.scriptUsesString) then
|
|
begin
|
|
scantype.ItemIndex := 0;
|
|
casevis := True;
|
|
if _oldvartype<>VARTYPE_INDEX_TEXT then
|
|
cbCasesensitive.Checked := True;
|
|
|
|
cbCasesensitive.ShowHint := False;
|
|
cbHexadecimal.Enabled := btnNewScan.Enabled;
|
|
hexvis := False;
|
|
end
|
|
else
|
|
begin
|
|
casevis := False;
|
|
hexvis := True;
|
|
scanvalue.MaxLength := 0;
|
|
cbHexadecimal.Enabled := btnNewScan.Enabled;
|
|
end;
|
|
//cbHexadecimal.Checked:=hexstateForIntTypes;
|
|
end
|
|
else
|
|
|
|
case newvartype of
|
|
VARTYPE_INDEX_BINARY:
|
|
begin //binary
|
|
rbdec.Checked := True;
|
|
cbHexadecimal.Checked := False;
|
|
cbHexadecimal.Visible := False;
|
|
decbitvis := True;
|
|
Scantype.ItemIndex := 0;
|
|
end;
|
|
|
|
VARTYPE_INDEX_SINGLE:
|
|
begin //float;
|
|
casevis := False;
|
|
|
|
cbHexadecimal.Checked := False;
|
|
cbHexadecimal.Enabled := False;
|
|
scanvalue.MaxLength := 0;
|
|
end;
|
|
|
|
VARTYPE_INDEX_DOUBLE:
|
|
begin //double
|
|
hexvis := False;
|
|
temp := scanvalue.Text;
|
|
|
|
|
|
cbHexadecimal.Checked := False;
|
|
cbHexadecimal.Enabled := False;
|
|
scanvalue.MaxLength := 0;
|
|
end;
|
|
|
|
VARTYPE_INDEX_TEXT:
|
|
begin //text
|
|
scantype.ItemIndex := 0;
|
|
casevis := True;
|
|
if _oldvartype<>VARTYPE_INDEX_TEXT then
|
|
cbCasesensitive.Checked := True;
|
|
|
|
cbCasesensitive.ShowHint := False;
|
|
unicodevis := True;
|
|
|
|
cbHexadecimal.Enabled := btnNewScan.Enabled;
|
|
hexvis := False;
|
|
end;
|
|
|
|
VARTYPE_INDEX_AOB:
|
|
begin //array of byte
|
|
scantype.ItemIndex := 0;
|
|
scanvalue.MaxLength := 0;
|
|
cbHexadecimal.Enabled := btnNewScan.Enabled;
|
|
cbHexadecimal.Checked := True;
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
cbHexadecimal.Caption := hextext;
|
|
|
|
//group code (12/4/2011)
|
|
scantype.visible:=newvartype<>10;
|
|
lblscantype.visible:=newvartype<>10;
|
|
|
|
if newvartype=10 then
|
|
begin
|
|
//create groupconfig button
|
|
createGroupConfigButton;
|
|
end
|
|
else
|
|
begin
|
|
//destroy button if it exists
|
|
destroyGroupConfigButton;
|
|
end;
|
|
|
|
|
|
cbHexadecimal.Visible := hexvis;
|
|
rbdec.Visible := decbitvis;
|
|
rbbit.Visible := decbitvis;
|
|
|
|
pnlScanValueOptions.visible:=(cbHexadecimal.Visible or rbDec.visible or rbBit.Visible);
|
|
|
|
|
|
|
|
|
|
cbunicode.Visible := unicodevis;
|
|
cbCodePage.visible:= unicodevis;
|
|
|
|
cbCaseSensitive.Visible := casevis;
|
|
|
|
cbfastscan.Enabled := btnNewScan.Enabled and (not btnNextScan.Enabled);
|
|
//only enabled when btnNewScan is enabled and nextscan not
|
|
|
|
|
|
|
|
UpdateScanType;
|
|
dontconvert := False;
|
|
|
|
//set the old vartype
|
|
oldvartype := vartype.ItemIndex;
|
|
|
|
for i := 0 to panel5.ControlCount - 1 do
|
|
begin
|
|
panel5.Controls[i].Refresh;
|
|
panel5.Controls[i].Repaint;
|
|
panel5.Controls[i].Invalidate;
|
|
end;
|
|
|
|
|
|
if decbitvis then
|
|
cbHexadecimal.Visible := False;
|
|
|
|
scanvalue.Text := convertvalue(_oldvartype, _newvartype, oldvalue,
|
|
washex, cbhexadecimal.Checked);
|
|
|
|
|
|
panel5.OnResize(panel5); //lazarus, force the scantext left
|
|
|
|
|
|
if ScanType.itemindex=-1 then
|
|
ScanType.itemindex:=0; //just in case something has set it to -1
|
|
|
|
if pnlScanValueOptions.visible then
|
|
begin
|
|
if foundlist3.width>pnlScanValueOptions.left then
|
|
foundlist3.width:=foundlist3.width-(foundlist3.width-pnlScanValueOptions.left)-2;
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
procedure TMainForm.LogoClick(Sender: TObject);
|
|
var s: string;
|
|
begin
|
|
s:=format('http://www.cheatengine.org/?referredby=CE%.2f',[ceversion]);
|
|
if messagedlg(rsDoYouWantToGoToTheCheatEngineWebsite, mtConfirmation,
|
|
[mbYes, mbNo], 0) = mrYes then
|
|
ShellExecute(0, PChar('open'), PChar(s),
|
|
PChar(''), PChar(''), SW_MAXIMIZE);
|
|
|
|
end;
|
|
|
|
procedure TMainForm.VarTypeDropDown(Sender: TObject);
|
|
begin
|
|
vartype.DropDownCount := vartype.items.Count;
|
|
end;
|
|
|
|
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: boolean);
|
|
begin
|
|
CanClose := mustclose or CheckIfSaved;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.SpeedButton2Click(Sender: TObject);
|
|
begin
|
|
if messagedlg(strdeleteall, mtConfirmation, [mbNo, mbYes], 0) = mrYes then
|
|
addresslist.Clear;
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.AddresslistDropByListview(Sender: TObject;
|
|
node: TTreenode; attachmode: TNodeAttachMode);
|
|
var
|
|
i: integer;
|
|
begin
|
|
|
|
for i := 0 to foundlist3.Items.Count - 1 do
|
|
if foundlist3.Items[i].Selected then
|
|
begin
|
|
try
|
|
AddToRecord(i, node, attachmode);
|
|
except
|
|
end;
|
|
end;
|
|
|
|
if node<>nil then node.Expand(false);
|
|
end;
|
|
|
|
procedure TMainForm.SpeedButton3Click(Sender: TObject);
|
|
begin
|
|
AddresslistDropByListview(addresslist, nil, naAdd);
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.Selectallitems1Click(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
begin
|
|
foundlist3.BeginUpdate;
|
|
try
|
|
|
|
for i := 0 to foundlist3.Items.Count - 1 do
|
|
begin
|
|
//foundlist3.items[i].Selected := True;
|
|
foundlist3.Items[i].Selected := True;
|
|
end;
|
|
finally
|
|
foundlist3.EndUpdate;
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.Freezealladdresses2Click(Sender: TObject);
|
|
begin
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if addresslist.selectedRecord.active then
|
|
addresslist.DeactivateSelected
|
|
else
|
|
addresslist.ActivateSelected;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.PopupMenu2Popup(Sender: TObject);
|
|
|
|
var
|
|
i: integer;
|
|
|
|
//6.0
|
|
selectionCount: integer;
|
|
selectedrecord: TMemoryRecord;
|
|
|
|
begin
|
|
sethotkey1.Caption := rsSetChangeHotkeys;
|
|
|
|
selectedrecord := addresslist.selectedRecord;
|
|
selectionCount := 0;
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if addresslist.MemRecItems[i].isSelected then
|
|
Inc(selectioncount);
|
|
|
|
|
|
miZeroTerminate.Visible := (selectedrecord <> nil) and (selectedrecord.VarType = vtString);
|
|
miZeroTerminate.Checked := (miZeroTerminate.Visible) and
|
|
(selectedrecord.Extra.stringData.ZeroTerminate);
|
|
|
|
DeleteThisRecord1.Visible := (addresslist.selectedRecord <> nil);
|
|
Change1.Visible := (addresslist.selectedrecord <> nil) and
|
|
(not (addresslist.selectedRecord.vartype = vtAutoAssembler));
|
|
address1.visible := (addresslist.selectedrecord <> nil) and (not addresslist.selectedRecord.isGroupHeader or addresslist.selectedRecord.isAddressGroupHeader);
|
|
Type1.visible := (addresslist.selectedrecord <> nil) and (not addresslist.selectedRecord.isGroupHeader);
|
|
Value1.visible := (addresslist.selectedrecord <> nil);
|
|
Smarteditaddresses1.visible := (addresslist.selectedrecord <> nil) and (not addresslist.selectedRecord.isGroupHeader or addresslist.selectedRecord.isAddressGroupHeader);
|
|
|
|
BrowseThisMemoryRegion1.Visible :=(addresslist.selectedRecord <> nil) and (not addresslist.selectedRecord.isGroupHeader or addresslist.selectedRecord.isAddressGroupHeader) and (not (addresslist.selectedRecord.vartype = vtAutoAssembler));
|
|
miDisassemble.Visible:=Browsethismemoryregion1.Visible;
|
|
|
|
ShowAsHexadecimal1.Visible :=
|
|
(addresslist.selectedRecord <> nil) and (addresslist.selectedRecord.VarType in
|
|
[vtByte, vtWord, vtDword, vtQword, vtSingle, vtDouble, vtCustom, vtByteArray]) and
|
|
(not addresslist.selectedRecord.isGroupHeader);
|
|
|
|
|
|
miShowAsSigned.visible:=(addresslist.selectedRecord <> nil) and (not addresslist.selectedRecord.showAsHex) and (addresslist.selectedRecord.VarType<>vtAutoAssembler) and (not addresslist.selectedRecord.isGroupHeader);
|
|
miShowAsSigned.Checked:=(addresslist.selectedRecord <> nil) and (addresslist.selectedrecord.showAsSigned);
|
|
|
|
if (addresslist.selectedRecord <> nil) and (addresslist.selectedrecord.VarType =
|
|
vtBinary) then
|
|
begin
|
|
if addresslist.selectedRecord.Extra.bitData.showasbinary then
|
|
miShowAsBinary.Caption := rsShowAsDecimal
|
|
else
|
|
miShowAsBinary.Caption := rsShowAsBinary;
|
|
|
|
miShowAsBinary.Visible := True;
|
|
end
|
|
else
|
|
miShowAsBinary.Visible := False;
|
|
|
|
|
|
if (addresslist.selectedRecord <> nil) then
|
|
begin
|
|
if not addresslist.selectedRecord.showAsHex then
|
|
ShowAsHexadecimal1.Caption := rsShowAsHexadecimal
|
|
else
|
|
ShowAsHexadecimal1.Caption := rsShowAsDecimal;
|
|
end;
|
|
|
|
|
|
|
|
SetHotkey1.Visible := (addresslist.selectedRecord <> nil);
|
|
if SetHotkey1.visible and addresslist.selectedRecord.hasHotkeys then
|
|
SetHotkey1.caption:=rsSetChangeHotkeys
|
|
else
|
|
SetHotkey1.caption:=rsSetHotkeys;
|
|
|
|
|
|
//6.1: Groupheaders can also have hotkeys (for toggle hotkeys)
|
|
|
|
Freezealladdresses2.Visible := (addresslist.selectedRecord <> nil);
|
|
|
|
Changescript1.Visible := (addresslist.selectedRecord <> nil) and
|
|
(addresslist.selectedrecord.VarType = vtAutoAssembler);
|
|
|
|
miAsyncScript.visible:=Changescript1.Visible;
|
|
if miAsyncScript.visible then
|
|
miAsyncScript.Checked:=addresslist.selectedrecord.Async;
|
|
|
|
n5.Visible := (addresslist.selectedRecord <> nil);
|
|
|
|
Pointerscanforthisaddress1.Visible := BrowseThisMemoryRegion1.Visible;
|
|
|
|
miGeneratePointermap.Visible:=processid<>0;
|
|
|
|
Findoutwhataccessesthisaddress1.Visible := BrowseThisMemoryRegion1.Visible;
|
|
Setbreakpoint1.Visible := BrowseThisMemoryRegion1.Visible;
|
|
|
|
sep1.Visible := BrowseThisMemoryRegion1.Visible;
|
|
Calculatenewvaluepart21.Visible := (addresslist.Count > 0);
|
|
Forcerechecksymbols1.Visible := addresslist.Count > 0;
|
|
|
|
//one extra check for recalculate (don't show it when an aa address is selected)
|
|
if (addresslist.selectedRecord <> nil) and
|
|
(addresslist.selectedRecord.vartype = vtAutoAssembler) then
|
|
Calculatenewvaluepart21.Visible := False;
|
|
|
|
n4.Visible := (addresslist.Count > 0) or (miGeneratePointermap.visible);
|
|
|
|
n1.Visible := True;
|
|
CreateGroup.Visible := True;
|
|
|
|
if (selectedrecord <> nil) and selectedrecord.treenode.HasChildren then
|
|
begin
|
|
miGroupconfig.Visible := True;
|
|
miHideChildren.Checked := moHideChildren in selectedrecord.options;
|
|
miBindActivation.Checked := moActivateChildrenAsWell in selectedrecord.options;
|
|
miBindDeactivation.checked := moDeactivateChildrenAsWell in selectedrecord.options;
|
|
miRecursiveSetValue.Checked := moRecursiveSetValue in selectedrecord.options;
|
|
miAllowCollapse.checked := moAllowManualCollapseAndExpand in selectedrecord.options;
|
|
miManualExpandCollapse.checked := moManualExpandCollapse in selectedrecord.options;
|
|
miAlwaysHideChildren.checked := moAlwaysHideChildren in selectedrecord.options;
|
|
end
|
|
else
|
|
miGroupconfig.Visible := False;
|
|
|
|
miChangeColor.Visible := addresslist.selcount > 0;
|
|
|
|
miUndoValue.Visible := (addresslist.selectedRecord <> nil) and
|
|
(addresslist.selectedRecord.canUndo);
|
|
|
|
miSetDropdownOptions.visible:=addresslist.selcount > 0;
|
|
|
|
miDBVMFindWhatWritesOrAccesses.visible:={$ifdef windows}Findoutwhataccessesthisaddress1.Visible and isDBVMCapable{$else}false{$endif}; //02/24/2019: Most cpu's support EPT/NP now
|
|
sep2.Visible:=miDBVMFindWhatWritesOrAccesses.Visible;
|
|
|
|
miDBVMFindWhatWritesOrAccesses.enabled:={$ifdef windows}DBKLoaded or isRunningDBVM{$else}false{$endif};
|
|
|
|
if (selectedrecord<>nil) and (selectedrecord.VarType=vtAutoAssembler) then
|
|
begin
|
|
miAutoAssembleErrorMessage.visible:=selectedrecord.LastAAExecutionFailed;
|
|
if selectedrecord.LastAAExecutionFailed then
|
|
miAutoAssembleErrorMessage.Caption:='<<'+selectedrecord.LastAAExecutionFailedReason+'>>';
|
|
end
|
|
else
|
|
begin
|
|
miAutoAssembleErrorMessage.visible:=false;
|
|
miAutoAssembleErrorMessage.Caption:='';
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.foundlistpopupPopup(Sender: TObject);
|
|
var bytesize: integer;
|
|
i, last: integer;
|
|
mi: TMenuItem;
|
|
begin
|
|
|
|
Browsethismemoryregioninthedisassembler1.Enabled := Foundlist3.SelCount >= 1;
|
|
|
|
if foundlist3.Items.Count = 0 then
|
|
begin
|
|
Removeselectedaddresses1.Enabled := False;
|
|
Browsethismemoryarrea1.Enabled := False;
|
|
Selectallitems1.Enabled := False;
|
|
end
|
|
else
|
|
begin
|
|
Removeselectedaddresses1.Enabled := True;
|
|
Browsethismemoryarrea1.Enabled := True;
|
|
|
|
Selectallitems1.Enabled := foundlist3.Items.Count < 5000;
|
|
end;
|
|
|
|
if Foundlist3.SelCount > 1 then
|
|
Removeselectedaddresses1.Caption := rsRemoveSelectedAddresses
|
|
else
|
|
Removeselectedaddresses1.Caption := rsRemoveSelectedAddress;
|
|
|
|
if Foundlist3.selcount = 0 then
|
|
begin
|
|
Removeselectedaddresses1.Enabled := False;
|
|
Browsethismemoryarrea1.Enabled := False;
|
|
end
|
|
else
|
|
begin
|
|
Removeselectedaddresses1.Enabled := True;
|
|
Browsethismemoryarrea1.Enabled := True;
|
|
end;
|
|
|
|
if Removeselectedaddresses1.enabled then
|
|
Removeselectedaddresses1.enabled := not (GetVarType in [vtBinary, vtByteArray, vtAll]);
|
|
|
|
miChangeValue.enabled:=Browsethismemoryarrea1.enabled;
|
|
miChangeValueBack.enabled:=Browsethismemoryarrea1.enabled and (PreviousResultList.count>0);
|
|
miAddAddress.enabled:=Browsethismemoryarrea1.enabled;
|
|
|
|
//updatwe the display override
|
|
if memscan<>nil then
|
|
bytesize:=memscan.Getbinarysize div 8
|
|
else
|
|
bytesize:=1; //should never happen
|
|
|
|
MenuItem19.visible:=(foundlist3.Items.Count>0) and (memscan<>nil);
|
|
|
|
miDisplayDefault.visible:=(foundlist3.Items.Count>0) and (memscan<>nil);
|
|
|
|
miDisplayByte.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=1);
|
|
miDisplay2Byte.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=2);
|
|
miDisplay4Byte.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=4);
|
|
miDisplay8Byte.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=8);
|
|
miDisplayFloat.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=4);
|
|
miDisplayDouble.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=8);
|
|
miDisplayHex.visible:=(foundlist3.Items.Count>0) and (memscan<>nil) and (bytesize>=1);
|
|
|
|
// miDisplayHex.caption:
|
|
if foundlist<>nil then
|
|
begin
|
|
if foundlist.isHexadecimal then
|
|
miDisplayHex.caption:=rsDecimal
|
|
else
|
|
miDisplayHex.caption:=rsHexadecimal
|
|
end;
|
|
|
|
|
|
|
|
if (foundlist3.Items.Count>0) and (memscan<>nil) then
|
|
begin
|
|
//populate the list with custom types
|
|
last:=foundlistpopup.Items.IndexOf(miDisplayDouble)+1;
|
|
//first delete the current list (new one could have been added)
|
|
|
|
while foundlistpopup.Items.Count>last do
|
|
foundlistpopup.Items.Delete(last);
|
|
|
|
for i:=0 to customTypes.Count-1 do
|
|
begin
|
|
if TCustomType(customTypes[i]).bytesize<=bytesize then
|
|
begin
|
|
mi:=TMenuItem.Create(foundlistpopup);
|
|
mi.Caption:=TCustomType(customTypes[i]).name;
|
|
mi.RadioItem:=miDisplayDouble.RadioItem;
|
|
mi.AutoCheck:=miDisplayDouble.AutoCheck;
|
|
mi.GroupIndex:=miDisplayDouble.GroupIndex;
|
|
mi.OnClick:=@miChangeDisplayTypeClick;
|
|
mi.tag:=1000+i;
|
|
foundlistpopup.Items.Add(mi);
|
|
|
|
if foundlistDisplayOverride=mi.tag then
|
|
mi.Checked:=true;
|
|
end;
|
|
end;
|
|
|
|
|
|
menuitem14.visible:=(memscan.lastScanWasRegionScan=false) and (memscan.VarType in [vtAll, vtByte, vtWord, vtDword, vtQword, vtSingle, vtDouble]); ;
|
|
miForgotScan.visible:=(memscan.lastScanWasRegionScan=false) and (memscan.VarType in [vtAll, vtByte, vtWord, vtDword, vtQword, vtSingle, vtDouble]); ;
|
|
end
|
|
else
|
|
begin
|
|
menuitem14.visible:=false;
|
|
miForgotScan.visible:=false;
|
|
end;
|
|
|
|
miFlFindWhatAccesses.enabled:=Browsethismemoryarrea1.enabled;
|
|
miFlFindWhatWrites.enabled:=Browsethismemoryarrea1.enabled;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.Removeselectedaddresses1Click(Sender: TObject);
|
|
var
|
|
e, i, j: integer;
|
|
bit: byte;
|
|
selected: array of integer;
|
|
begin
|
|
if SaveFirstScanThread <> nil then
|
|
begin
|
|
SaveFirstScanThread.WaitFor; //wait till it's done
|
|
FreeAndNil(SaveFirstScanThread);
|
|
end;
|
|
|
|
for i:=0 to PreviousResultList.count-1 do
|
|
TSavedScanHandler(PreviousResultList[i]).deinitialize;
|
|
|
|
|
|
if foundlist3.selcount = 1 then //use itemindex (faster)
|
|
begin
|
|
foundlist.deleteaddress(foundlist3.ItemIndex);
|
|
end
|
|
else if foundlist3.selcount > 1 then
|
|
begin
|
|
if foundlist3.items.Count > 100000 then
|
|
if messagedlg(rsThisListIsHuge, mtConfirmation, [mbYes, mbNo], 0) <> mrYes then
|
|
exit;
|
|
|
|
screen.Cursor := crhourglass;
|
|
|
|
//MainForm.Caption := CEWait;
|
|
//Mainform.Refresh;
|
|
|
|
foundlist3.Items.BeginUpdate;
|
|
try
|
|
j := 0;
|
|
setlength(selected, foundlist3.selcount);
|
|
for i := 0 to foundlist3.items.Count - 1 do
|
|
begin
|
|
if foundlist3.items[i].Selected then
|
|
begin
|
|
selected[j] := i;
|
|
Inc(j);
|
|
end;
|
|
end;
|
|
|
|
for i := length(selected) - 1 downto 0 do
|
|
foundlist.deleteaddress(selected[i]);
|
|
|
|
finally
|
|
//Mainform.Caption := CENorm;
|
|
screen.Cursor := crDefault;
|
|
foundlist3.Items.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
foundcount:=foundlist.Reinitialize;
|
|
|
|
for i:=0 to PreviousResultList.count-1 do
|
|
TSavedScanHandler(PreviousResultList[i]).reinitialize;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.FormClose(Sender: TObject; var cAction: TCloseAction);
|
|
var
|
|
i: integer;
|
|
reg: Tregistry;
|
|
crashcounter: integer;
|
|
|
|
h: thandle;
|
|
|
|
|
|
begin
|
|
if SyncSymbols and (processid<>0) then
|
|
SyncSymbolsNow;
|
|
|
|
i:=0;
|
|
while i<screen.CustomFormCount do
|
|
begin
|
|
if (screen.CustomForms[i] is TCEForm) then
|
|
begin
|
|
screen.CustomForms[i].Free;
|
|
end
|
|
else
|
|
inc(i);
|
|
end;
|
|
|
|
{$ifdef windows}
|
|
if adwindow <> nil then
|
|
FreeAndNil(adwindow);
|
|
{$endif}
|
|
|
|
//cleanup the user forms
|
|
if formdesigner <> nil then
|
|
formdesigner.Close;
|
|
|
|
//undo unrandomize
|
|
if unrandomize <> nil then
|
|
FreeAndNil(unrandomize);
|
|
|
|
cbSpeedhack.Checked := False;
|
|
|
|
if flashprocessbutton <> nil then
|
|
begin
|
|
flashprocessbutton.Terminate;
|
|
flashprocessbutton.WaitFor;
|
|
FreeAndNil(FlashProcessButton);
|
|
end;
|
|
{$ifdef windows}
|
|
try
|
|
|
|
if pointer(@DebugActiveProcessStop) <> pointer(@DebugActiveProcessStopProstitute) then
|
|
begin
|
|
//detach the debugger
|
|
//hide;
|
|
crashcounter := 0;
|
|
if advancedoptions <> nil then
|
|
begin
|
|
if advancedoptions.Pausebutton.Down then
|
|
begin
|
|
advancedoptions.Pausebutton.Down := False;
|
|
advancedoptions.Pausebutton.Click;
|
|
end;
|
|
end;
|
|
|
|
|
|
if debuggerthread <> nil then
|
|
begin
|
|
debuggerthread.Terminate;
|
|
debuggerthread.WaitFor;
|
|
debuggerthread.Free;
|
|
debuggerthread := nil;
|
|
end;
|
|
end;
|
|
except
|
|
|
|
end;
|
|
{$endif}
|
|
|
|
if frmProcessWatcher <> nil then
|
|
freeandnil(frmProcessWatcher);
|
|
|
|
try
|
|
if tempbitmap<>nil then
|
|
freeandnil(tempbitmap);
|
|
|
|
shutdown;
|
|
|
|
// unregisterhotkey(handle, 0);
|
|
except
|
|
|
|
end;
|
|
|
|
if advancedoptions <> nil then
|
|
begin
|
|
if advancedoptions.Pausebutton.Down then
|
|
begin
|
|
with advancedoptions do
|
|
begin
|
|
pausebutton.down := not pausebutton.down;
|
|
pausebutton.Click;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if length(windowlist) > 0 then
|
|
begin
|
|
toggleWindow;
|
|
setforegroundwindow(lastforeground);
|
|
setactivewindow(lastactive);
|
|
end;
|
|
|
|
if autoattachlist<>nil then
|
|
FreeAndNil(autoattachlist);
|
|
|
|
|
|
if speedhack <> nil then
|
|
FreeAndNil(speedhack);
|
|
|
|
if pluginhandler <> nil then
|
|
begin
|
|
pluginhandler.free;
|
|
pluginhandler:=nil;
|
|
end;
|
|
|
|
|
|
|
|
if formsettings.cbSaveMemoryregionScanSettings.checked then
|
|
begin
|
|
//save to the registry
|
|
reg:=tregistry.Create;
|
|
try
|
|
Reg.RootKey := HKEY_CURRENT_USER;
|
|
if Reg.OpenKey('\Software\'+strCheatEngine,true) then
|
|
begin
|
|
reg.WriteInteger('scan CopyOnWrite', integer(cbCopyOnWrite.State));
|
|
reg.WriteInteger('scan Executable', integer(cbExecutable.State));
|
|
reg.WriteInteger('scan Writable', integer(cbWritable.State));
|
|
|
|
reg.WriteBool('scan PresentMemoryOnly', cbPresentMemoryOnly.checked);
|
|
end;
|
|
except
|
|
|
|
end;
|
|
|
|
reg.free;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.CommentButtonClick(Sender: TObject);
|
|
begin
|
|
comments.Show;
|
|
end;
|
|
|
|
procedure TMainForm.CopySelectedRecords;
|
|
begin
|
|
clipboard.astext := addresslist.GetTableXMLAsText(True);
|
|
end;
|
|
|
|
procedure TMainForm.paste(simplecopypaste: boolean);
|
|
{
|
|
this routine will paste a entry from the cplipboard into the addresslist of CE
|
|
If simplecopypaste is false frmPasteTableentry is shown to let the user change
|
|
some stuff before adding the new entry
|
|
|
|
returns the entry number of the new addresses (first one)
|
|
}
|
|
var
|
|
s: string;
|
|
begin
|
|
s := clipboard.AsText;
|
|
addresslist.AddTableXMLAsText(s, simplecopypaste);
|
|
end;
|
|
|
|
procedure TMainForm.Copy1Click(Sender: TObject);
|
|
begin
|
|
|
|
copyselectedrecords;
|
|
end;
|
|
|
|
procedure TMainForm.Cut1Click(Sender: TObject);
|
|
begin
|
|
copyselectedrecords;
|
|
addresslist.DeleteSelected(False);
|
|
end;
|
|
|
|
procedure TMainForm.Paste1Click(Sender: TObject);
|
|
begin
|
|
Paste(formsettings.cbsimplecopypaste.Checked);
|
|
end;
|
|
|
|
procedure TMainForm.DBVMFindWhatWritesOrAccesses(address: ptruint);
|
|
var
|
|
res: word;
|
|
id: integer;
|
|
|
|
fcd: TFoundCodeDialog;
|
|
unlockaddress: qword;
|
|
canuseept: boolean;
|
|
|
|
PA: qword;
|
|
begin
|
|
{$ifdef windows}
|
|
if not isRunningDBVM then
|
|
LoadDBK32;
|
|
|
|
canuseept:=hasEPTSupport;
|
|
if (isDBVMCapable=false) then
|
|
begin
|
|
messagedlg(rsRequiresDBVMCapableCPU, mtError, [mbok], 0);
|
|
exit;
|
|
end;
|
|
|
|
if canuseept=false then
|
|
begin
|
|
messagedlg(rsRequiresEPT, mtError, [mbok], 0);
|
|
exit;
|
|
end;
|
|
|
|
if loaddbvmifneeded(rsRequiresDBVMEPT) then
|
|
begin
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if addresslist.selectedRecord.IsPointer then
|
|
begin
|
|
with TformPointerOrPointee.Create(self) do
|
|
begin
|
|
btnFindWhatWritesPointer.Caption := rsFindOutWhatAccessesThisPointer;
|
|
btnFindWhatWritesPointee.Caption := rsFindWhatAccessesTheAddressPointedAtByThisPointer;
|
|
|
|
res := showmodal;
|
|
if res = mrNo then //find what writes to the address pointer at by this pointer
|
|
address := addresslist.selectedRecord.GetRealAddress
|
|
else
|
|
if res = mrYes then
|
|
address := symhandler.getAddressFromName(
|
|
addresslist.selectedRecord.interpretableaddress)
|
|
else
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
//spawn a DBVM watch config screen where the user can select options like lock memory
|
|
if frmDBVMWatchConfig=nil then
|
|
frmDBVMWatchConfig:=TfrmDBVMWatchConfig.create(self);
|
|
|
|
frmDBVMWatchConfig.address:=address;
|
|
|
|
if frmDBVMWatchConfig.showmodal=mrok then
|
|
begin
|
|
|
|
if frmDBVMWatchConfig.LockPage then
|
|
begin
|
|
LoadDBK32; //this does require the driver
|
|
unlockaddress:=LockMemory(processid, address and QWORD($fffffffffffff000),4096)
|
|
end
|
|
else
|
|
unlockaddress:=0;
|
|
|
|
case frmDBVMWatchConfig.watchtype of
|
|
0: id:=dbvm_watch_writes(frmDBVMWatchConfig.PhysicalAddress, addresslist.selectedRecord.bytesize, frmDBVMWatchConfig.Options, frmDBVMWatchConfig.MaxEntries);
|
|
1: id:=dbvm_watch_reads(frmDBVMWatchConfig.PhysicalAddress, addresslist.selectedRecord.bytesize, frmDBVMWatchConfig.Options, frmDBVMWatchConfig.MaxEntries);
|
|
2: id:=dbvm_watch_executes(frmDBVMWatchConfig.PhysicalAddress, addresslist.selectedRecord.bytesize, frmDBVMWatchConfig.Options, frmDBVMWatchConfig.MaxEntries);
|
|
else
|
|
id:=-1;
|
|
end;
|
|
|
|
if (id<>-1) then
|
|
begin
|
|
|
|
//spawn a foundcodedialog
|
|
fcd:=TFoundCodeDialog.Create(self);
|
|
fcd.multipleRip:=frmDBVMWatchConfig.cbMultipleRIP.Checked;
|
|
fcd.debuggerinterfacewatchid:=id;
|
|
fcd.dbvmwatch_unlock:=unlockaddress;
|
|
case frmDBVMWatchConfig.watchtype of
|
|
0: fcd.caption:=Format(rsTheFollowingOpcodesAccessed, [inttohex(address, 8)]);
|
|
1: fcd.caption:=Format(rsTheFollowingOpcodesWriteTo, [inttohex(address, 8)]);
|
|
2: fcd.caption:=Format(rsTheFollowingAddressesExecute, [inttohex(address, 8)]);
|
|
end;
|
|
|
|
|
|
fcd.show;
|
|
end
|
|
else
|
|
begin
|
|
MessageDlg(rsDbvmWatchFailed, mtError, [mbok], 0);
|
|
if unlockaddress<>0 then
|
|
UnlockMemory(unlockaddress);
|
|
end;
|
|
|
|
end;
|
|
freeandnil(frmDBVMWatchConfig);
|
|
|
|
|
|
end;
|
|
end;
|
|
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miDBVMFindWhatWritesOrAccessesClick(Sender: TObject);
|
|
var address: ptruint;
|
|
begin
|
|
address := addresslist.selectedRecord.GetRealAddress;
|
|
DBVMFindWhatWritesOrAccesses(address);
|
|
end;
|
|
|
|
procedure TMainForm.miAlwaysHideChildrenClick(Sender: TObject);
|
|
begin
|
|
miAlwaysHideChildren.Checked := not miAlwaysHideChildren.Checked;
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
if miAlwaysHideChildren.Checked then
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options + [moAlwaysHideChildren]
|
|
else
|
|
addresslist.selectedRecord.options := addresslist.selectedRecord.options - [moAlwaysHideChildren];
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miNetworkClick(Sender: TObject);
|
|
begin
|
|
updateNetworkOptions;
|
|
end;
|
|
|
|
type
|
|
TCEServerOptionMenuItemData=class
|
|
data: TCEServerOption;
|
|
end;
|
|
|
|
TCEServerOptionMenuItemValue=class
|
|
value: string;
|
|
end;
|
|
|
|
procedure TMainForm.updateNetworkOption(sender: TObject);
|
|
var
|
|
mi: TMenuItem absolute sender;
|
|
data: TCEServerOptionMenuItemData;
|
|
value: TCEServerOptionMenuItemValue;
|
|
v: string;
|
|
c: TCEConnection;
|
|
begin
|
|
|
|
if (sender is TMenuItem) then
|
|
begin
|
|
if tobject(mi.tag) is TCEServerOptionMenuItemValue then
|
|
begin
|
|
value:=TCEServerOptionMenuItemValue(mi.tag);
|
|
data:=TCEServerOptionMenuItemData(mi.Parent.Tag);
|
|
|
|
v:=value.value;
|
|
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
c.setOption(data.data.optname, v);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
data:=TCEServerOptionMenuItemData(mi.tag);
|
|
if data.data.optiontype=netBoolean then
|
|
begin
|
|
if mi.checked then v:='1' else v:='0';
|
|
end
|
|
else
|
|
begin
|
|
v:=data.data.currentvalue;
|
|
if InputQuery(rsNetworkOption+data.data.optname, rsChangeValue, v)<>true
|
|
then exit;
|
|
end;
|
|
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
c.setOption(data.data.optname, v);
|
|
data.data.currentvalue:=c.getOption(data.data.optname);
|
|
|
|
mi.OnClick:=nil;
|
|
if data.data.optiontype=netBoolean then
|
|
mi.checked:=data.data.currentvalue='1'
|
|
else
|
|
mi.caption:=data.data.optdescription+' : '+data.data.currentvalue;
|
|
|
|
mi.OnClick:=@updateNetworkOption;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.updateNetworkOptions;
|
|
var
|
|
i,j: integer;
|
|
ol: TCEServerOptions;
|
|
|
|
mi: TMenuItem;
|
|
smi: TMenuItem;
|
|
data: TCEServerOptionMenuItemData;
|
|
value: TCEServerOptionMenuItemValue;
|
|
sl: TStringlist;
|
|
|
|
v: array of string;
|
|
begin
|
|
//fetch the current available ceserver options, and show them in the menu
|
|
while miNetwork.Count>3 do
|
|
begin
|
|
if tobject(miNetwork.items[3].Tag) is TObject then
|
|
TObject(miNetwork.items[3].Tag).free;
|
|
|
|
miNetwork.Items[3].Free;
|
|
end;
|
|
|
|
ol:=[];
|
|
getConnection.getOptions(ol);
|
|
|
|
for i:=0 to length(ol)-1 do
|
|
begin
|
|
mi:=TMenuItem.Create(self);
|
|
mi.Caption:=ol[i].optdescription;
|
|
|
|
data:=TCEServerOptionMenuItemData.create;
|
|
data.data:=ol[i];
|
|
mi.Tag:=ptruint(data);
|
|
|
|
|
|
if ol[i].optiontype=netParent then
|
|
begin
|
|
//nothing else
|
|
end
|
|
else
|
|
begin
|
|
mi.onclick:=@updateNetworkOption;
|
|
if ol[i].optiontype=netBoolean then
|
|
begin
|
|
mi.AutoCheck:=true;
|
|
mi.checked:=ol[i].currentvalue='1';
|
|
end
|
|
else
|
|
begin
|
|
|
|
if ol[i].acceptablevalues<>'' then
|
|
begin
|
|
mi.onclick:=nil;
|
|
//turn the options into subitems
|
|
sl:=TStringList.Create;
|
|
sl.LineBreak:=';';
|
|
sl.Text:=ol[i].acceptablevalues;
|
|
|
|
for j:=0 to sl.Count-1 do
|
|
begin
|
|
v:=sl[j].Split('=');
|
|
value:=TCEServerOptionMenuItemValue.Create;
|
|
value.value:=v[0];
|
|
|
|
smi:=TMenuItem.create(self);
|
|
smi.Caption:=v[1];
|
|
smi.RadioItem:=true;
|
|
smi.GroupIndex:=i+1;
|
|
smi.checked:=ol[i].currentvalue=v[0];
|
|
smi.tag:=ptruint(value);
|
|
smi.AutoCheck:=true;
|
|
|
|
smi.onclick:=@updateNetworkOption;
|
|
|
|
mi.Add(smi);
|
|
end;
|
|
|
|
sl.free;
|
|
end
|
|
else
|
|
mi.caption:=mi.caption+' : '+ol[i].currentvalue;
|
|
end;
|
|
end;
|
|
|
|
if ol[i].parentoptname<>'' then
|
|
begin
|
|
for j:=0 to miNetwork.count-1 do
|
|
begin
|
|
if (tobject(miNetwork.items[j].Tag) is TCEServerOptionMenuItemData) and (TCEServerOptionMenuItemData(miNetwork.items[j].Tag).data.optname=ol[i].parentoptname) then
|
|
begin
|
|
miNetwork.items[j].Add(mi);
|
|
break;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
miNetwork.Add(mi);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miNetworkReadUseProcMemClick(Sender: TObject);
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miOnlyShowCurrentCompareToColumnClick(Sender: TObject);
|
|
begin
|
|
ActivePreviousResultColumn:=ActivePreviousResultColumn;
|
|
cereg.writeBool('Only show current compare column', miOnlyShowCurrentCompareToColumn.Checked);
|
|
|
|
Panel5Resize(nil);
|
|
end;
|
|
|
|
procedure TMainForm.Findoutwhataccessesthisaddress1Click(Sender: TObject);
|
|
var
|
|
address: ptrUint;
|
|
res: word;
|
|
begin
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
address := addresslist.selectedRecord.GetRealAddress;
|
|
if (not startdebuggerifneeded) then
|
|
exit;
|
|
|
|
if addresslist.selectedRecord.IsPointer then
|
|
begin
|
|
with TformPointerOrPointee.Create(self) do
|
|
begin
|
|
btnFindWhatWritesPointer.Caption := rsFindOutWhatAccessesThisPointer;
|
|
btnFindWhatWritesPointee.Caption := rsFindWhatAccessesTheAddressPointedAtByThisPointer;
|
|
|
|
res := showmodal;
|
|
if res = mrNo then //find what writes to the address pointer at by this pointer
|
|
address := addresslist.selectedRecord.GetRealAddress
|
|
else
|
|
if res = mrYes then
|
|
begin
|
|
addresslist.selectedRecord.parseAddressString(addresslist.selectedRecord.interpretableaddress, address);
|
|
end
|
|
else
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
DebuggerThread.FindWhatAccesses(address, addresslist.selectedRecord.bytesize); //byte
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Setbreakpoint1Click(Sender: TObject);
|
|
var
|
|
address: ptrUint;
|
|
res: word;
|
|
begin
|
|
OutputDebugString('Setbreakpoint1Click');
|
|
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
address := addresslist.selectedRecord.GetRealAddress;
|
|
|
|
if (not startdebuggerifneeded) then
|
|
exit;
|
|
|
|
if addresslist.selectedRecord.IsPointer then
|
|
begin
|
|
with TformPointerOrPointee.Create(self) do
|
|
begin
|
|
btnFindWhatWritesPointer.Caption := rsFindOutWhatWritesThisPointer;
|
|
btnFindWhatWritesPointee.Caption := rsFindWhatWritesTheAddressPointedAtByThisPointer;
|
|
|
|
res := showmodal;
|
|
if res = mrNo then //find what writes to the address pointer at by this pointer
|
|
address := addresslist.selectedRecord.GetRealAddress
|
|
else
|
|
if res = mrYes then
|
|
begin
|
|
addresslist.selectedRecord.parseAddressString(addresslist.selectedRecord.interpretableaddress, address);
|
|
end
|
|
else
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
DebuggerThread.FindWhatWrites(address, addresslist.selectedRecord.bytesize);
|
|
|
|
//debug
|
|
//debuggerthread.SetOnWriteBreakpoint(address, addresslist.selectedRecord.bytesize, bpmException);
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.TopDisablerTimer(Sender: TObject);
|
|
begin
|
|
setwindowpos(mainform.Handle, HWND_NOTOPMOST, mainform.left, mainform.top,
|
|
mainform.Width, mainform.Height, SWP_SHOWWINDOW);
|
|
TopDisabler.Enabled := False;
|
|
end;
|
|
|
|
procedure TMainForm.advancedbuttonClick(Sender: TObject);
|
|
begin
|
|
advancedoptions.Show;
|
|
end;
|
|
|
|
procedure TMainForm.cbHexadecimalClick(Sender: TObject);
|
|
var
|
|
x: qword;
|
|
i: integer;
|
|
begin
|
|
|
|
if dontconvert then
|
|
exit;
|
|
|
|
if cbHexadecimal.Checked then
|
|
begin
|
|
//convert what is in scanvalue to hexadecimal notation
|
|
val(scanvalue.Text, x, i);
|
|
case GetVarType of
|
|
vtByte: scanvalue.Text := IntToHex(byte(x), 2);
|
|
vtWord: scanvalue.Text := inttohex(word(x), 4);
|
|
vtDword: scanvalue.Text := inttohex(dword(x), 8);
|
|
vtQword: scanvalue.Text := inttohex(qword(x), 16);
|
|
end;
|
|
|
|
end
|
|
else
|
|
begin
|
|
//convert to decimal notation
|
|
case GetVarType of
|
|
vtByte, vtWord, vtDword, vtQWord:
|
|
begin
|
|
if length(scanvalue.Text) > 0 then
|
|
begin
|
|
if scanvalue.Text[1] = '-' then
|
|
val('-$' + copy(scanvalue.Text, 2, length(scanvalue.Text)), x, i)
|
|
else
|
|
val('$' + scanvalue.Text, x, i);
|
|
|
|
scanvalue.Text := IntToStr(x);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.SetHotkey1Click(Sender: TObject);
|
|
begin
|
|
{ HotKeyForm.recnr:=lastselected;}
|
|
if addresslist.selectedRecord=nil then exit;
|
|
if addresslist.selectedRecord.isBeingEdited then
|
|
exit;
|
|
|
|
with THotKeyForm.Create(self) do
|
|
begin
|
|
memrec := addresslist.selectedRecord;
|
|
if memrec<>nil then
|
|
begin
|
|
memrec.beginEdit;
|
|
Show;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.UndoScanClick(Sender: TObject);
|
|
var
|
|
i, j: integer;
|
|
error: integer;
|
|
a, b: string;
|
|
|
|
begin
|
|
|
|
if (sender=undoscan) or (messagedlg(strConfirmUndo, mtConfirmation, [mbYes, mbNo], 0) = mrYes) then
|
|
begin
|
|
foundlist3.BeginUpdate;
|
|
cleanupPreviousResults;
|
|
|
|
foundlist.Deinitialize;
|
|
memscan.undolastscan;
|
|
foundcount := foundlist.Initialize(getvartype, memscan.CustomType);
|
|
|
|
reloadPreviousResults;
|
|
|
|
undoscan.Enabled := False;
|
|
foundlist3.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.adjustbringtofronttext;
|
|
var
|
|
hk: string;
|
|
reg: TRegistry;
|
|
|
|
begin
|
|
if formsettings.frameHotkeyConfig.cbHideAllWindows.Checked then
|
|
begin
|
|
if allwindowsareback then
|
|
begin
|
|
if onlyfront then
|
|
fronttext := strHideForeground
|
|
else
|
|
fronttext := strHideAll;
|
|
end
|
|
else
|
|
begin
|
|
if onlyfront then
|
|
fronttext := strUnhideForeground
|
|
else
|
|
fronttext := strUnhideAll;
|
|
end;
|
|
|
|
end
|
|
else
|
|
fronttext := rsBringsCheatEngineToFront;
|
|
|
|
|
|
hk:=cereg.readString('BringToFrontHotkey');
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.FormShow(Sender: TObject);
|
|
|
|
|
|
var
|
|
reg: tregistry;
|
|
modifier: dword;
|
|
key: dword;
|
|
hk: string;
|
|
year, month, day: word;
|
|
temp: string;
|
|
|
|
i,j: integer;
|
|
outputfile: textfile;
|
|
go: boolean;
|
|
loadt: boolean;
|
|
|
|
firsttime: boolean;
|
|
x: array of integer;
|
|
|
|
t: tcomponent;
|
|
|
|
|
|
ReferenceControl: TControl;
|
|
ReferenceSide : TAnchorSideReference;
|
|
|
|
c: TControl;
|
|
|
|
logopic: TPicture;
|
|
rs: TResourceStream;
|
|
cleanrun: boolean;
|
|
|
|
{$ifdef windows}
|
|
cbi: TComboboxInfo;
|
|
{$endif}
|
|
extrasize: integer;
|
|
s: string;
|
|
|
|
rname: string;
|
|
begin
|
|
if onetimeonly then
|
|
exit;
|
|
|
|
|
|
|
|
fontmultiplication:=ProcessLabel.Height/15; //normal dpi/font settings have this at 15.
|
|
|
|
screen.HintFont:=font;
|
|
|
|
|
|
onetimeonly := True;
|
|
{$if defined(CPU386) or defined(CPUX86_64)}
|
|
Set8087CW($133f);
|
|
SetSSECSR($1f80);
|
|
{$endif}
|
|
|
|
loadt := False;
|
|
editsh2.Text := format('%.1f', [1.0]);
|
|
|
|
|
|
reg := Tregistry.Create;
|
|
try
|
|
Reg.RootKey := HKEY_CURRENT_USER;
|
|
|
|
if not Reg.OpenKey('\Software\'+strCheatEngine, False) then //can't be opened. Clean install
|
|
begin
|
|
if Reg.OpenKey('\Software\'+strCheatEngine, True) then
|
|
begin
|
|
//write some default data into the registry
|
|
reg.WriteBool('Undo', True);
|
|
reg.writeBool('Advanced', True);
|
|
|
|
reg.WriteInteger('ScanThreadpriority',
|
|
formsettings.combothreadpriority.ItemIndex);
|
|
end;
|
|
end;
|
|
except
|
|
|
|
end;
|
|
|
|
if reg.ValueExists('First Time User') then
|
|
firsttime := reg.ReadBool('First Time User')
|
|
else
|
|
firsttime := True;
|
|
|
|
if firsttime then
|
|
begin
|
|
reg.WriteBool('First Time User', False);
|
|
|
|
|
|
if formsettings.lbLanguages.Count>1 then
|
|
begin
|
|
i:=ShowSelectionList(self, rsLanguage, rsChooseLanguage, formSettings.lbLanguages.Items, s);
|
|
if i<>-1 then
|
|
begin
|
|
formSettings.lbLanguages.ItemIndex:=i;
|
|
formsettings.btnSelectLanguage.Click;
|
|
end;
|
|
end;
|
|
|
|
|
|
if messagedlg(rsTryTutorial, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
|
|
{$ifdef darwin}
|
|
miTutorial64.click;
|
|
{$else}
|
|
{$ifdef cpu32}
|
|
miTutorial.Click;
|
|
{$else}
|
|
miTutorial64.Click;
|
|
{$endif}
|
|
{$endif}
|
|
end;
|
|
|
|
if reg.ValueExists('Show previous value column') then
|
|
begin
|
|
miShowPreviousValue.checked:=reg.ReadBool('Show previous value column');
|
|
miShowPreviousValueClick(miShowPreviousValue);
|
|
end;
|
|
|
|
if reg.ValueExists('Only show current compare column') then
|
|
miOnlyShowCurrentCompareToColumn.checked:=reg.ReadBool('Only show current compare column');
|
|
|
|
|
|
// animatewindow(mainform.Handle,10000,AW_CENTER);
|
|
//mainform.repaint;
|
|
fronttext := rsBringsCheatEngineToFront;
|
|
|
|
if dontrunshow then
|
|
exit;
|
|
|
|
panel7.DoubleBuffered := True;
|
|
flashprocessbutton := tflash.Create(False);
|
|
|
|
|
|
|
|
dontrunshow := True;
|
|
decodedate(now, year, month, day);
|
|
if (month = 7) and (day = 1) then
|
|
ShowMessage(strhappybirthday);
|
|
if (month = 1) and (day = 1) then
|
|
begin
|
|
if reg.ValueExists('ShownHappyNewYear'+inttostr(year))=false then
|
|
begin
|
|
ShowMessage(strnewyear);
|
|
reg.WriteBool('ShownHappyNewYear'+inttostr(year), true);
|
|
end;
|
|
end;
|
|
if (month = 1) and (day = 1) and (year >= 2030) then
|
|
ShowMessage(strFuture);
|
|
|
|
if (month = 4) and (day = 1) then
|
|
aprilfools := True;
|
|
|
|
|
|
//aprilfools:=true;
|
|
{$ifdef windows}
|
|
if aprilfools then //what whould happen if this var is false?
|
|
begin
|
|
if copy(cenorm,1,5)='Cheat' then
|
|
begin
|
|
cenorm[3]:='E';
|
|
cenorm[4]:='A';
|
|
caption:=cenorm;
|
|
end;
|
|
EnableCheatECoinSystem;
|
|
end;
|
|
{$endif}
|
|
|
|
|
|
//Load the table if one was suplied
|
|
overridedebug := False;
|
|
|
|
|
|
if (GetSystemType < 4) {or (is64bitos)} then //not nt or later
|
|
begin
|
|
with formsettings do
|
|
begin
|
|
cbKernelQueryMemoryRegion.Enabled := False;
|
|
cbKernelReadWriteProcessMemory.Enabled := False;
|
|
cbKernelOpenProcess.Enabled := False;
|
|
cbProcessWatcher.Enabled := False;
|
|
cbKDebug.Enabled := False;
|
|
cbGlobalDebug.Enabled := False;
|
|
|
|
TauntOldOsUser.Visible := True;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
vartypechange(vartype);
|
|
adjustbringtofronttext;
|
|
|
|
{
|
|
if aprilfools then
|
|
Caption := cenorm + ' ' + rsEXPIRED + '!';}
|
|
|
|
if autoattachtimer.Enabled then
|
|
autoattachcheck
|
|
else
|
|
AutoAttachThread:=TAutoAttachThread.Create(false);
|
|
|
|
|
|
|
|
|
|
//SMenu:=GetSystemMenu(handle,false);
|
|
cleanrun:=autosize;
|
|
autosize:=false;
|
|
|
|
|
|
memscan := tmemscan.Create(ProgressBar);
|
|
memscan.GuiScanner:=true;
|
|
memscan.OnGuiUpdate:=@MemscanGuiUpdate;
|
|
memscan.OnInitialScanDone:=@MemScanDone;
|
|
memscan.OnScanStart:=@MemScanStart;
|
|
|
|
foundlist := tfoundlist.Create(foundlist3, memscan);
|
|
|
|
|
|
logo.Width:=settingsbutton.width;
|
|
|
|
{$ifdef altname}
|
|
rname:='IMAGES_ALT_CELOGO';
|
|
{$else}
|
|
rname:='IMAGES_CELOGO';
|
|
{$endif}
|
|
|
|
{$ifdef windows}
|
|
{$ifndef altname}
|
|
if logo.Width>=90 then
|
|
{$endif}
|
|
{$endif}
|
|
begin
|
|
rs := TResourceStream.Create(HInstance, rname, RT_RCDATA);
|
|
logopic:=TPicture.Create;
|
|
logopic.LoadFromStreamWithFileExt(rs,'.PNG');
|
|
logo.Picture:=logopic;
|
|
logo.Stretch:=true;
|
|
|
|
|
|
logopic.free;
|
|
freeandnil(rs);
|
|
end;
|
|
|
|
if settingsbutton.Width>logo.Picture.Width then
|
|
logo.Width:=settingsbutton.width;
|
|
|
|
if logo.Width>=80 then
|
|
begin
|
|
rs := TResourceStream.Create(HInstance, rname, RT_RCDATA);
|
|
logopic:=TPicture.Create;
|
|
logopic.LoadFromStreamWithFileExt(rs,'.PNG');
|
|
logo.Picture:=logopic;
|
|
logo.Stretch:=true;
|
|
|
|
|
|
logopic.free;
|
|
freeandnil(rs);
|
|
end;
|
|
|
|
logo.Height:=trunc((logo.Width / logo.picture.Width)*logo.picture.Height);
|
|
|
|
sbOpenProcess.BorderSpacing.Around:=ScaleX(sbOpenProcess.BorderSpacing.Around, 96);
|
|
loadbutton.BorderSpacing.Top:=sbOpenProcess.BorderSpacing.Around;
|
|
|
|
|
|
//because the images have no empty border autosize is out of the question as that makes them hug the border. So, scale them manually
|
|
sbOpenProcess.Width:=scalex(sbOpenProcess.Width, 96);
|
|
sbOpenProcess.Height:=scaley(sbOpenProcess.Height, 96);
|
|
|
|
LoadButton.Width:=scalex(LoadButton.Width, 96);
|
|
LoadButton.Height:=scaley(LoadButton.Height, 96);
|
|
|
|
SaveButton.Width:=scalex(SaveButton.Width, 96);
|
|
SaveButton.Height:=scaley(SaveButton.Height, 96);
|
|
|
|
SpeedButton2.Width:=scalex(SpeedButton2.Width, 96);
|
|
SpeedButton2.Height:=scaley(SpeedButton2.Height, 96);
|
|
|
|
SpeedButton3.Width:=scalex(SpeedButton3.Width, 96);
|
|
SpeedButton3.Height:=scaley(SpeedButton3.Height, 96);
|
|
|
|
|
|
if panel7.Height>ProgressBar.Top+ProgressBar.Height then
|
|
label6.AnchorSideTop.Control:=panel7
|
|
else
|
|
label6.AnchorSideTop.Control:=ProgressBar;
|
|
|
|
|
|
panel5resize(panel5);
|
|
|
|
{$ifdef windows}
|
|
if WindowsVersion>=wvVista then
|
|
begin
|
|
i:=sendmessage(scanvalue.Handle, EM_GETMARGINS, 0,0);
|
|
i:=(i shr 16)+(i and $ffff);
|
|
end
|
|
else
|
|
{$endif}
|
|
i:=8;
|
|
|
|
editSH2.Constraints.MinWidth:=canvas.TextWidth('500.0 ')+i;
|
|
|
|
|
|
edtAlignment.Constraints.MinWidth:=canvas.TextWidth('XXXX');
|
|
edtAlignment.Constraints.MaxWidth:=canvas.TextWidth('XXXXX');
|
|
|
|
panel6.clientheight:=cbPauseWhileScanning.top+cbPauseWhileScanning.height+2;
|
|
gbScanOptions.ClientHeight:=panel6.top+panel6.height+2;
|
|
|
|
fromaddress.font.name:='Courier';
|
|
toaddress.font.name:='Courier';
|
|
i:=GetFontData(font.Handle).Height;
|
|
fromaddress.Font.Height:=i;
|
|
toaddress.Font.Height:=i;
|
|
|
|
if Reg.OpenKey('\Software\'+strCheatEngine+'\FoundList'+darkmodestring, false) then
|
|
begin
|
|
if reg.ValueExists('FoundList.NormalValueColor') then foundlistcolors.NormalValueColor:=reg.ReadInteger('FoundList.NormalValueColor');
|
|
if reg.ValueExists('FoundList.ChangedValueColor') then foundlistcolors.ChangedValueColor:=reg.ReadInteger('FoundList.ChangedValueColor');
|
|
if reg.ValueExists('FoundList.StaticColor') then foundlistcolors.StaticColor:=reg.ReadInteger('FoundList.StaticColor');
|
|
if reg.ValueExists('FoundList.DynamicColor') then foundlistcolors.DynamicColor:=reg.ReadInteger('FoundList.DynamicColor');
|
|
if reg.ValueExists('FoundList.BackgroundColor') then foundlist3.color:=reg.ReadInteger('FoundList.BackgroundColor');
|
|
if reg.ValueExists('FoundList.CompareToHeaderColor') then foundlistcolors.compareToHeadercolor:=reg.ReadInteger('FoundList.CompareToHeaderColor');
|
|
if reg.ValueExists('FoundList.ShowStaticAsStatic') then showStaticAsStatic:=reg.ReadBool('FoundList.ShowStaticAsStatic');
|
|
if reg.ValueExists('FoundList.OverrideFontSize') then AddressListOverrideFontSize:=reg.ReadBool('FoundList.OverrideFontSize');
|
|
|
|
LoadFontFromRegistry(foundlist3.font,reg);
|
|
if not AddressListOverrideFontSize then Foundlist3.Font.Height:=i;
|
|
end
|
|
else
|
|
begin
|
|
foundlistColors.NormalValueColor:=clWindowtext;
|
|
foundlistColors.ChangedValueColor:=clRed;
|
|
foundlistColors.StaticColor:=clGreen;
|
|
foundlistColors.DynamicColor:=clWindowtext;
|
|
foundlistColors.CompareToHeaderColor:=clGreen;
|
|
|
|
showStaticAsStatic:=true;
|
|
Foundlist3.Font.Height:=i;
|
|
end;
|
|
freeandnil(reg);
|
|
|
|
|
|
btnNewScan.autosize:=true;
|
|
btnNextScan.AutoSize:=true;
|
|
btnNewScan.autosize:=false;
|
|
btnNextScan.AutoSize:=false;
|
|
|
|
i:=max(btnNewScan.Width, btnNextScan.Width);
|
|
btnNewScan.width:=i;
|
|
btnNextScan.width:=i;
|
|
|
|
btnAddAddressManually.autosize:=true;
|
|
btnAddAddressManually.autosize:=false;
|
|
btnMemoryView.autosize:=true;
|
|
btnMemoryView.autosize:=false;
|
|
i:=max(btnAddAddressManually.Width, btnMemoryView.Width);
|
|
btnAddAddressManually.width:=i;
|
|
btnMemoryView.width:=i;
|
|
|
|
i:=canvas.TextHeight('ygGxX');
|
|
btnAddAddressManually.ClientHeight:=i+4;
|
|
btnMemoryView.ClientHeight:=i+4;
|
|
|
|
|
|
{$ifdef windows}
|
|
cbi.cbSize:=sizeof(cbi);
|
|
if GetComboBoxInfo(vartype.handle, @cbi) then
|
|
extrasize:=cbi.rcButton.Right-cbi.rcButton.Left+cbi.rcItem.Left
|
|
else
|
|
{$endif}
|
|
extrasize:=16;
|
|
|
|
i:=Canvas.TextWidth(rsMUGenerateGroupscanCommand)+extrasize;
|
|
i:=max(i, Canvas.TextWidth(strExactValue)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strBiggerThan)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strsmallerThan)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strValueBetween)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strUnknownInitialValue)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strIncreasedValue)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strIncreasedValueBy)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strDecreasedValue)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strDecreasedValueBy)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strChangedValue)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strUnchangedValue)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strCompareToLastScan)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strCompareToFirstScan)+extrasize);
|
|
i:=max(i, Canvas.TextWidth(strcompareToSavedScan)+extrasize);
|
|
|
|
vartype.Constraints.MinWidth:=i;
|
|
|
|
i:=foundlist3.width;
|
|
if undoscan.visible and (undoscan.left<btnNextScan.Left+btnNextScan.Width) then
|
|
begin
|
|
j:=(btnNextScan.Left+btnNextScan.Width)-undoscan.left;
|
|
i:=foundlist3.width-j;
|
|
end;
|
|
|
|
pnlFloat.Visible:=true;
|
|
panel9.Constraints.MinWidth:=panel9.Width;
|
|
pnlFloat.Visible:=false;
|
|
|
|
|
|
|
|
pnlScanOptions.Constraints.MinHeight:=gbScanOptions.Top-panel9.top;
|
|
panel10.Constraints.MinWidth:=max(panel14.Width, panel10.Width);
|
|
|
|
pnlScanValueOptions.Constraints.MinHeight:=rbBit.Height+rbDec.height;
|
|
pnlScanValueOptions.Constraints.MinWidth:=max(rbDec.width, rbBit.width);
|
|
|
|
if i>pnlScanValueOptions.left then
|
|
i:=pnlScanValueOptions.left-4;
|
|
|
|
if i>lblValueType.left then
|
|
i:=lblValueType.left-4;
|
|
|
|
if i>gbScanOptions.left then
|
|
i:=gbScanOptions.left-4;
|
|
|
|
if i+speedbutton3.Width>gbScanOptions.left then
|
|
dec(i, (i+speedbutton3.Width)-gbScanOptions.left)
|
|
else
|
|
begin
|
|
gbScanOptions.AnchorSideLeft.Control:=speedbutton3;
|
|
gbScanOptions.AnchorSideLeft.Side:=asrRight;
|
|
gbScanOptions.Anchors:=gbScanOptions.Anchors+[akLeft];
|
|
end;
|
|
|
|
if i<0 then
|
|
begin
|
|
clientwidth:=clientwidth+(-i);
|
|
foundlist3.width:=1;
|
|
end
|
|
else
|
|
foundlist3.width:=i;
|
|
|
|
|
|
|
|
if speedbutton2.top<btnMemoryView.Top then
|
|
foundlist3.AnchorSideBottom.Control:=speedbutton2;
|
|
|
|
|
|
lblcompareToSavedScan.left:=btnNewScan.left-(lblcompareToSavedScan.Width div 2)+((btnNextScan.left+btnNextScan.Width-btnNewScan.left) div 2);
|
|
|
|
ProgressBar.height:=scaley(ProgressBar.height, 96);
|
|
|
|
i:=((logopanel.Top+logopanel.height)-scanvalue.top)+2;
|
|
if i>0 then
|
|
scantext.BorderSpacing.Top:=scantext.BorderSpacing.Top+i;
|
|
|
|
if pnlScanValueOptions.top+pnlScanValueOptions.Height>scanvalue.top+scanvalue.height then
|
|
scantype.AnchorSideTop.Control:=pnlScanValueOptions
|
|
else
|
|
begin
|
|
scantype.AnchorSideTop.Control:=scanvalue;
|
|
scantype.BorderSpacing.Top:=2;
|
|
end;
|
|
|
|
panel9.borderspacing.Top:=(scantype.height div 2)-(cbNot.Height div 2);
|
|
|
|
if cleanrun then //clean setup
|
|
begin
|
|
foundlist3.Column[0].AutoSize:=true;
|
|
foundlist3.Column[1].AutoSize:=true;
|
|
foundlist3.Column[2].AutoSize:=true;
|
|
|
|
j:=max(foundlist3.canvas.textwidth('DDDDDDDDDDDDD'), foundlist3.Column[0].Width);
|
|
|
|
foundlist3.Column[0].AutoSize:=false;
|
|
foundlist3.Column[0].Width:=j;
|
|
|
|
i:=j+foundlist3.Column[1].Width+foundlist3.Column[2].Width ;
|
|
|
|
|
|
foundlist3.Column[1].AutoSize:=false;
|
|
foundlist3.Column[2].AutoSize:=false;
|
|
|
|
if foundlist3.clientWidth<i then
|
|
width:=width+(i-foundlist3.clientWidth);
|
|
|
|
i:=panel5.Height+splitter1.height+addresslist.headers.Height+btnNewScan.Height*4;
|
|
if clientheight<i then
|
|
clientheight:=i;
|
|
|
|
self.position:=poDesigned;
|
|
self.position:=poScreenCenter;
|
|
|
|
i:=addresslist.headers.Canvas.TextWidth(addresslist.headers.Sections[0].Text+' ');
|
|
if i>addresslist.headers.Sections[0].Width then addresslist.headers.Sections[0].Width:=i;
|
|
|
|
i:=max(addresslist.headers.Canvas.TextWidth(addresslist.headers.Sections[1].Text), addresslist.headers.Canvas.TextWidth(strNoDescription));
|
|
if i>addresslist.headers.Sections[1].Width then addresslist.headers.Sections[1].Width:=i;
|
|
|
|
i:=max(addresslist.headers.Canvas.TextWidth(addresslist.headers.Sections[2].Text), addresslist.headers.Canvas.TextWidth('P->DDDDDDDDDDDD'));
|
|
if i>addresslist.headers.Sections[2].Width then addresslist.headers.Sections[2].Width:=i;
|
|
|
|
i:=max(addresslist.headers.Canvas.TextWidth(addresslist.headers.Sections[3].Text), addresslist.headers.Canvas.TextWidth(rs_vtByteArray));
|
|
if i>addresslist.headers.Sections[3].Width then addresslist.headers.Sections[3].Width:=i;
|
|
|
|
|
|
//initial state: focus on the addresslist
|
|
panel5.height:=gbScanOptions.top+gbScanOptions.Height;
|
|
|
|
i:=12*addresslist.Items.Owner.DefaultItemHeight;
|
|
j:=addresslist.height;
|
|
if i>j then
|
|
begin
|
|
i:=clientheight+(i-addresslist.height);
|
|
clientheight:=i;
|
|
end;
|
|
end;
|
|
|
|
panel5.OnResize(panel5);
|
|
|
|
gbScanOptionsChangeBounds(panel5);
|
|
|
|
|
|
btnSetSpeedhack2.AutoSize:=false;
|
|
btnSetSpeedhack2.Height:=btnAddAddressManually.Height;
|
|
|
|
scantype.Anchors:=[akRight];
|
|
scantype.AnchorSideTop.Control:=nil;
|
|
scantype.Anchors:=[akRight, akTop];
|
|
|
|
if not memscan.canWriteResults then
|
|
MessageDlg(Format(rsInvalidScanFolder, [memscan.GetScanFolder]), mtError, [mbOk], 0);
|
|
|
|
// ImageList2.GetBitmap(0);
|
|
|
|
case cereg.readInteger('Last Rounding Type',1) of
|
|
0: rt1.checked:=true;
|
|
1: rt2.checked:=true;
|
|
2: rt3.checked:=true;
|
|
end;
|
|
|
|
ActivePreviousResultColumn:=2;
|
|
|
|
if runningAsAdmin then
|
|
caption:=caption+' (Admin)';
|
|
|
|
askAboutRunningAsAdmin:=true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.rbBitClick(Sender: TObject);
|
|
begin
|
|
|
|
if not isbit then
|
|
begin
|
|
isbit := True;
|
|
//convert the value to a binary value
|
|
try
|
|
if scanvalue.Text = '' then
|
|
scanvalue.Text := '0'
|
|
else
|
|
scanvalue.Text := parsers.inttobin(StrToQWordEx(scanvalue.Text));
|
|
if scanvalue.Text = '' then
|
|
scanvalue.Text := '0';
|
|
except
|
|
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.rbDecClick(Sender: TObject);
|
|
begin
|
|
if isbit then
|
|
begin
|
|
isbit := False;
|
|
//convert the binary text to a decimal representation
|
|
scanvalue.Text := IntToStr(parsers.BinToInt(scanvalue.Text));
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Cut2Click(Sender: TObject);
|
|
var e: TEdit;
|
|
begin
|
|
e:=nil;
|
|
if scanvalue.Focused then e:=scanvalue;
|
|
if (scanvalue2<>nil) and scanvalue2.Focused then e:=scanvalue2;
|
|
if e=nil then exit;
|
|
|
|
if e.SelLength > 0 then
|
|
e.CutToClipboard;
|
|
end;
|
|
|
|
procedure TMainForm.Copy2Click(Sender: TObject);
|
|
var e: tedit;
|
|
begin
|
|
e:=nil;
|
|
if scanvalue.Focused then e:=scanvalue;
|
|
if (scanvalue2<>nil) and scanvalue2.Focused then e:=scanvalue2;
|
|
|
|
if e=nil then exit;
|
|
|
|
if e.SelLength > 0 then
|
|
e.CopyToClipboard;
|
|
end;
|
|
|
|
procedure TMainForm.Paste2Click(Sender: TObject);
|
|
var
|
|
cb: TClipboard;
|
|
i: integer;
|
|
allow: boolean;
|
|
e: tedit;
|
|
begin
|
|
cb := tclipboard.Create;
|
|
try
|
|
if cb.HasFormat(CF_TEXT) then
|
|
begin
|
|
e:=nil;
|
|
if scanvalue.Focused then e:=scanvalue;
|
|
if (scanvalue2<>nil) and scanvalue2.Focused then e:=scanvalue2;
|
|
|
|
if e=nil then exit;
|
|
|
|
e.PasteFromClipboard;
|
|
end;
|
|
finally
|
|
cb.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.checkpaste;
|
|
var
|
|
cb: TClipboard;
|
|
i: integer;
|
|
allow: boolean;
|
|
begin
|
|
cb := tclipboard.Create;
|
|
Paste2.Enabled := cb.HasFormat(CF_TEXT);
|
|
cb.Free;
|
|
end;
|
|
|
|
procedure TMainForm.ccpmenuPopup(Sender: TObject);
|
|
begin
|
|
checkpaste;
|
|
end;
|
|
|
|
procedure TMainForm.Splitter1Moved(Sender: TObject);
|
|
begin
|
|
panel5.Repaint;
|
|
end;
|
|
|
|
procedure TMainForm.SettingsClick(Sender: TObject);
|
|
var
|
|
|
|
oldScanDone, oldInitialScanDone, oldScanStart: TNotifyEvent;
|
|
oldKernelQueryMemoryRegion, oldKernelReadWriteProcessMemory, oldKernelOpenProcess: boolean;
|
|
begin
|
|
|
|
suspendhotkeyhandler;
|
|
|
|
|
|
oldKernelQueryMemoryRegion:=formsettings.cbKernelQueryMemoryRegion.Checked;
|
|
oldKernelReadWriteProcessMemory:=formsettings.cbKernelReadWriteProcessMemory.Checked;
|
|
oldKernelOpenProcess:=formsettings.cbKernelOpenProcess.Checked;
|
|
|
|
if formsettings.ShowModal <> mrOk then
|
|
begin
|
|
resumehotkeyhandler;
|
|
LoadSettingsFromRegistry(true, true);
|
|
exit;
|
|
end;
|
|
|
|
|
|
resumehotkeyhandler;
|
|
|
|
{$ifdef windows}
|
|
|
|
if oldKernelQueryMemoryRegion<>formsettings.cbKernelQueryMemoryRegion.Checked then
|
|
begin
|
|
if formsettings.cbKernelQueryMemoryRegion.Checked then
|
|
UseDBKQueryMemoryRegion
|
|
else
|
|
DontUseDBKQueryMemoryRegion;
|
|
end;
|
|
|
|
if oldKernelReadWriteProcessMemory<>formsettings.cbKernelReadWriteProcessMemory.Checked then
|
|
begin
|
|
if formsettings.cbKernelReadWriteProcessMemory.Checked then
|
|
UseDBKReadWriteMemory
|
|
else
|
|
DontUseDBKReadWriteMemory;
|
|
end;
|
|
|
|
if oldKernelOpenProcess<>formsettings.cbKernelOpenProcess.Checked then
|
|
begin
|
|
if formsettings.cbKernelOpenProcess.Checked then
|
|
UseDBKOpenProcess
|
|
else
|
|
DontUseDBKOpenProcess;
|
|
end;
|
|
{$endif}
|
|
|
|
adjustbringtofronttext;
|
|
|
|
if not btnNextScan.Enabled then
|
|
begin
|
|
//memscan can be reset
|
|
if memscan <> nil then
|
|
begin
|
|
oldScanDone:=memscan.OnScanDone;
|
|
oldScanStart:=memscan.OnScanStart;
|
|
oldInitialScanDone:=memscan.OnInitialScanDone;
|
|
memscan.Free;
|
|
end
|
|
else
|
|
begin
|
|
oldScanDone:=nil;
|
|
oldScanStart:=@MemScanStart;
|
|
oldInitialScanDone:=@MemScanDone;
|
|
end;
|
|
|
|
memscan := tmemscan.Create(ProgressBar);
|
|
memscan.GuiScanner:=true;
|
|
memscan.OnScanStart:=@memscanStart;
|
|
memscan.OnGuiUpdate:=@memscanGuiUpdate;
|
|
memscan.OnScanDone:=oldScanDone;
|
|
memscan.OnScanStart:=oldScanStart;
|
|
memscan.OnInitialScanDone:=oldInitialScanDone;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.cbCaseSensitiveClick(Sender: TObject);
|
|
begin
|
|
cbHexadecimal.Checked := cbcasesensitive.Checked;
|
|
end;
|
|
|
|
procedure TMainForm.LogoMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
begin
|
|
if button = mbright then
|
|
miAbout.click;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.OpenProcesslist1Click(Sender: TObject);
|
|
begin
|
|
sbOpenProcess.Click;
|
|
end;
|
|
|
|
procedure TMainForm.CloseCheatEngine1Click(Sender: TObject);
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TMainForm.Showashexadecimal1Click(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
newstate: boolean;
|
|
begin
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
newstate := not addresslist.selectedRecord.showAsHex;
|
|
|
|
for i := 0 to addresslist.Count - 1 do
|
|
if addresslist[i].isSelected then
|
|
addresslist[i].showAsHex := newstate;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.OpenMemorybrowser1Click(Sender: TObject);
|
|
begin
|
|
btnMemoryView.click;
|
|
end;
|
|
|
|
procedure TMainForm.cbSaferPhysicalMemoryChange(sender: tobject);
|
|
begin
|
|
{$ifdef windows}
|
|
DBK32functions.saferQueryPhysicalMemory:=cbsaferPhysicalMemory.checked;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.cbPauseWhileScanningClick(Sender: TObject);
|
|
|
|
begin
|
|
if (cbPauseWhileScanning.Checked) and (processid = getcurrentprocessid) then
|
|
begin
|
|
cbPauseWhileScanning.Checked := False;
|
|
messagedlg(strdontbother, mtError, [mbOK], 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.ProcessLabelDblClick(Sender: TObject);
|
|
var
|
|
peprocess: dword;
|
|
needed: dword;
|
|
x: dword;
|
|
processInfo: TProcessBasicInformation;
|
|
|
|
buf: PChar;
|
|
begin
|
|
{$ifdef windows}
|
|
if formsettings.cbKernelOpenProcess.Checked then
|
|
begin
|
|
if processid = 0 then
|
|
exit;
|
|
|
|
if not IsValidHandle(processhandle) then
|
|
if messagedlg(rsTheProcessIsnTFullyOpenedIndicatingAInvalidProcess,
|
|
mtWarning, [mbYes, mbNo], 0) <> mrYes then
|
|
exit;
|
|
|
|
peprocess := GetPEProcess(processid);
|
|
ShowMessage('PEProcess=' + IntToHex(peprocess, 8));
|
|
memorybrowser.memoryaddress := peprocess;
|
|
|
|
end;
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.ProcessLabelMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: integer);
|
|
begin
|
|
{$ifdef windows}
|
|
if assigned(newkernelhandler.IsValidHandle) then
|
|
begin
|
|
if (button = mbright) and (DBKLoaded) and newkernelhandler.IsValidHandle(processhandle) then
|
|
begin
|
|
outputdebugstring('(button = mbright) and (DBKLoaded) and IsValidHandle(processhandle)');
|
|
tfrmProcessInfo.Create(self).Show;
|
|
end;
|
|
end
|
|
else
|
|
outputdebugstring('IsValidHandle is unassigned');
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.cbUnrandomizerClick(Sender: TObject);
|
|
begin
|
|
if cbunrandomizer.Checked then
|
|
begin
|
|
if (messagedlg(rsUnrandomizerInfo, mtWarning, [mbYes, mbNo], 0) = mrYes) then
|
|
begin
|
|
unrandomize := tunrandomize.Create(True);
|
|
with unrandomize do
|
|
begin
|
|
|
|
progressbar := tprogressbar.Create(self);
|
|
progressbar.AnchorSideLeft.control:=cbunrandomizer;
|
|
progressbar.AnchorSideLeft.side:=asrLeft;
|
|
|
|
progressbar.AnchorSideRight.control:=cbunrandomizer;
|
|
progressbar.AnchorSideRight.side:=asrRight;
|
|
|
|
progressbar.AnchorSideTop.control:=cbunrandomizer;
|
|
progressbar.AnchorSideTop.side:=asrTop;
|
|
|
|
progressbar.AnchorSideBottom.control:=cbunrandomizer;
|
|
progressbar.AnchorSideBottom.side:=asrBottom;
|
|
|
|
progressbar.Anchors:=[akTop, akLeft, akRight, akBottom];
|
|
|
|
progressbar.parent := self;
|
|
cbunrandomizer.Enabled := False;
|
|
start;
|
|
end;
|
|
end
|
|
else
|
|
cbUnrandomizer.Checked := False;
|
|
end
|
|
else
|
|
begin
|
|
if unrandomize <> nil then
|
|
FreeAndNil(unrandomize);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.cbUnrandomizerMouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: integer);
|
|
begin
|
|
if cbunrandomizer.Checked and (button = mbright) then
|
|
begin
|
|
//show unrandimized addresses
|
|
unrandomize.showaddresses;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.SaveIntialTablesDir(dir: string);
|
|
var
|
|
reg: tregistry;
|
|
begin
|
|
reg := Tregistry.Create;
|
|
try
|
|
Reg.RootKey := HKEY_CURRENT_USER;
|
|
if Reg.OpenKey('\Software\'+strCheatEngine, True) then
|
|
reg.WriteString('Initial tables dir', dir);
|
|
|
|
finally
|
|
reg.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.actOpenExecute(Sender: TObject);
|
|
var
|
|
merge: boolean;
|
|
app: word;
|
|
Extension,oldFileName: string;
|
|
|
|
begin
|
|
|
|
|
|
merge := False;
|
|
if not autoopen then
|
|
if CheckIfSaved = False then
|
|
exit;
|
|
|
|
|
|
oldFileName:=Opendialog1.FileName;
|
|
if autoopen or Opendialog1.Execute then
|
|
begin
|
|
SaveIntialTablesDir(extractfilepath(Opendialog1.filename));
|
|
|
|
autoopen := False;
|
|
Extension := uppercase(extractfileext(opendialog1.filename));
|
|
if (Extension <> '.XML') and
|
|
{(Extension<>'.PTR') and
|
|
(Extension<>'.AMT') and
|
|
(Extension<>'.GH') and
|
|
(Extension<>'.CET') and
|
|
(Extension<>'.CT2') and
|
|
(Extension<>'.CT3') and }
|
|
(Extension <> '.CT') and (Extension <> '.CETRAINER') then
|
|
raise Exception.Create(strUnknownExtension);
|
|
|
|
|
|
if ((addresslist.Count > 0) or (advancedoptions.count > 0) or (DissectedStructs.count>0) ) and
|
|
(Extension <> '.EXE') then
|
|
begin
|
|
app := messagedlg(rsDoYouWishToMergeTheCurrentTableWithThisTable,
|
|
mtConfirmation, mbYesNoCancel, 0);
|
|
case app of
|
|
mrCancel: exit;
|
|
mrYes: merge := True;
|
|
mrNo: merge := False;
|
|
end;
|
|
|
|
end;
|
|
|
|
try
|
|
LoadTable(Opendialog1.filename, merge);
|
|
SaveDialog1.filename:=Opendialog1.filename;
|
|
SaveDialog1.InitialDir:=opendialog1.InitialDir;
|
|
|
|
UserDefinedTableName:=Opendialog1.filename;
|
|
reinterpretaddresses;
|
|
|
|
recentFilesUpdate(Opendialog1.filename);
|
|
except
|
|
on e:exception do
|
|
MessageDlg('This table failed to load: '+e.message,mtError,[mbok],0);
|
|
end;
|
|
end
|
|
else Opendialog1.FileName:=oldFileName;
|
|
|
|
if (advancedoptions <> nil) and (advancedoptions.count>0) then
|
|
advancedoptions.Show;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.actSaveExecute(Sender: TObject);
|
|
var
|
|
protect: boolean;
|
|
oldFileName: string;
|
|
begin
|
|
saveGotCanceled:=true;
|
|
protect := False;
|
|
if (savedialog1.FileName = '') and (opendialog1.filename <> '') then
|
|
begin
|
|
//set the filename the table was opened with to the filename you save as default to
|
|
//and dont forget to change the extension to .CT
|
|
savedialog1.FileName := ChangeFileExt(opendialog1.FileName, '');
|
|
end;
|
|
|
|
|
|
oldFileName:=Savedialog1.FileName;
|
|
if Savedialog1.Execute then
|
|
begin
|
|
if uppercase(ExtractFileExt(savedialog1.FileName)) = '.CETRAINER' then
|
|
protect := MessageDlg(rsDoYouWantToProtectThisTrainerFileFromEditing,
|
|
mtConfirmation, [mbYes, mbNo], 0) = mrYes;
|
|
|
|
savetable(savedialog1.FileName, protect);
|
|
|
|
saveGotCanceled:=false;
|
|
opendialog1.FileName := savedialog1.filename;
|
|
opendialog1.InitialDir:=savedialog1.InitialDir;
|
|
SaveIntialTablesDir(extractfilepath(savedialog1.filename));
|
|
|
|
UserDefinedTableName:=savedialog1.filename;
|
|
|
|
recentFilesUpdate(savedialog1.filename);
|
|
end
|
|
else Savedialog1.FileName:=oldFileName;
|
|
end;
|
|
|
|
procedure TMainForm.actAutoAssembleExecute(Sender: TObject);
|
|
begin
|
|
tfrmautoinject.Create(self).Show;
|
|
end;
|
|
|
|
procedure TMainForm.changeScriptCallback(memrec: TMemoryRecord; script: string; scriptchanged: boolean);
|
|
{
|
|
Gets called when a edit script is done
|
|
}
|
|
begin
|
|
if scriptchanged then
|
|
memrec.AutoAssemblerData.script.Text := script;
|
|
|
|
memrec.endEdit; //release it so the user can delete it if he/she wants to
|
|
end;
|
|
|
|
function TMainForm.AddressListAutoAssemblerEdit(Sender: TObject; memrec: TMemoryRecord): boolean;
|
|
var
|
|
x: TFrmAutoInject;
|
|
y: array of integer;
|
|
begin
|
|
result:=false; //not used
|
|
if memrec.AsyncProcessing then exit;
|
|
|
|
if memrec.isBeingEdited then
|
|
begin
|
|
if memrec.autoAssembleWindow<>nil then
|
|
begin
|
|
if memrec.autoAssembleWindow.WindowState<>wsNormal then
|
|
memrec.autoAssembleWindow.WindowState:=wsNormal;
|
|
|
|
memrec.autoAssembleWindow.show;
|
|
memrec.autoAssembleWindow.BringToFront;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
x := tfrmautoinject.Create(self);
|
|
x.memrec:=memrec;
|
|
with x do
|
|
begin
|
|
//name:='AAEditScript';
|
|
new1.Enabled := False;
|
|
miNewTab.Visible := false;
|
|
|
|
editscript := True;
|
|
editscript2 := True;
|
|
|
|
|
|
memrec.beginEdit;
|
|
memrec.autoAssembleWindow := x;
|
|
callbackroutine := @changeScriptCallback;
|
|
|
|
assemblescreen.Text := memrec.AutoAssemblerData.script.Text;
|
|
|
|
setlength(y, 0);
|
|
loadformposition(x, y);
|
|
|
|
Caption := Format(rsAutoAssembleEdit, [memrec.Description]);
|
|
Show;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miAsyncScriptClick(Sender: TObject);
|
|
begin
|
|
if (addresslist.selectedRecord <> nil) and
|
|
(addresslist.selectedRecord.VarType = vtAutoAssembler) then
|
|
addresslist.selectedRecord.Async:=miAsyncScript.Checked;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.Changescript1Click(Sender: TObject);
|
|
begin
|
|
if (addresslist.selectedRecord <> nil) and
|
|
(addresslist.selectedRecord.VarType = vtAutoAssembler) then
|
|
AddressListAutoAssemblerEdit(addresslist, addresslist.selectedRecord);
|
|
end;
|
|
|
|
procedure TMainForm.Forcerechecksymbols1Click(Sender: TObject);
|
|
begin
|
|
outputdebugstring('Forcerechecksymbols');
|
|
symhandler.reinitialize;
|
|
symhandler.waitforsymbolsloaded;
|
|
// addresslist.needsToReinterpret := True;
|
|
addresslist.reinterpretAddresses;
|
|
end;
|
|
|
|
procedure TMainForm.Edit;
|
|
var
|
|
frmPasteTableentry: TfrmPasteTableentry;
|
|
replace_find: string;
|
|
replace_with: string;
|
|
changeoffsetstring: string;
|
|
changepointerlastoffsetstring: string;
|
|
changeoffset: int64;
|
|
changepointerlastoffset: int64;
|
|
i: integer;
|
|
hasselected: boolean;
|
|
childrenaswell: boolean;
|
|
relativeaswell: boolean;
|
|
checkifrelative: boolean=true;
|
|
s: string;
|
|
begin
|
|
if addresslist.Count = 0 then
|
|
exit;
|
|
|
|
relativeaswell:=false;
|
|
|
|
frmPasteTableentry := TfrmPasteTableentry.Create(self);
|
|
try
|
|
frmPasteTableentry.Caption := rsEditAddresses;
|
|
frmPasteTableentry.Button1.Caption := rsEdit;
|
|
|
|
if frmpastetableentry.showmodal = mrCancel then
|
|
exit;
|
|
replace_find := frmpastetableentry.edtFind.Text;
|
|
replace_with := frmpastetableentry.edtReplace.Text;
|
|
|
|
changeoffsetstring := '$' + stringreplace(frmpastetableentry.edtOffset.Text, '-', '-$', [rfReplaceAll]);
|
|
changeoffsetstring := stringreplace(changeoffsetstring, '$-', '-', [rfReplaceAll]);
|
|
changepointerlastoffsetstring:='$'+stringreplace(frmpastetableentry.edtPointerLastOffset.Text,'-','-$',[rfReplaceAll]);
|
|
changepointerlastoffsetstring:=stringreplace(changepointerlastoffsetstring,'$-','-',[rfReplaceAll]);
|
|
|
|
if not TryStrToInt64(changeoffsetstring,changeoffset) then changeoffset:=0;
|
|
if not TryStrToInt64(changepointerlastoffsetstring,changepointerlastoffset) then changepointerlastoffset:=0;
|
|
|
|
childrenaswell:=frmPasteTableentry.cbChildrenAsWell.checked;
|
|
finally
|
|
frmPasteTableentry.Free;
|
|
end;
|
|
|
|
|
|
hasselected := False;
|
|
for i := 0 to addresslist.Count - 1 do
|
|
begin
|
|
if addresslist[i].isselected then
|
|
begin
|
|
hasselected := True;
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
for i := 0 to addresslist.Count - 1 do
|
|
begin
|
|
if (hasselected and addresslist[i].isSelected) or (not hasselected) then
|
|
begin
|
|
if checkifrelative and (addresslist[i].interpretableaddress<>'') then
|
|
begin
|
|
s:=trim(addresslist[i].interpretableaddress);
|
|
if (s<>'') and (s[1] in ['-','+']) then
|
|
begin
|
|
relativeaswell:=messagedlg(rsAdjustMRwithRelativeAddress, mtConfirmation, [mbyes, mbno], 0) = mryes;
|
|
checkifrelative:=false;
|
|
end;
|
|
end;
|
|
|
|
addresslist[i].adjustAddressby(changeoffset, changepointerlastoffset, childrenaswell, relativeaswell);
|
|
addresslist[i].replaceDescription(replace_find, replace_with, childrenaswell);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Smarteditaddresses1Click(Sender: TObject);
|
|
begin
|
|
edit;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miGeneratePointermapClick(Sender: TObject);
|
|
var
|
|
frmPointerScanner: TfrmPointerScanner;
|
|
oldSettingsForm: tfrmpointerscannersettings;
|
|
begin
|
|
frmPointerScanner := tfrmpointerscanner.Create(self);
|
|
frmPointerScanner.Show;
|
|
|
|
oldSettingsForm:=frmpointerscannersettings;
|
|
|
|
frmpointerscannersettings := tfrmpointerscannersettings.Create(self);
|
|
|
|
if processhandler.is64Bit then
|
|
frmpointerscannersettings.edtReverseStop.text:='00007FFFFFFFFFFF'
|
|
else
|
|
begin
|
|
if Is64bitOS then
|
|
frmpointerscannersettings.edtReverseStop.text:='FFFFFFFF'
|
|
else
|
|
frmpointerscannersettings.edtReverseStop.text:='7FFFFFFF';
|
|
end;
|
|
|
|
frmpointerscannersettings.CbAlligned.checked:=true;
|
|
frmpointerscannersettings.cbConnectToNode.checked:=false;
|
|
|
|
frmpointerscannersettings.rbGeneratePointermap.checked:=true;
|
|
frmpointerscannersettings.btnOk.Click;
|
|
|
|
frmPointerScanner.SkipNextScanSettings:=true;
|
|
frmPointerScanner.Method3Fastspeedandaveragememoryusage1.Click;
|
|
|
|
freeandnil(frmpointerscannersettings);
|
|
|
|
frmpointerscannersettings:=oldSettingsForm;
|
|
end;
|
|
|
|
procedure TMainForm.Pointerscanforthisaddress1Click(Sender: TObject);
|
|
var
|
|
address: ptrUint;
|
|
Count: dword;
|
|
j: integer;
|
|
check: boolean;
|
|
i: integer;
|
|
findpointeroffsets: boolean;
|
|
|
|
frmPointerScanner: TfrmPointerScanner;
|
|
memrec: TMemoryRecord;
|
|
begin
|
|
if addresslist.selectedRecord <> nil then
|
|
begin
|
|
memrec := addresslist.selectedRecord;
|
|
findpointeroffsets := False;
|
|
|
|
|
|
address := memrec.GetRealAddress;
|
|
|
|
|
|
//default
|
|
frmPointerScanner := tfrmpointerscanner.Create(self);
|
|
frmPointerScanner.Show;
|
|
|
|
if frmpointerscannersettings = nil then //used over and over
|
|
frmpointerscannersettings := tfrmpointerscannersettings.Create(self);
|
|
|
|
frmpointerscannersettings.cbAddress.Text := inttohex(address, 8);
|
|
frmpointerscannersettings.cbCompareToOtherPointermaps.Checked:=false;
|
|
frmpointerscannersettings.cbUseLoadedPointermap.checked:=false;
|
|
|
|
if findpointeroffsets then
|
|
begin
|
|
//create and fill in the offset list
|
|
|
|
frmpointerscannersettings.cbMustEndWithSpecificOffset.Checked := True;
|
|
TOffsetEntry(frmpointerscannersettings.offsetlist[0]).offset := memrec.offsets[0].offset;
|
|
|
|
for i := 1 to memrec.offsetcount - 1 do
|
|
begin
|
|
frmpointerscannersettings.btnAddOffset.Click;
|
|
TOffsetEntry(frmpointerscannersettings.offsetlist[i]).offset := memrec.offsets[i].offset;
|
|
end;
|
|
end;
|
|
|
|
frmpointerscannersettings.rbFindAddress.checked:=true;
|
|
frmPointerScanner.Method3Fastspeedandaveragememoryusage1.Click;
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.OnToolsClick(Sender: TObject);
|
|
begin
|
|
shellexecute(0, 'open', PChar(
|
|
formsettings.lvTools.Items[TMenuItem(Sender).Tag].SubItems[0]), nil, nil, SW_SHOW);
|
|
end;
|
|
|
|
procedure TMainForm.plugintype5click(Sender: TObject);
|
|
var
|
|
x: TPluginfunctionType5;
|
|
begin
|
|
x := TPluginfunctionType5(tmenuitem(Sender).Tag);
|
|
if x <> nil then
|
|
x.callback();
|
|
end;
|
|
|
|
procedure TMainForm.plugintype0click(Sender: TObject);
|
|
var
|
|
selectedrecord: PPlugin0_SelectedRecord;
|
|
var
|
|
x: TPluginfunctionType0;
|
|
interpretableaddress: string[255];
|
|
description: string[255];
|
|
i: integer;
|
|
offsets: PDwordArray;
|
|
|
|
a, b, c, d, e, f, g, h, j: dword;
|
|
|
|
t: TVariableType;
|
|
begin
|
|
if addresslist.selectedRecord = nil then
|
|
exit;
|
|
|
|
interpretableaddress := ' ';
|
|
description := ' ';
|
|
|
|
|
|
getmem(selectedrecord, sizeof(TPlugin0_SelectedRecord));
|
|
//fill it with data
|
|
|
|
interpretableaddress := addresslist.selectedRecord.interpretableaddress;
|
|
|
|
selectedrecord^.interpretedaddress := @interpretableaddress[1];
|
|
|
|
selectedrecord^.address := addresslist.selectedRecord.getrealAddress;
|
|
selectedrecord^.ispointer := addresslist.selectedRecord.IsPointer;
|
|
selectedrecord^.countoffsets := addresslist.selectedRecord.offsetCount;
|
|
|
|
getmem(offsets, selectedrecord^.countoffsets * 4); //don't forget to free
|
|
selectedrecord^.offsets := offsets;
|
|
for i := 0 to selectedrecord^.countoffsets - 1 do
|
|
pdword(selectedrecord^.offsets)[i] := addresslist.selectedRecord.offsets[i].offset;
|
|
|
|
description := addresslist.selectedRecord.Description;
|
|
selectedrecord^.description := @description[1];
|
|
|
|
selectedrecord^.valuetype := integer(addresslist.selectedRecord.VarType);
|
|
selectedrecord^.size := addresslist.selectedRecord.bytesize;
|
|
|
|
|
|
|
|
x := TPluginfunctionType0(tmenuitem(Sender).Tag);
|
|
if x <> nil then
|
|
begin
|
|
|
|
interpretableaddress[length(interpretableaddress) + 1] := #0;
|
|
description[length(description) + 1] := #0;
|
|
|
|
if x.callback(selectedrecord) then
|
|
begin
|
|
|
|
interpretableaddress[255] := #0;
|
|
description[255] := #0;
|
|
|
|
pbyte(@interpretableaddress[0])^ := StrLen(@interpretableaddress[1]);
|
|
pbyte(@description[0])^ := StrLen(@description[1]);
|
|
|
|
addresslist.selectedRecord.interpretableaddress := interpretableaddress;
|
|
|
|
addresslist.selectedRecord.Description := description;
|
|
byte(t) := selectedrecord^.valuetype;
|
|
addresslist.selectedRecord.VarType := t;
|
|
|
|
//load back and free memory
|
|
freememandnil(offsets);
|
|
//using my own var instead the user is lame enough to mess up the pointer
|
|
addresslist.selectedRecord.ReinterpretAddress;
|
|
end;
|
|
//showmessage(inttohex(dword(@x.callback),8));
|
|
end;
|
|
|
|
|
|
addresslist.selectedRecord.refresh;
|
|
|
|
end;
|
|
|
|
|
|
//------------------foundlist------------------
|
|
|
|
procedure TMainForm.Foundlist3Data(Sender: TObject; Item: TListItem);
|
|
var
|
|
extra: dword;
|
|
Value, s, PreviousValue: string;
|
|
Address: ptruint;
|
|
addressString: string;
|
|
valuetype: TVariableType;
|
|
|
|
ssVt: TVariableType;
|
|
p: pointer;
|
|
invalid: boolean;
|
|
ct: TCustomType;
|
|
|
|
part: integer;
|
|
error: string;
|
|
|
|
hexadecimal: boolean;
|
|
|
|
PreviousValueList: tstringlist=nil;
|
|
i: integer;
|
|
begin
|
|
//put in data
|
|
ct:=foundlist.CustomType;
|
|
|
|
part:=0;
|
|
|
|
|
|
try
|
|
valuetype:=foundlist.vartype;
|
|
address := foundlist.GetAddress(item.Index, extra, Value);
|
|
|
|
if (address=0) then
|
|
begin
|
|
item.Caption := rsProcessing;
|
|
for i:=1 to foundlist3.ColumnCount-1 do
|
|
item.subitems.add(rsProcessing);
|
|
|
|
exit;
|
|
end;
|
|
|
|
if showStaticAsStatic then
|
|
AddressString:=foundlist.GetModuleNamePlusOffset(item.index)
|
|
else
|
|
AddressString:=inttohex(address,8);
|
|
|
|
|
|
hexadecimal:=foundlist.isHexadecimal;
|
|
|
|
if foundlistDisplayOverride<>0 then
|
|
begin
|
|
if foundlistDisplayOverride=7 then
|
|
hexadecimal:=not hexadecimal
|
|
else
|
|
begin
|
|
case foundlistDisplayOverride of
|
|
1: valuetype:=vtByte;
|
|
2: valuetype:=vtWord;
|
|
3: valuetype:=vtDword;
|
|
4: valuetype:=vtQword;
|
|
5: valuetype:=vtSingle;
|
|
6: valuetype:=vtDouble;
|
|
end;
|
|
hexadecimal:=false;
|
|
end;
|
|
|
|
if foundlistDisplayOverride>=1000 then
|
|
begin
|
|
if (foundlistDisplayOverride-1000)<customTypes.count then
|
|
begin
|
|
|
|
if TCustomType(customTypes[foundlistDisplayOverride-1000]).bytesize<=memscan.Getbinarysize then
|
|
begin
|
|
valuetype:=vtCustom;
|
|
ct:=TCustomType(customTypes[foundlistDisplayOverride-1000]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if valuetype=vtAll then
|
|
value:=readAndParseAddress(address, TVariableType(extra), ct, hexadecimal)
|
|
else
|
|
value:=readAndParseAddress(address, valuetype, ct, hexadecimal);
|
|
end;
|
|
|
|
|
|
PreviousValue:=value;
|
|
|
|
|
|
if foundlist.vartype = vtBinary then //binary
|
|
begin
|
|
AddressString := AddressString + '^' + IntToStr(extra);
|
|
end
|
|
else
|
|
if foundlist.vartype = vtAll then //all
|
|
begin
|
|
if extra >= $1000 then
|
|
begin
|
|
ct:=TCustomType(customTypes[extra - $1000]);
|
|
valuetype:=vtCustom;
|
|
AddressString := AddressString + ':' + ct.Name;
|
|
end
|
|
else
|
|
begin
|
|
valuetype := TVariableType(extra);
|
|
|
|
//here valuetype is stored using the new method
|
|
case valuetype of
|
|
vtByte: AddressString := AddressString + ':1';
|
|
vtWord: AddressString := AddressString + ':2';
|
|
vtDword: AddressString := AddressString + ':4';
|
|
vtQword: AddressString := AddressString + ':8';
|
|
vtSingle: AddressString := AddressString + ':s';
|
|
vtDouble: AddressString := AddressString + ':d';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if miShowPreviousValue.checked and (previousresultlist<>nil) then
|
|
begin
|
|
PreviousValue:='';
|
|
PreviousValueList:=tstringlist.create;
|
|
//get the previous value of this entry
|
|
invalid:=false;
|
|
case foundlist.vartype of
|
|
vtByte: ssVt:=vtbyte;
|
|
vtWord: ssVt:=vtword;
|
|
vtDword: ssVt:=vtdword;
|
|
vtSingle: ssVt:=vtsingle;
|
|
vtDouble: ssVt:=vtdouble;
|
|
vtQword: ssVt:=vtQword;
|
|
vtCustom: ssVt:=vtCustom;
|
|
vtAll: ssVt:=vtall;
|
|
else
|
|
invalid:=true;
|
|
|
|
end;
|
|
|
|
if not invalid then
|
|
begin
|
|
|
|
for i:=0 to PreviousResultList.count-1 do
|
|
begin
|
|
if foundlist3.columns[i+2].Visible then
|
|
begin
|
|
//p:=PreviousResultList[i].getpointertoaddress(address, ssvt, ct);
|
|
|
|
if TSavedScanHandler(PreviousResultList[i]).getStringFromAddress(address, s,hexadecimal,foundlist.isSigned, valuetype, ct)=false then //valuetype and CT are only used if the memscan was a vtAll type
|
|
begin
|
|
if TSavedScanHandler(PreviousResultList[i]).lastFail=1 then
|
|
s:=rsPleaseWait
|
|
else
|
|
s:=rsBusy+' : '+inttostr(TSavedScanHandler(PreviousResultList[i]).lastFail);
|
|
end;
|
|
end
|
|
else
|
|
s:='';
|
|
|
|
previousvaluelist.add(s);
|
|
|
|
{$ifdef darwin}
|
|
if i+2=fActivePreviousResultColumn then
|
|
PreviousValue:=s;
|
|
{$endif}
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
part:=3; //meh
|
|
|
|
{$ifdef darwin}
|
|
//no ownerdraw support for macos listview
|
|
if (previousvalue<>rsPleaseWait) and (value<>previousvalue) then
|
|
value:='* '+value+' *';
|
|
{$endif}
|
|
|
|
|
|
item.Caption := AddressString;
|
|
item.subitems.add(Value);
|
|
if previousvaluelist<>nil then
|
|
begin
|
|
for i:=0 to previousvaluelist.count-1 do
|
|
item.subitems.add(previousvaluelist[i]);
|
|
end;
|
|
|
|
|
|
|
|
|
|
except
|
|
on e: exception do
|
|
begin
|
|
//ShowMessage(IntToStr(item.index));
|
|
|
|
error:=rsCEError+inttostr(item.index)+rsPart+inttostr(part)+':'+e.message;
|
|
|
|
if part in [0,3] then
|
|
begin
|
|
item.Caption:=error;
|
|
item.subitems.add(e.Message);
|
|
item.subitems.add('');
|
|
end;
|
|
|
|
if part=1 then
|
|
begin
|
|
item.Caption := AddressString;
|
|
item.subitems.add(error);
|
|
item.subitems.add(e.Message);
|
|
end;
|
|
|
|
if part=2 then
|
|
begin
|
|
item.Caption := AddressString;
|
|
item.subitems.add(Value);
|
|
item.subitems.add(error);
|
|
end;
|
|
|
|
if PreviousResultList<>nil then
|
|
for i:=1 to PreviousResultList.count-1 do
|
|
item.subitems.add('');
|
|
end;
|
|
end;
|
|
|
|
if previousvaluelist<>nil then
|
|
freeandnil(previousvaluelist);
|
|
end;
|
|
|
|
procedure TMainForm.UpdateFoundlisttimerTimer(Sender: TObject);
|
|
begin
|
|
|
|
if foundlist <> nil then
|
|
foundlist.RefetchValueList;
|
|
end;
|
|
|
|
procedure TMainForm.Foundlist3KeyDown(Sender: TObject; var Key: word;
|
|
Shift: TShiftState);
|
|
var
|
|
i: integer;
|
|
begin
|
|
|
|
foundlistpopupPopup(sender);
|
|
if ((key = Ord('A')) and (ssctrl in Shift) and not (ssalt in Shift)) then
|
|
begin
|
|
//select all
|
|
if foundlist3.Items.Count < 5000 then
|
|
begin
|
|
for i := 0 to foundlist3.items.Count - 1 do
|
|
foundlist3.Items[i].Selected := True;
|
|
|
|
// foundlist3.SelectAll;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.miTutorialClick(Sender: TObject);
|
|
begin
|
|
if not fileexists(cheatenginedir+{$ifdef altname}'rtmtutorial-i386.exe'{$else}'Tutorial-i386.exe'{$endif}) then
|
|
begin
|
|
if fileexists(cheatenginedir+{$ifdef altname}'rtmtutorial-i386.cepack'{$else}'Tutorial-i386.cepack'{$endif}) then
|
|
ceunpackfile(cheatenginedir+{$ifdef altname}'rtmtutorial-i386.cepack'{$else}'Tutorial-i386.cepack'{$endif}, cheatenginedir+{$ifdef altname}'rtmtutorial-i386.exe'{$else}'Tutorial-i386.exe'{$endif}, false);
|
|
end;
|
|
|
|
shellexecute(0, 'open', pchar(cheatenginedir+{$ifdef altname}'rtmtutorial-i386.exe'{$else}'Tutorial-i386.exe'{$endif}), nil, nil, sw_show);
|
|
end;
|
|
|
|
procedure TMainForm.miFlFindWhatAccessesClick(Sender: TObject);
|
|
var
|
|
address: ptrUint;
|
|
res: word;
|
|
begin
|
|
if foundlist3.Selected<>nil then
|
|
begin
|
|
address:=foundlist.GetAddress(foundlist3.Selected.Index);
|
|
if (not startdebuggerifneeded) then
|
|
exit;
|
|
|
|
DebuggerThread.FindWhatAccesses(address, memscan.Getbinarysize div 8);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.miFlFindWhatWritesClick(Sender: TObject);
|
|
var
|
|
address: ptrUint;
|
|
extra: dword;
|
|
res: word;
|
|
begin
|
|
if foundlist3.Selected<>nil then
|
|
begin
|
|
address:=foundlist.GetAddress(foundlist3.Selected.Index);
|
|
if (not startdebuggerifneeded) then
|
|
exit;
|
|
|
|
DebuggerThread.FindWhatWrites(address, memscan.Getbinarysize div 8);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.miSaveFileClick(Sender: TObject);
|
|
begin
|
|
{$ifdef windows}
|
|
if Processwindow = nil then
|
|
ProcessWindow := TProcessWindow.Create(application);
|
|
|
|
if ProcessWindow.opendialog2.Execute then
|
|
Filehandler.CommitChanges(ProcessWindow.opendialog2.filename);
|
|
{$endif}
|
|
end;
|
|
|
|
procedure TMainForm.miChangeValueBackClick(Sender: TObject);
|
|
var
|
|
_currentlySelectedSavedResultname: string;
|
|
s: tstringlist;
|
|
i: integer;
|
|
a: ptruint;
|
|
p: pointer;
|
|
|
|
bytesize: integer;
|
|
x: ptruint;
|
|
|
|
savedscan: TSavedScanHandler;
|
|
begin
|
|
//show a list of possible options. Previous, last scan, savedscan
|
|
if memscan=nil then exit;
|
|
if PreviousResultList.count=0 then exit;
|
|
if GetVarType in [vtBinary, vtByteArray, vtAll, vtGrouped] then exit;
|
|
|
|
bytesize:=memscan.Getbinarysize div 8;
|
|
if bytesize=0 then exit;
|
|
|
|
s:=tstringlist.create();
|
|
|
|
memscan.getsavedresults(s);
|
|
s.insert(0,'Last Scan');
|
|
|
|
i:=ShowSelectionList(self, rsPreviousValueList, rsSelectTheSavedResult, s, currentlySelectedSavedResultname);
|
|
s.free;
|
|
if i=-1 then exit;
|
|
if i=0 then currentlySelectedSavedResultname:='TMP';
|
|
|
|
savedscan:=TSavedScanHandler.create(memscan.getScanFolder, currentlySelectedSavedResultname);
|
|
savedscan.memscan:=memscan;
|
|
savedscan.AllowNotFound:=true;
|
|
savedscan.AllowRandomAccess:=true;
|
|
|
|
try
|
|
{$ifdef darwin}
|
|
a:=foundlist.GetAddress(foundlist3.Selected.Index);
|
|
p:=savedscan.getpointertoaddress(a, memscan.VarType,memscan.CustomType);
|
|
|
|
if p<>nil then
|
|
WriteProcessMemory(processhandle, pointer(a),p,bytesize,x);
|
|
|
|
{$endif}
|
|
|
|
for i:=0 to foundlist3.items.Count-1 do
|
|
begin
|
|
if foundlist3.Items[i].Selected then
|
|
begin
|
|
a:=foundlist.GetAddress(i);
|
|
p:=savedscan.getpointertoaddress(a, memscan.VarType,memscan.CustomType);
|
|
|
|
if p<>nil then
|
|
WriteProcessMemory(processhandle, pointer(a),p,bytesize,x);
|
|
end;
|
|
end;
|
|
finally
|
|
savedscan.free;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.miChangeValueClick(Sender: TObject);
|
|
var
|
|
a:ptruint;
|
|
extra: dword;
|
|
value, newvalue: string;
|
|
i: integer;
|
|
vt: TVariableType;
|
|
customtype: TCustomType;
|
|
begin
|
|
customtype:=nil;
|
|
if foundlist3.Selected<>nil then
|
|
begin
|
|
foundlist.GetAddress(foundlist3.Selected.Index, extra, Value);
|
|
|
|
if InputQuery(rsChangeValue, rsGiveTheNewValueForTheSelectedAddressEs, value) then
|
|
begin
|
|
newvalue:=value;
|
|
|
|
if foundlist.vartype=vtAll then //all, extra contains the vartype
|
|
begin
|
|
if extra<$1000 then
|
|
begin
|
|
vt:=TVariableType(extra);
|
|
end
|
|
else
|
|
begin //custom type
|
|
vt:=vtCustom;
|
|
customtype:=tcustomtype(customTypes[extra-$1000]);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
vt:=foundlist.vartype;
|
|
if vt=vtCustom then
|
|
customtype:=foundlist.CustomType;
|
|
end;
|
|
|
|
if (vt=vtString) and (cbUnicode.checked) then
|
|
vt:=vtUnicodeString;
|
|
|
|
for i:=0 to foundlist3.items.Count-1 do
|
|
begin
|
|
if foundlist3.Items[i].Selected then
|
|
begin
|
|
a:=foundlist.GetAddress(i, extra, Value);
|
|
|
|
ParseStringAndWriteToAddress(newvalue, a, vt, foundlist.isHexadecimal, customtype);
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
var
|
|
_us: string;
|
|
|
|
|
|
|
|
var
|
|
advapi: thandle;
|
|
tu: unicodestring;
|
|
|
|
|
|
|
|
procedure TMainForm.d3dclicktest(_overlayid: integer; x, y: integer);
|
|
var
|
|
w, h: integer;
|
|
begin
|
|
{$ifdef windows}
|
|
w := d3dhook.getwidth;
|
|
h := d3dhook.getheight;
|
|
|
|
ShowMessage(rsOverlay + IntToStr(_overlayid) + rsWasClickedAtPositon +
|
|
IntToStr(x) + ',' + IntToStr(y) + rsWidth + IntToStr(w) + rsHeight + IntToStr(h));
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TMainForm.Browsethismemoryregioninthedisassembler1Click(Sender: TObject);
|
|
var
|
|
a, b: dword;
|
|
s: string;
|
|
begin
|
|
if (foundlist3.ItemIndex <> -1) then
|
|
begin
|
|
memorybrowser.disassemblerview.SelectedAddress :=
|
|
foundlist.GetAddress(foundlist3.ItemIndex, b, s);
|
|
memorybrowser.Show;
|
|
end;
|
|
end;
|
|
|
|
procedure TAutoAttachThread.autoattachcheck;
|
|
begin
|
|
MainForm.autoattachcheck(CurrentProcessList);
|
|
end;
|
|
|
|
constructor TAutoAttachThread.Create(CreateSuspended: boolean);
|
|
begin
|
|
Interval:=2000;
|
|
CurrentProcessList:=TStringList.Create;
|
|
inherited Create(CreateSuspended);
|
|
end;
|
|
|
|
procedure TAutoAttachThread.Execute;
|
|
begin
|
|
while not terminated do
|
|
begin
|
|
if ((MainForm.autoattachlist = nil) or (formsettings = nil) or (MainForm.extraautoattachlist = nil)) or
|
|
((MainForm.autoattachlist.Count+MainForm.extraautoattachlist.Count)<1) or
|
|
((not formsettings.cbAlwaysAutoAttach.Checked) and ((processhandle <> 0) or (processid <> 0))) then
|
|
begin
|
|
sleep(Interval);
|
|
continue;
|
|
end;
|
|
|
|
getprocesslist(CurrentProcessList,false,true);
|
|
synchronize(@autoattachcheck);
|
|
sleep(Interval);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.autoattachcheck(pl: TStringList = nil);
|
|
var
|
|
i, j, k: integer;
|
|
newPID: dword;
|
|
a: string;
|
|
p: string;
|
|
|
|
oldpid: dword;
|
|
oldphandle: thandle;
|
|
attachlist: TStringList;
|
|
begin
|
|
attachlist := TStringList.Create;
|
|
try
|
|
attachlist.AddStrings(autoattachlist);
|
|
attachlist.AddStrings(extraautoattachlist);
|
|
|
|
|
|
if attachlist.Count > 0 then
|
|
begin
|
|
//in case there is no processwatcher this timer will be used to enumerate the processlist every 2 seconds
|
|
if pl=nil then
|
|
begin
|
|
pl := TStringList.Create;
|
|
getprocesslist(pl,false,true);
|
|
end;
|
|
|
|
try
|
|
for i := 0 to attachlist.Count - 1 do
|
|
begin
|
|
a := uppercase(trim(attachlist.Strings[i]));
|
|
for j := pl.Count - 1 downto 0 do //can't do indexof
|
|
begin
|
|
|
|
p := uppercase(pl.strings[j]);
|
|
if pos(a, p) = 10 then
|
|
begin
|
|
//the process is found
|
|
p := '$' + copy(p, 1, 8);
|
|
val(p, newPID, k);
|
|
if k = 0 then
|
|
begin
|
|
if ProcessHandler.processid = newPID then
|
|
exit; //already attached to the newest one
|
|
|
|
if newPID=GetCurrentProcessId then
|
|
continue; //Do not autoattach to self
|
|
|
|
openprocessPrologue;
|
|
|
|
oldpid := ProcessHandler.processid;
|
|
oldphandle := processhandler.processhandle;
|
|
|
|
ProcessHandler.processid := newPID;
|
|
unpause;
|
|
DetachIfPossible;
|
|
|
|
|
|
|
|
MainForm.ProcessLabel.Caption := pl.strings[j];
|
|
Open_Process;
|
|
enablegui(False);
|
|
|
|
openProcessEpilogue('', oldpid, oldphandle, True);
|
|
|
|
symhandler.reinitialize;
|
|
reinterpretaddresses;
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
// pl.IndexOf(autoattachlist.items[i]);
|
|
|
|
finally
|
|
cleanProcessList(pl);
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
finally
|
|
attachlist.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.AutoAttachTimerTimer(Sender: TObject);
|
|
begin
|
|
if (autoattachlist = nil) or (formsettings = nil) or (extraautoattachlist = nil) then
|
|
exit;
|
|
|
|
if (not formsettings.cbAlwaysAutoAttach.Checked) and
|
|
((processhandle <> 0) or (processid <> 0)) then
|
|
exit;
|
|
|
|
autoattachcheck;
|
|
end;
|
|
|
|
|
|
|
|
procedure TMainForm.btnFirstClick(Sender: TObject);
|
|
var
|
|
svalue2: string;
|
|
percentage: boolean;
|
|
fastscanmethod: TFastscanmethod;
|
|
begin
|
|
{$ifdef windows}
|
|
if aprilfools then decreaseCheatECoinCount;
|
|
|
|
QueryPerformanceCounter(scantimestart);
|
|
{$endif}
|
|
|
|
|
|
cleanupPreviousResults;
|
|
|
|
if (memscan=nil) or (foundlist=nil) then raise exception.create(rsUnableToScanFixYourScanSettings);
|
|
|
|
foundlist.Deinitialize; //unlock file handles
|
|
|
|
|
|
|
|
if cbpercentage <> nil then
|
|
percentage := cbpercentage.Checked
|
|
else
|
|
percentage := False;
|
|
|
|
|
|
if btnFirst.tag = 0 then
|
|
begin
|
|
|
|
|
|
ProgressBar.min := 0;
|
|
ProgressBar.max := 1000;
|
|
ProgressBar.position := 0;
|
|
|
|
if scanvalue2 <> nil then
|
|
svalue2 := scanvalue2.Text
|
|
else
|
|
svalue2 := '';
|
|
|
|
lastscantype := scantype.ItemIndex;
|
|
|
|
if cbPauseWhileScanning.Checked then
|
|
begin
|
|
advancedoptions.Pausebutton.down := True;
|
|
advancedoptions.Pausebutton.Click;
|
|
end;
|
|
|
|
case cbWritable.State of
|
|
cbUnchecked: memscan.scanWritable := scanExclude;
|
|
cbChecked: memscan.scanWritable := scanInclude;
|
|
cbGrayed: memscan.scanWritable := scanDontCare;
|
|
end;
|
|
|
|
case cbExecutable.State of
|
|
cbUnchecked: memscan.scanExecutable := scanExclude;
|
|
cbChecked: memscan.scanExecutable := scanInclude;
|
|
cbGrayed: memscan.scanExecutable := scanDontCare;
|
|
end;
|
|
|
|
case cbCopyOnWrite.State of
|
|
cbUnchecked: memscan.scanCopyOnWrite := scanExclude;
|
|
cbChecked: memscan.scanCopyOnWrite := scanInclude;
|
|
cbGrayed: memscan.scanCopyOnWrite := scanDontCare;
|
|
end;
|
|
|
|
{$ifdef darwin}
|
|
case cbDirty.state of
|
|
cbUnchecked: memscan.scanDirty := scanExclude;
|
|
cbChecked: memscan.scanDirty := scanInclude;
|
|
cbGrayed: memscan.scanDirty := scanDontCare;
|
|
end;
|
|
{$endif}
|
|
|
|
if cbfastscan.Checked then
|
|
begin
|
|
if rbFsmAligned.Checked then
|
|
fastscanmethod := fsmAligned
|
|
else
|
|
fastscanmethod := fsmLastDigits;
|
|
end
|
|
else
|
|
fastscanmethod := fsmNotAligned;
|
|
|
|
memscan.floatscanWithoutExponents:=cbFloatSimple.checked;
|
|
memscan.inversescan:=cbNot.Checked and cbnot.Visible;
|
|
|
|
memscan.codePage:=cbCodePage.checked;
|
|
if ScanTabList <> nil then
|
|
ScanTabList.Enabled := False;
|
|
|
|
memscan.luaformula:=cbLuaFormula.visible and cbLuaFormula.checked;
|
|
memscan.NewLuaState:=cbNewLuaState.Checked;
|
|
memscan.busyformIsModal:=true;
|
|
memscan.workingsetonly:=(getConnection=nil) and cbPresentMemoryOnly.checked; //workingsetonly is false when networked
|
|
|
|
memscan.firstscan(GetScanType2, getVarType2, roundingtype,
|
|
scanvalue.Text, svalue2, scanStart, scanStop,
|
|
cbHexadecimal.Checked, rbdec.Checked, cbunicode.Checked, cbCaseSensitive.Checked, fastscanmethod, edtAlignment.Text,
|
|
TCustomType(vartype.items.objects[vartype.ItemIndex]));
|
|
|
|
DisableGui;
|
|
|
|
SpawnCancelButton;
|
|
|
|
end
|
|
else if btnFirst.tag = 2 then
|
|
begin
|
|
//btnNewScan
|
|
btnFirst.Tag := 0;
|
|
donewscan;
|
|
memscan.newscan; //cleanup memory and terminate all background threads
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.MemScanStart(sender: TObject);
|
|
begin
|
|
foundlist.Deinitialize; //unlock file handles
|
|
cleanupPreviousResults;
|
|
end;
|
|
|
|
procedure TMainForm.MemScanDone(sender: TObject);
|
|
var
|
|
i: integer;
|
|
_canceled: boolean;
|
|
actuallyshown: double;
|
|
error: boolean;
|
|
_previous: string;
|
|
|
|
c: qword;
|
|
|
|
scantime: qword;
|
|
begin
|
|
{$ifdef windows}
|
|
QueryPerformanceCounter(scantimefinish);
|
|
|
|
scantime:=scantimefinish-scantimestart;
|
|
|
|
{$ifdef SCANPERF}
|
|
if ssCtrl in GetKeyShiftState then
|
|
showmessage(inttostr(scantime));
|
|
{$endif}
|
|
{$endif}
|
|
|
|
|
|
if ScanTabList <> nil then
|
|
ScanTabList.Enabled := True;
|
|
|
|
i := 0;
|
|
_canceled := False;
|
|
|
|
btnFirst.Tag := 2;
|
|
btnFirst.Caption := rsScan;
|
|
btnNext.tag := 0;
|
|
ProgressBar.Position := 0;
|
|
|
|
error:=tmemscan(sender).hasError;
|
|
|
|
if tmemscan(sender).hasError then
|
|
begin
|
|
error:=true;
|
|
messagedlg(Format(rsScanError, [memscan.GetErrorString]), mtError, [mbOK], 0);
|
|
end
|
|
else
|
|
error:=false;
|
|
|
|
|
|
enablegui(memscan.LastScanType = stNextScan);
|
|
destroyCancelButton;
|
|
|
|
|
|
|
|
foundlist.Initialize(getvartype, memscan.Getbinarysize, cbHexadecimal.Checked,
|
|
formsettings.cbShowAsSigned.Checked, not rbBit.Checked, cbunicode.Checked,
|
|
TCustomType(VarType.items.objects[vartype.ItemIndex]));
|
|
|
|
c:=memscan.GetFoundCount;
|
|
foundcount := c;
|
|
|
|
cleanupPreviousResults;
|
|
|
|
if not compareToSavedScan then
|
|
_previous:='TMP'
|
|
else
|
|
_previous:=currentlySelectedSavedResultname;
|
|
|
|
reloadPreviousResults;
|
|
for i:=0 to PreviousResultList.count-1 do
|
|
if TSavedScanHandler(PreviousResultList[i]).name=_previous then
|
|
ActivePreviousResultColumn:=i+2;
|
|
|
|
if (foundlist3.items.Count <> foundcount) and (not foundlist.isUnknownInitialValue) then
|
|
begin
|
|
actuallyshown := foundlist3.items.Count;
|
|
foundcountlabel.Caption := foundcountlabel.Caption + ' (' + rsShown +
|
|
': ' + Format('%.0n', [actuallyshown]) + ')';
|
|
end;
|
|
|
|
if memscan.lastscantype = stFirstScan then
|
|
begin
|
|
//firstscan Epilogue
|
|
setGbScanOptionsEnabled(False);
|
|
|
|
vartype.Enabled := False;
|
|
btnNextScan.Enabled := True;
|
|
btnNewScan.Caption := strNewScan;
|
|
end;
|
|
|
|
|
|
ProgressBar.Position := 0;
|
|
UpdateFoundlisttimer.Enabled := True;
|
|
|
|
Scantype.ItemIndex := lastscantype;
|
|
UpdateScanType;
|
|
|
|
if cbpercentage <> nil then
|
|
cbPercentageOnChange(cbpercentage);
|
|
|
|
|
|
scanepilogue(_canceled);
|
|
|
|
if error and (memscan.lastscantype = stFirstScan) then //firstscan failed
|
|
btnNewScan.Click;
|
|
|
|
if (GetScanType=soUnchanged) and cbRepeatUntilStopped.visible and cbRepeatUntilStopped.checked then
|
|
begin
|
|
if repeatDelay<>0 then
|
|
begin
|
|
if repeatScanTimer<>nil then
|
|
freeandnil(repeatscantimer);
|
|
|
|
repeatScanTimer:=TTimer.create(self);
|
|
repeatscantimer.interval:=repeatdelay;
|
|
repeatscantimer.OnTimer:=@repeatScanTimerTimer;
|
|
|
|
|
|
end
|
|
else
|
|
btnNext.Click;
|
|
end
|
|
else
|
|
beep; //let the blind user know the scan has finished (See, I'm thinking about the visually impeared users...)
|
|
|
|
end;
|
|
|
|
procedure TMainForm.repeatScanTimerTimer(sender: TObject);
|
|
begin
|
|
freeandnil(repeatscantimer);
|
|
if cbRepeatUntilStopped.visible and cbRepeatUntilStopped.checked and (GetScanType=soUnchanged) then
|
|
btnNext.click;
|
|
end;
|
|
|
|
procedure TMainForm.CancelbuttonClick(Sender: TObject);
|
|
begin
|
|
if cancelbutton.tag = 0 then
|
|
begin
|
|
cancelbutton.Caption := rsTerminatingScan;
|
|
cancelbutton.Enabled := False;
|
|
cancelbutton.Tag := 1; //force termination
|
|
cancelbutton.Hint := rsThisButtonWillForceCancelAScanExpectMemoryLeaks;
|
|
cancelbutton.ParentShowHint := False;
|
|
cancelbutton.ShowHint := True;
|
|
memscan.terminatescan(False);
|
|
|
|
cancelbuttonenabler.Enabled := False;
|
|
cancelbuttonenabler.interval := 8000; //8 seconds
|
|
cancelbuttonenabler.tag := 1;
|
|
cancelbuttonenabler.Enabled := True;
|
|
end
|
|
else
|
|
begin
|
|
//force it. It took too long
|
|
memscan.TerminateScan(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.CancelbuttonenablerInterval(Sender: TObject);
|
|
begin
|
|
if cancelbutton <> nil then
|
|
cancelbutton.Enabled := True;
|
|
|
|
if cancelbutton.Tag = 1 then
|
|
cancelbutton.Caption := rsForceTermination;
|
|
TTimer(Sender).Enabled := False;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.btnNextClick(Sender: TObject);
|
|
var
|
|
svalue2: string;
|
|
estimateddiskspaceneeded: qword;
|
|
diskspacefree, totaldiskspace: int64;
|
|
{$ifdef windows}
|
|
totaldiskspacefree: LARGE_INTEGER;{$endif}
|
|
percentage: boolean;
|
|
begin
|
|
{$ifdef windows}
|
|
if aprilfools then decreaseCheatECoinCount;
|
|
{$endif}
|
|
|
|
{ estimateddiskspaceneeded:=foundcount*8*3;
|
|
GetDiskFreeSpaceEx(pchar(memscan.ScanresultFolder), diskspacefree, totaldiskspace,@totaldiskspacefree);
|
|
|
|
|
|
if estimateddiskspaceneeded>diskspacefree then
|
|
if MessageDlg(rsYouAreLowOnDiskspaceOnTheFolderWhereTheScanresults, mtwarning, [mbyes, mbno], 0)<>mryes then exit;
|
|
}
|
|
|
|
|
|
|
|
if cbpercentage <> nil then
|
|
percentage := cbPercentage.Checked
|
|
else
|
|
percentage := False;
|
|
|
|
|
|
|
|
if cbPauseWhileScanning.Checked then
|
|
begin
|
|
advancedoptions.Pausebutton.down := True;
|
|
advancedoptions.Pausebutton.Click;
|
|
end;
|
|
|
|
ProgressBar.min := 0;
|
|
ProgressBar.max := 1000;
|
|
ProgressBar.position := 0;
|
|
|
|
|
|
if scanvalue2 <> nil then
|
|
svalue2 := scanvalue2.Text
|
|
else
|
|
svalue2 := '';
|
|
|
|
lastscantype := scantype.ItemIndex;
|
|
|
|
memscan.floatscanWithoutExponents:=cbFloatSimple.checked;
|
|
memscan.inverseScan:=cbNot.Checked and cbnot.Visible;
|
|
memscan.codePage:=cbCodePage.checked;
|
|
memscan.luaformula:=cbLuaFormula.visible and cbLuaFormula.checked;
|
|
memscan.NewLuaState:=cbNewLuaState.checked;
|
|
|
|
memscan.busyformIsModal:=not ((GetScanType=soUnchanged) and cbRepeatUntilStopped.checked);
|
|
|
|
|
|
if ScanTabList <> nil then
|
|
ScanTabList.Enabled := False;
|
|
|
|
memscan.nextscan(GetScanType2, roundingtype, scanvalue.Text,
|
|
svalue2, cbHexadecimal.Checked, rbdec.Checked,
|
|
cbunicode.Checked, cbCaseSensitive.Checked, percentage, compareToSavedScan,
|
|
currentlySelectedSavedResultname);
|
|
DisableGui;
|
|
SpawnCancelButton;
|
|
end;
|
|
|
|
procedure TMainForm.scanEpilogue(canceled: boolean);
|
|
var
|
|
vtype: TVariableType;
|
|
i: integer;
|
|
bytes: tbytes;
|
|
begin
|
|
|
|
vtype := getvartype;
|
|
if not canceled then
|
|
begin
|
|
case vtype of
|
|
vtBinary: i := memscan.getbinarysize;
|
|
vtString: i := length(scanvalue.Text);
|
|
vtByteArray: //array of byte
|
|
begin
|
|
setlength(bytes, 0);
|
|
try
|
|
ConvertStringToBytes(scanvalue.Text, cbHexadecimal.Checked, bytes);
|
|
i := length(bytes);
|
|
except
|
|
i := 1;
|
|
end;
|
|
setlength(bytes, 0);
|
|
end;
|
|
end;
|
|
foundlist.Initialize(vtype, i, cbHexadecimal.Checked,
|
|
formsettings.cbShowAsSigned.Checked, not rbBit.Checked, cbunicode.Checked,
|
|
memscan.CustomType);
|
|
end
|
|
else
|
|
foundlist.Initialize(vtype, memscan.CustomType);
|
|
//failed scan, just reopen the addressfile
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
if cbRepeatUntilStopped.checked=false then //don't focus. it takes way the click handlers which is needed for checkboxes
|
|
begin
|
|
|
|
if scanvalue.Visible and scanvalue.Enabled then
|
|
begin
|
|
scanvalue.SetFocus;
|
|
scanvalue.SelectAll;
|
|
end
|
|
else
|
|
if not canceled then
|
|
begin
|
|
btnNextScan.SetFocus;
|
|
end;
|
|
|
|
end;
|
|
except
|
|
|
|
end;
|
|
|
|
|
|
|
|
if cbPauseWhileScanning.Checked then
|
|
begin
|
|
advancedoptions.Pausebutton.down := False; //resume
|
|
advancedoptions.Pausebutton.Click;
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
procedure TMainForm.FormDestroy(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
oldscanstate: PScanState;
|
|
x: array of integer;
|
|
reg: tregistry;
|
|
begin
|
|
|
|
|
|
if flashprocessbutton<>nil then
|
|
begin
|
|
flashprocessbutton.Terminate;
|
|
flashprocessbutton.WaitFor;
|
|
flashprocessbutton.Free;
|
|
end;
|
|
|
|
if freezethread<>nil then
|
|
begin
|
|
freezeThread.Terminate;
|
|
freezeThread.WaitFor;
|
|
freeandnil(freezeThread);
|
|
end;
|
|
|
|
setlength(x,7);
|
|
x[0]:=addresslist.headers.Sections[0].Width;
|
|
x[1]:=addresslist.headers.Sections[1].Width;
|
|
x[2]:=addresslist.headers.Sections[2].Width;
|
|
x[3]:=addresslist.headers.Sections[3].Width;
|
|
x[4]:=addresslist.headers.Sections[4].Width;
|
|
x[5]:=panel5.Height;
|
|
x[6]:=foundlist3.columns[0].Width;
|
|
|
|
saveformposition(self, x);
|
|
|
|
if foundlist <> nil then
|
|
foundlist.Deinitialize;
|
|
|
|
if addresslist <> nil then
|
|
FreeAndNil(addresslist);
|
|
|
|
if scantablist = nil then
|
|
if memscan <> nil then
|
|
FreeAndNil(memscan);
|
|
|
|
if scantablist <> nil then
|
|
begin
|
|
for i := 0 to scantablist.Count - 1 do
|
|
begin
|
|
if scantablist.SelectedTab <> i then
|
|
begin
|
|
oldscanstate := scantablist.TabData[i];
|
|
freeandnil(oldscanstate^.foundlist);
|
|
freeandnil(oldscanstate^.memscan);
|
|
freememandnil(oldscanstate);
|
|
end;
|
|
end;
|
|
FreeAndNil(scantablist);
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
procedure TMainForm.tbSpeedChange(Sender: TObject);
|
|
var
|
|
x: integer;
|
|
y: single;
|
|
begin
|
|
x := tbSpeed.position;
|
|
case x of
|
|
0: y := 0;
|
|
1: y := 0.25;
|
|
2: y := 0.5;
|
|
3: y := 1;
|
|
4: y := 2;
|
|
5: y := 5;
|
|
6: y := 10;
|
|
7: y := 20;
|
|
8: y := 50;
|
|
9: y := 100;
|
|
10: y := 200;
|
|
11: y := 500;
|
|
else
|
|
y := 1;
|
|
end;
|
|
|
|
if x>=3 then
|
|
editSH2.Text := format('%.0f', [y])
|
|
else
|
|
if x>=2 then
|
|
editSH2.Text := format('%.1f', [y])
|
|
else
|
|
if x<2 then
|
|
editSH2.Text := format('%.2f', [y]);
|
|
end;
|
|
|
|
procedure TMainForm.btnSetSpeedhack2Click(Sender: TObject);
|
|
var
|
|
newspeed: single;
|
|
fs: Tformatsettings;
|
|
error: boolean;
|
|
begin
|
|
error := False;
|
|
try
|
|
newspeed := StrToFloat(editsh2.Text);
|
|
except
|
|
fs := DefaultFormatSettings;
|
|
try
|
|
newspeed := StrToFloat(editsh2.Text, fs);
|
|
except
|
|
error := True;
|
|
end;
|
|
end;
|
|
|
|
if error or IsInfinite(newspeed) or IsNan(newspeed) then
|
|
raise Exception.Create(Format(rsIsNotAValidSpeed, [editSH2.Text]));
|
|
|
|
if speedHack <> nil then
|
|
begin
|
|
{$ifdef windows}
|
|
if speedhack.processid<>processid then
|
|
begin
|
|
//the process switched
|
|
FreeAndNil(speedhack); //recreate
|
|
speedhack := TSpeedhack.Create;
|
|
end;
|
|
{$endif}
|
|
|
|
speedhack.setSpeed(newspeed);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.cbSpeedhackChange(Sender: TObject);
|
|
var ss: TShiftState;
|
|
begin
|
|
if cbSpeedhack.Checked then
|
|
begin
|
|
try
|
|
if speedhack <> nil then
|
|
FreeAndNil(speedhack);
|
|
|
|
speedhack := TSpeedhack.Create;
|
|
except
|
|
on e: Exception do
|
|
begin
|
|
{ outputdebugstring('Normal speedhack activation failed. Checking for :"activateAlternateSpeedhack"');
|
|
lua_getglobal(luavm, 'activateAlternateSpeedhack');//failure. check if there is an alternative in lua
|
|
if lua_isfunction(luavm,-1) then
|
|
begin
|
|
OutputDebugString('Calling activateAlternateSpeedhack');
|
|
lua_pushboolean(luavm,true);
|
|
lua_pcall(luavm, 1,1,0);
|
|
if lua_toboolean(luavm,-1)<>true then
|
|
cbSpeedhack.Checked:=false;
|
|
|
|
exit;
|
|
end
|
|
else
|
|
lua_pop(luavm,1);
|
|
}
|
|
|
|
cbSpeedhack.Checked := False;
|
|
MessageDlg(e.message,mtError,[mbok],0);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if speedhack <> nil then
|
|
FreeAndNil(speedhack);
|
|
end;
|
|
|
|
panel14.Visible := cbSpeedhack.Checked;
|
|
end;
|
|
|
|
{--------Processlist menuitem--------}
|
|
//var
|
|
// il: TImageList;
|
|
|
|
|
|
procedure TMainForm.Process1Click(Sender: TObject);
|
|
|
|
var
|
|
sl: TStringList;
|
|
mi: array of TMenuItem;
|
|
currentmi: TMenuItemExtra;
|
|
i, j: integer;
|
|
|
|
tempicon: Graphics.TIcon;
|
|
tempp: tpicture;
|
|
p: integer;
|
|
|
|
begin
|
|
//fill with processlist
|
|
// if il = nil then
|
|
// il := TImageList.Create(self);
|
|
|
|
// il.clear;
|
|
|
|
|
|
sl := TStringList.Create;
|
|
|
|
try
|
|
GetProcessList(sl);
|
|
for i := process1.Count - 1 downto 3 do
|
|
process1.Items[i].Free;
|
|
|
|
setlength(mi, sl.Count);
|
|
for i := 0 to sl.Count - 1 do
|
|
begin
|
|
j := sl.Count - 1 - i;
|
|
currentmi := TMenuItemExtra.Create(self);
|
|
currentmi.Caption := sl[i];
|
|
{$ifdef windows}
|
|
currentmi.Default := dword(ptrUint(PProcessListInfo(sl.Objects[i])^.processid)) = ProcessID;
|
|
currentmi.Data := pointer(ptrUint(PProcessListInfo(sl.Objects[i])^.processid));
|
|
{$else}
|
|
if TryStrToInt('$'+copy(sl[i],1,pos('-',sl[i])), p) then
|
|
begin
|
|
currentmi.Data := pointer(p);
|
|
currentmi.default:=p=processid;
|
|
end;
|
|
{$endif}
|
|
|
|
currentmi.OnClick := @ProcessItemClick;
|
|
|
|
|
|
{$IFDEF WINDOWS}
|
|
if PProcessListInfo(sl.Objects[i])^.processIcon > 0 then
|
|
begin
|
|
tempicon := Graphics.TIcon.Create;
|
|
tempicon.handle := PProcessListInfo(sl.Objects[i])^.processIcon;
|
|
|
|
tempp:=TPicture.create;
|
|
tempp.Icon:=tempicon;
|
|
currentmi.Bitmap:=tempp.bitmap;
|
|
|
|
tempp.free;
|
|
tempicon.free;
|
|
end
|
|
else
|
|
{$ENDIF}
|
|
currentmi.ImageIndex := -1;
|
|
|
|
mi[j] := currentmi;
|
|
process1.Add(currentmi);
|
|
end;
|
|
|
|
finally
|
|
cleanProcessList(sl);
|
|
sl.Free;
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
procedure TMainForm.ProcessItemClick(Sender: TObject);
|
|
var
|
|
pid: dword;
|
|
oldprocess: Dword;
|
|
oldprocesshandle: thandle;
|
|
oldprocessname: string;
|
|
begin
|
|
|
|
if openprocessPrologue then
|
|
begin
|
|
oldprocessname := copy(mainform.ProcessLabel.Caption, pos(
|
|
'-', mainform.ProcessLabel.Caption) + 1, length(mainform.ProcessLabel.Caption));
|
|
oldprocess := processID;
|
|
oldprocesshandle := processhandle;
|
|
if (Sender is TMenuItemExtra) then
|
|
begin
|
|
pid := dword(ptrUint(TMenuItemExtra(Sender).Data));
|
|
//the menuitem .data field contains the processid (and not some allocated memory)
|
|
|
|
unpause;
|
|
DetachIfPossible;
|
|
|
|
with TProcessWindow.Create(self) do
|
|
begin
|
|
pwop(inttohex(pid, 8));
|
|
ProcessLabel.Caption := TMenuItemExtra(Sender).Caption;
|
|
Free;
|
|
end;
|
|
|
|
openprocessepilogue(oldprocessname, oldprocess, oldprocesshandle);
|
|
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
{^^^^^^^^Processlist menuitem^^^^^^^^}
|
|
procedure TMainForm.miAboutClick(Sender: TObject);
|
|
begin
|
|
About := TAbout.Create(self);
|
|
About.showmodal;
|
|
end;
|
|
|
|
procedure TMainForm.CreateProcess1Click(Sender: TObject);
|
|
var
|
|
x: dword;
|
|
oldprocess: Dword;
|
|
oldprocesshandle: thandle;
|
|
oldprocessname: string;
|
|
begin
|
|
if openprocessPrologue then
|
|
begin
|
|
|
|
oldprocessname := copy(mainform.ProcessLabel.Caption, pos(
|
|
'-', mainform.ProcessLabel.Caption) + 1, length(mainform.ProcessLabel.Caption));
|
|
oldprocess := processID;
|
|
oldprocesshandle := processhandle;
|
|
with TProcessWindow.Create(self) do
|
|
begin
|
|
miCreateProcess.Click;
|
|
Free;
|
|
end;
|
|
|
|
if processid <> oldprocess then
|
|
openprocessepilogue(oldprocessname, oldprocess, oldprocesshandle);
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.Helpindex1Click(Sender: TObject);
|
|
begin
|
|
ShellExecute(0,'open','https://wiki.cheatengine.org/index.php',nil,nil,SW_SHOW);
|
|
// Application.HelpContext(1);
|
|
end;
|
|
|
|
procedure TMainForm.New1Click(Sender: TObject);
|
|
begin
|
|
if MessageDlg(rsAreYouSureYouWantToEraseTheDataInTheCurrentTable,
|
|
mtConfirmation, [mbYes, mbNo], 0) = mrYes then
|
|
clearlist;
|
|
end;
|
|
|
|
procedure TMainForm.ClearList;
|
|
{
|
|
Will remove all entries from the cheattable, comments, and advanced options window
|
|
}
|
|
begin
|
|
Comments.Memo1.Clear;
|
|
comments.Memo1.Lines.Add(strInfoAboutTable);
|
|
advancedoptions.clear;
|
|
addresslist.Clear;
|
|
end;
|
|
|
|
procedure TMainForm.ClearRecentFiles(Sender:TObject);
|
|
begin
|
|
if MessageDlg(rsAreYouSure, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
|
|
begin
|
|
recentfiles.Clear;
|
|
cereg.writeStrings('Recent Files', recentfiles);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.RecentFilesClick(Sender:TObject);
|
|
var filename: string;
|
|
begin
|
|
if CheckIfSaved then
|
|
begin
|
|
filename:=RecentFiles[tmenuitem(sender).Tag];
|
|
LoadTable(filename,false);
|
|
SaveDialog1.FileName:=filename;
|
|
OpenDialog1.FileName:=filename;
|
|
recentFilesUpdate(filename);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.File1Click(Sender: TObject);
|
|
var
|
|
i: integer;
|
|
m: TMenuItem;
|
|
begin
|
|
miSaveScanresults.Enabled := memscan.nextscanCount > 0;
|
|
miLoadRecent.Visible:=RecentFiles.Count>0;
|
|
|
|
miLoadRecent.Clear;
|
|
for i:=0 to RecentFiles.count-1 do
|
|
begin
|
|
m:=tmenuitem.Create(miLoadRecent);
|
|
m.Caption:=RecentFiles[i];
|
|
m.OnClick:=@RecentFilesClick;
|
|
m.tag:=i;
|
|
|
|
miLoadRecent.Add(m);
|
|
end;
|
|
|
|
m:=tmenuitem.Create(miLoadRecent);
|
|
m.Caption:='-';
|
|
miLoadRecent.Add(m);
|
|
|
|
m:=tmenuitem.Create(miLoadRecent);
|
|
m.Name:='miEmptyRecentFilesList';
|
|
m.Caption:=rsClearRecentFiles;
|
|
m.OnClick:=@ClearRecentFiles;
|
|
miLoadRecent.Add(m);
|
|
|
|
|
|
miDeleteSavedScanResults.visible:=memscan.SavedScanCount>0;
|
|
end;
|
|
|
|
procedure TMainForm.actOpenProcesslistExecute(Sender: TObject);
|
|
begin
|
|
sbOpenProcess.Click;
|
|
end;
|
|
|
|
procedure TMainForm.Type1Click(Sender: TObject);
|
|
begin
|
|
addresslist.doTypeChange;
|
|
end;
|
|
|
|
procedure TMainForm.DoGroupconfigButtonClick(sender: tobject);
|
|
var gcf: TfrmGroupScanAlgoritmGenerator;
|
|
begin
|
|
gcf:=TfrmGroupScanAlgoritmGenerator.create(self);
|
|
try
|
|
gcf.parseParameters(scanvalue.text);
|
|
except
|
|
on e:exception do
|
|
begin
|
|
MessageDlg(e.message,mtError,[mbok],0);
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
if gcf.showmodal=mrok then
|
|
scanvalue.text:=gcf.getparameters;
|
|
|
|
gcf.free;
|
|
end;
|
|
|
|
|
|
function TMainForm.GetScanType2: TScanOption;
|
|
{
|
|
not needed anymore
|
|
}
|
|
begin
|
|
result:=GetScanType;
|
|
end;
|
|
|
|
function TMainForm.GetScanType: TScanOption;
|
|
begin
|
|
result:=soExactValue;
|
|
begin
|
|
if not (getvartype in [vtBinary,vtString,vtByteArray]) then //not binary, string or bytearray
|
|
begin
|
|
if not btnNextScan.enabled then
|
|
begin
|
|
//first scan
|
|
case scantype.ItemIndex of
|
|
0: result:=soExactValue;
|
|
1: result:=soBiggerThan;
|
|
2: result:=soSmallerThan;
|
|
3: result:=soValueBetween;
|
|
4: result:=soUnknownValue;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
//next scan
|
|
case scantype.itemindex of
|
|
0: result:=soExactValue;
|
|
1: result:=soBiggerThan;
|
|
2: result:=soSmallerThan;
|
|
3: result:=soValueBetween;
|
|
4: result:=soIncreasedValue;
|
|
5: result:=soIncreasedValueBy;
|
|
6: result:=soDecreasedValue;
|
|
7: result:=soDecreasedValueBy;
|
|
8: result:=soChanged;
|
|
9: result:=soUnchanged;
|
|
10: result:=soForgot;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TMainForm.getVarType2: TVariableType; //obsolete
|
|
begin
|
|
result:=getVarType;
|
|
|
|
end;
|
|
|
|
function TMainForm.getVarType: TVariableType;
|
|
begin
|
|
case VarType.ItemIndex of
|
|
VARTYPE_INDEX_BINARY: result:=vtBinary; //binary
|
|
VARTYPE_INDEX_BYTE: result:=vtByte; //byte
|
|
VARTYPE_INDEX_WORD: result:=vtWord; //2 bytes
|
|
VARTYPE_INDEX_DWORD: result:=vtDword; //4 bytes
|
|
VARTYPE_INDEX_QWORD: result:=vtQword; //8 bytes
|
|
VARTYPE_INDEX_SINGLE: result:=vtSingle; //float
|
|
VARTYPE_INDEX_DOUBLE: result:=vtDouble; //double
|
|
VARTYPE_INDEX_TEXT: result:=vtString; //text
|
|
VARTYPE_INDEX_AOB: result:=vtByteArray; //array of byte
|
|
VARTYPE_INDEX_ALL: result:=vtAll; //all, only for new memscan
|
|
VARTYPE_INDEX_GROUPED: result:=vtGrouped; //grouped, only for memscan
|
|
else
|
|
result:=vtCustom;
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.setVarType(vt: TVariableType);
|
|
begin
|
|
if vartype.enabled then
|
|
begin
|
|
case vt of
|
|
vtBinary: vartype.itemindex:=VARTYPE_INDEX_BINARY;
|
|
vtByte: vartype.itemindex:=VARTYPE_INDEX_BYTE;
|
|
vtWord: vartype.itemindex:=VARTYPE_INDEX_WORD;
|
|
vtDword: vartype.itemindex:=VARTYPE_INDEX_DWORD;
|
|
vtQword: vartype.itemindex:=VARTYPE_INDEX_QWORD;
|
|
vtSingle: vartype.itemindex:=VARTYPE_INDEX_SINGLE;
|
|
vtDouble: vartype.itemindex:=VARTYPE_INDEX_DOUBLE;
|
|
vtString: vartype.itemindex:=VARTYPE_INDEX_TEXT;
|
|
vtByteArray: vartype.itemindex:=VARTYPE_INDEX_AOB;
|
|
vtAll: vartype.itemindex:=VARTYPE_INDEX_ALL;
|
|
vtGrouped: vartype.itemindex:=VARTYPE_INDEX_GROUPED;
|
|
end;
|
|
|
|
vartype.OnChange(vartype);
|
|
end;
|
|
end;
|
|
|
|
procedure TMainForm.MemscanGuiUpdate(sender: TObject; totaladdressestoscan: qword; currentlyscanned: qword; foundcount: qword);
|
|
begin
|
|
self.foundcount:=foundcount;
|
|
end;
|
|
|
|
|
|
procedure TMainForm.BoundsUpdate(sender: TObject);
|
|
var newminheight: integer;
|
|
begin
|
|
newminheight:=gbScanOptions.top + gbScanOptions.Height + max(speedbutton2.Height, btnAddAddressManually.height ) + 10;
|
|
|
|
if newminheight<>panel5.Constraints.MinHeight then
|
|
begin
|
|
gbScanOptions.OnChangeBounds:=nil;
|
|
panel5.Constraints.MinHeight := gbScanOptions.top + gbScanOptions.Height + max(speedbutton2.Height, btnAddAddressManually.height ) + 10;
|
|
gbScanOptions.OnChangeBounds:=@gbScanOptionsChangeBounds;
|
|
end;
|
|
|
|
boundsupdater.enabled:=false;
|
|
end;
|
|
|
|
procedure TMainForm.SpawnBoundsUpdater;
|
|
begin
|
|
if boundsupdater=nil then
|
|
begin
|
|
boundsupdater:=TTimer.Create(self);
|
|
boundsupdater.Interval:=500;
|
|
boundsupdater.OnTimer:=@BoundsUpdate;
|
|
boundsupdater.Enabled:=false;
|
|
end;
|
|
|
|
if boundsupdater.enabled=false then
|
|
boundsupdater.enabled:=true;
|
|
end;
|
|
|
|
procedure TMainForm.reloadPreviousResults;
|
|
var
|
|
l: tstringlist;
|
|
i: integer;
|
|
c: TListColumn;
|
|
ssh: TSavedScanHandler;
|
|
|
|
oldsizes: array of integer;
|
|
begin
|
|
oldsizes:=[];
|
|
l:=nil;
|
|
setlength(oldsizes, foundlist3.ColumnCount);
|
|
for i:=0 to foundlist3.columncount-1 do
|
|
oldsizes[i]:=foundlist3.columns[i].Width;
|
|
|
|
foundlist3.BeginUpdate;
|
|
try
|
|
cleanupPreviousResults;
|
|
if getVarType in [vtGrouped, vtString, vtUnicodeString, vtByteArray] then exit;
|
|
|
|
|
|
l:=tstringlist.create;
|
|
|
|
|
|
c:=foundlist3.Columns.Add;
|
|
c.caption:=rsPrevious;
|
|
if c.Index=fActivePreviousResultColumn then
|
|
c.tag:=foundlistColors.CompareToHeaderColor;
|
|
|
|
c.visible:=(c.Index>=2) and miShowPreviousValue.checked and ((miOnlyShowCurrentCompareToColumn.Checked=false) or (c.index=fActivePreviousResultColumn));
|
|
|
|
try
|
|
ssh:=TSavedScanHandler.create(memscan.getScanFolder, 'TMP');
|
|
except
|
|
exit; //invalid state (e.g newscan)
|
|
end;
|
|
ssh.memscan:=memscan;
|
|
ssh.AllowNotFound:=true;
|
|
ssh.AllowRandomAccess:=true;
|
|
PreviousResultList.add(ssh);
|
|
|
|
|
|
|
|
memscan.getsavedresults(l);
|
|
|
|
for i:=l.count-1 downto 0 do
|
|
begin
|
|
c:=foundlist3.Columns.Add;
|
|
c.caption:=l[i];
|
|
if c.Index=fActivePreviousResultColumn then
|
|
c.tag:=foundlistColors.CompareToHeaderColor;
|
|
|
|
c.visible:=(c.Index>=2) and miShowPreviousValue.checked and ((miOnlyShowCurrentCompareToColumn.Checked=false) or (c.index=fActivePreviousResultColumn));
|
|
|
|
|
|
ssh:=TSavedScanHandler.create(memscan.getScanFolder, l[i], true);
|
|
ssh.memscan:=memscan;
|
|
ssh.AllowNotFound:=true;
|
|
ssh.AllowRandomAccess:=true;
|
|
|
|
PreviousResultList.Add(ssh);
|
|
end;
|
|
finally
|
|
|
|
if l<>nil then
|
|
freemem(l);
|
|
|
|
if foundlist3.ColumnCount=length(oldsizes) then
|
|
begin
|
|
for i:=0 to length(oldsizes)-1 do
|
|
foundlist3.Column[i].Width:=oldsizes[i];
|
|
end
|
|
else
|
|
panel5resize(nil); //columncount changed
|
|
|
|
foundlist3.EndUpdate;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TMainForm.cleanupPreviousResults;
|
|
//do a foundlist3.beginupdate first if this is just part of repopulating
|
|
var i: integer;
|
|
begin
|
|
foundlist3.BeginUpdate;
|
|
for i:=0 to PreviousResultList.Count-1 do
|
|
begin
|
|
if PreviousResultList[i]<>nil then
|
|
TSavedScanHandler(PreviousResultList[i]).free;
|
|
end;
|
|
|
|
PreviousResultList.Clear;
|
|
|
|
//first 2 columns are address and current value, the ones following are the previous value
|
|
while foundlist3.Columns.count>2 do
|
|
foundlist3.Columns.Delete(2);
|
|
|
|
foundlist3.EndUpdate;
|
|
end;
|
|
|
|
procedure TMainForm.setActivePreviousResultColumn(c: integer);
|
|
var
|
|
i: integer;
|
|
{$ifdef darwin}
|
|
s: string;
|
|
{$endif}
|
|
begin
|
|
if InsideSetActivePreviousResult then exit;
|
|
|
|
InsideSetActivePreviousResult:=true;
|
|
|
|
cbCompareToSavedScan.OnChange:=nil;
|
|
|
|
if (c>=2) and (c<foundlist3.ColumnCount) then
|
|
begin
|
|
for i:=2 to foundlist3.ColumnCount-1 do
|
|
begin
|
|
foundlist3.Column[i].Tag:=0;
|
|
|
|
|
|
{$ifdef darwin}
|
|
s:=foundlist3.Column[i].caption;
|
|
foundlist3.Column[i].caption:=s.DeQuotedString('*');
|
|
{$endif}
|
|
|
|
if miOnlyShowCurrentCompareToColumn.Checked then
|
|
begin
|
|
if (i>=2) then
|
|
foundlist3.Columns[i].Visible:=(i=c) and miShowPreviousValue.checked; //only make the current compare column visible
|
|
|
|
end
|
|
else
|
|
foundlist3.Columns[i].Visible:=(i>=2) and miShowPreviousValue.checked;
|
|
|
|
end;
|
|
|
|
fActivePreviousResultColumn:=c;
|
|
|
|
if miOnlyShowCurrentCompareToColumn.Checked=false then //people that disable this likely want it the way the old CE showed it
|
|
begin
|
|
foundlist3.Column[c].tag:=foundlistColors.CompareToHeaderColor;
|
|
|
|
{$ifdef darwin}
|
|
s:=foundlist3.Column[c].caption;
|
|
|
|
foundlist3.Column[c].caption:=s.QuotedString('*');
|
|
{$endif}
|
|
end;
|
|
|
|
if (c-2)<PreviousResultList.count then
|
|
currentlySelectedSavedResultname:=TSavedScanHandler(PreviousResultList[c-2]).name;
|
|
|
|
if c>=3 then
|
|
begin
|
|
cbCompareToSavedScan.checked:=true;
|
|
compareToSavedScan := True;
|
|
if PreviousResultList.count>2 then //last, first are default
|
|
begin
|
|
lblcompareToSavedScan.Visible := true;
|
|
lblcompareToSavedScan.Caption := '('+currentlySelectedSavedResultname+')';
|
|
end
|
|
else
|
|
lblcompareToSavedScan.Visible := false;
|
|
end
|
|
else
|
|
begin
|
|
cbCompareToSavedScan.checked := false;
|
|
lblcompareToSavedScan.Visible := false;
|
|
end;
|
|
end;
|
|
|
|
|
|
cbCompareToSavedScan.OnChange:=@cbCompareToSavedScanChange;
|
|
|
|
foundlist3.Refresh;
|
|
InsideSetActivePreviousResult:=false;
|
|
end;
|
|
|
|
initialization
|
|
DecimalSeparator := '.';
|
|
ThousandSeparator := ',';
|
|
|
|
{$i MainUnit.lrs}
|
|
|
|
end.
|
|
|
|
open
|