Well as some of you may know I'm trying to recode Dark_Byte's speed hack so that I can use it to make a quick reload hack for CA. There's one problem I ran into along the way, and that is that Dark_Byte unfortunately coded his hack in Delphi, because apparently he thought it was easier to access assembly funtions through Delphi. So currently I'm trying to understand Delphi, and enough ASM to understand the little scripts he added.
Well here is his source code for you to look at. Like I said it's written in Delphi so it doesn't really belong in this forum, but there's no Delphi forum either. Hopefully I or someone else might get around to translating this into C++:
Code:
unit speedhack;
2 {obsolete since 5.5 has a seperate dll initialized by ce's auto assembler}
3
4 interface
5 uses windows,classes,globals;
6
7 type TTick=class(TThread)
8 private
9 public
10 procedure Execute; override;
11 end;
12
13 procedure InitializeSpeedhack;
14 procedure StopSpeedhack;
15
16 procedure GetTime; stdcall;
17 //function GetTime:dword; stdcall;
18 function NewQueryPerformanceCounter(var output: int64):BOOl; stdcall;
19 var CETick: dword;
20 CETick64: int64;
21 Ticker: TTick;
22
23 PerformanceFrequency: int64;
24 PerformanceFrequencyMS: int64;
25 acceleration: single;
26 sleeptime: dword;
27 slow: boolean;
28 tickerstopped: boolean;
29 speedhackenabled: boolean;
30
31
32 timeGetTimeInfo:TAPiInfo;
33 getTickcountInfo: TAPIInfo;
34 QueryPerformanceCounterInfo: TAPIInfo;
35 winmmlib,kernel32lib: thandle;
36
37 implementation
38
39 procedure InitializeSpeedhack;
40 var op:dword;
41 begin
42 cetick:=gettickcount;
43 //change the gettickcount and timegettime functions so that they look at cetick
44 if ticker<>nil then
45 begin
46 ticker.Terminate;
47 stopspeedhack;
48 end;
49 ticker:=nil;
50
51
52 winmmlib:=LoadLibrary('winmm.dll');
53 if winmmlib<>0 then
54 begin
55 timeGetTimeInfo.location:=GetProcAddress(winmmlib,'timeGetTime');
56 if VirtualProtect(timeGetTimeInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
57 begin
58 timeGetTimeInfo.jump[0]:=$e9;
59 pdword(@timeGetTimeInfo.jump[1])^:=dword(@GetTime)-dword(timeGetTimeInfo.location)-5;
60
61 try
62 asm
63 //store original
64 push edi
65 push esi
66 lea edi,timeGetTimeInfo.original[0]
67 mov esi,timeGetTimeInfo.location
68 movsd
69 movsb
70
71 //replace with jump
72 lea esi,timeGetTimeInfo.jump[0]
73 mov edi,timeGetTimeInfo.location
74 movsd
75 movsb
76
77 pop esi
78 pop edi
79 end;
80 except
81
82 end;
83 end;
84 end;
85
86
87 kernel32lib:=LoadLibrary('kernel32.dll');
88 if kernel32lib<>0 then
89 begin
90 //gettickcount
91 GetTickCountInfo.location:=GetProcAddress(kernel32lib,'GetTickCount');
92 if VirtualProtect(GetTickCountInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
93 begin
94 GetTickCountInfo.jump[0]:=$e9;
95 pdword(@GetTickCountInfo.jump[1])^:=dword(@GetTime)-dword(GetTickCountInfo.location)-5;
96
97 try
98 asm
99 //store original
100 push edi
101 push esi
102 lea edi,GetTickCountInfo.original[0]
103 mov esi,GetTickCountInfo.location
104 movsd
105 movsb
106
107 //replace with jump
108 lea esi,GetTickCountInfo.jump[0]
109 mov edi,GetTickCountInfo.location
110 movsd
111 movsb
112
113 pop esi
114 pop edi
115 end;
116 except
117
118 end;
119 end;
120
121
122 //QueryPerformanceCounter
123 if QueryPerformanceFrequency(PerformanceFrequency) then
124 begin
125 QueryPerformanceCounter(CETick64);
126 PerformanceFrequencyMS:=PerformanceFrequency div 1000;
127
128 //there is a high performance counter
129 QueryPerformanceCounterInfo.location:=GetProcAddress(kernel32lib,'QueryPerformanceCounter');
130 if VirtualProtect(QueryPerformanceCounterInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
131 begin
132 QueryPerformanceCounterInfo.jump[0]:=$e9;
133 pdword(@QueryPerformanceCounterInfo.jump[1])^:=dword(@NewQueryPerformanceCounter)-dword(QueryPerformanceCounterInfo.location)-5;
134
135 try
136 asm
137 //store original
138 push edi
139 push esi
140 lea edi,QueryPerformanceCounterInfo.original[0]
141 mov esi,QueryPerformanceCounterInfo.location
142 movsd
143 movsb
144
145 //replace with jump
146 lea esi,QueryPerformanceCounterInfo.jump[0]
147 mov edi,QueryPerformanceCounterInfo.location
148 movsd
149 movsb
150
151 pop esi
152 pop edi
153 end;
154 except
155
156 end;
157 end;
158 end;
159 end;
160
161 speedhackenabled:=true;
162
163 if ticker=nil then ticker:=TTick.Create(false);
164 end;
165
166 procedure StopSpeedhack;
167 begin
168 if not speedhackenabled then exit;
169
170 speedhackenableD:=false;
171
172 try
173 asm
174 lea esi,timeGetTimeInfo.original[0]
175 mov edi,timeGetTimeInfo.location
176 movsd
177 movsb
178 end;
179 except
180
181 end;
182
183 try
184 asm
185 lea esi,GetTickCountInfo.original[0]
186 mov edi,GetTickCountInfo.location
187 movsd
188 movsb
189 end;
190 except
191
192 end;
193
194 try
195 asm
196 lea esi,QueryPerformanceCounterInfo.original[0]
197 mov edi,QueryPerformanceCounterInfo.location
198 movsd
199 movsb
200 end;
201 except
202
203 end;
204
205
206
207 FreeLibrary(winmmlib);
208 FreeLibrary(kernel32lib);
209 winmmlib:=0;
210 kernel32lib:=0;
211 if ticker<>nil then ticker.terminate;
212 ticker:=nil;
213 end;
214
215
216 procedure GetTime; stdcall;
217 asm
218 mov eax,[CETick]
219 ret
220 end;
221
222 {function GetTime:dword; stdcall;
223 begin
224 result:=CETick;
225 end;}
226
227 function NewQueryPerformanceCounter(var output: int64):BOOl; stdcall;
228 begin
229 output:=cetick64;
230 result:=true;
231 end;
232
233 procedure TTick.Execute;
234 begin
235 tickerstopped:=false;
236 freeonterminate:=true;
237 priority:=tpTimeCritical; //if not a thread with higher priority will prevent the timer from running
238 while not terminated do
239 begin
240 inc(cetick64,trunc(acceleration*(PerformanceFrequency / (1000 / sleeptime))) );
241 inc(cetick,trunc(sleeptime*acceleration));
242 sleep(sleeptime);
243 end;
244 tickerstopped:=true;
245 end;
246
247 end.
EDIT: Here's the same code unnumbered. For those of you who want to compile it and have a 2006 compiler...
Code:
unit DBspdhack;
{obsolete since 5.5 has a seperate dll initialized by ce's auto assembler}
interface
uses windows,classes,globals;
type TTick=class(TThread)
private
public
procedure Execute; override;
end;
procedure InitializeSpeedhack;
procedure StopSpeedhack;
procedure GetTime; stdcall;
//function GetTime:dword; stdcall;
function NewQueryPerformanceCounter(var output: int64):BOOl; stdcall;
var CETick: dword;
CETick64: int64;
Ticker: TTick;
PerformanceFrequency: int64;
PerformanceFrequencyMS: int64;
acceleration: single;
sleeptime: dword;
slow: boolean;
tickerstopped: boolean;
speedhackenabled: boolean;
timeGetTimeInfo:TAPiInfo;
getTickcountInfo: TAPIInfo;
QueryPerformanceCounterInfo: TAPIInfo;
winmmlib,kernel32lib: thandle;
implementation
procedure InitializeSpeedhack;
var op:dword;
begin
cetick:=gettickcount;
//change the gettickcount and timegettime functions so that they look at cetick
if ticker<>nil then
begin
ticker.Terminate;
stopspeedhack;
end;
ticker:=nil;
winmmlib:=LoadLibrary('winmm.dll');
if winmmlib<>0 then
begin
timeGetTimeInfo.location:=GetProcAddress(winmmlib,'timeGetTime');
if VirtualProtect(timeGetTimeInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
begin
timeGetTimeInfo.jump[0]:=$e9;
pdword(@timeGetTimeInfo.jump[1])^:=dword(@GetTime)-dword(timeGetTimeInfo.location)-5;
try
asm
//store original
push edi
push esi
lea edi,timeGetTimeInfo.original[0]
mov esi,timeGetTimeInfo.location
movsd
movsb
//replace with jump
lea esi,timeGetTimeInfo.jump[0]
mov edi,timeGetTimeInfo.location
movsd
movsb
pop esi
pop edi
end;
except
end;
end;
end;
kernel32lib:=LoadLibrary('kernel32.dll');
if kernel32lib<>0 then
begin
//gettickcount
GetTickCountInfo.location:=GetProcAddress(kernel32lib,'GetTickCount');
if VirtualProtect(GetTickCountInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
begin
GetTickCountInfo.jump[0]:=$e9;
pdword(@GetTickCountInfo.jump[1])^:=dword(@GetTime)-dword(GetTickCountInfo.location)-5;
try
asm
//store original
push edi
push esi
lea edi,GetTickCountInfo.original[0]
mov esi,GetTickCountInfo.location
movsd
movsb
//replace with jump
lea esi,GetTickCountInfo.jump[0]
mov edi,GetTickCountInfo.location
movsd
movsb
pop esi
pop edi
end;
except
end;
end;
//QueryPerformanceCounter
if QueryPerformanceFrequency(PerformanceFrequency) then
begin
QueryPerformanceCounter(CETick64);
PerformanceFrequencyMS:=PerformanceFrequency div 1000;
//there is a high performance counter
QueryPerformanceCounterInfo.location:=GetProcAddress(kernel32lib,'QueryPerformanceCounter');
if VirtualProtect(QueryPerformanceCounterInfo.location,5,PAGE_EXECUTE_READWRITE,op) then
begin
QueryPerformanceCounterInfo.jump[0]:=$e9;
pdword(@QueryPerformanceCounterInfo.jump[1])^:=dword(@NewQueryPerformanceCounter)-dword(QueryPerformanceCounterInfo.location)-5;
try
asm
//store original
push edi
push esi
lea edi,QueryPerformanceCounterInfo.original[0]
mov esi,QueryPerformanceCounterInfo.location
movsd
movsb
//replace with jump
lea esi,QueryPerformanceCounterInfo.jump[0]
mov edi,QueryPerformanceCounterInfo.location
movsd
movsb
pop esi
pop edi
end;
except
end;
end;
end;
end;
speedhackenabled:=true;
if ticker=nil then ticker:=TTick.Create(false);
end;
procedure StopSpeedhack;
begin
if not speedhackenabled then exit;
speedhackenableD:=false;
try
asm
lea esi,timeGetTimeInfo.original[0]
mov edi,timeGetTimeInfo.location
movsd
movsb
end;
except
end;
try
asm
lea esi,GetTickCountInfo.original[0]
mov edi,GetTickCountInfo.location
movsd
movsb
end;
except
end;
try
asm
lea esi,QueryPerformanceCounterInfo.original[0]
mov edi,QueryPerformanceCounterInfo.location
movsd
movsb
end;
except
end;
FreeLibrary(winmmlib);
FreeLibrary(kernel32lib);
winmmlib:=0;
kernel32lib:=0;
if ticker<>nil then ticker.terminate;
ticker:=nil;
end;
procedure GetTime; stdcall;
asm
mov eax,[CETick]
ret
end;
{function GetTime:dword; stdcall;
begin
result:=CETick;
end;}
function NewQueryPerformanceCounter(var output: int64):BOOl; stdcall;
begin
output:=cetick64;
result:=true;
end;
procedure TTick.Execute;
begin
tickerstopped:=false;
freeonterminate:=true;
priority:=tpTimeCritical; //if not a thread with higher priority will prevent the timer from running
while not terminated do
begin
inc(cetick64,trunc(acceleration*(PerformanceFrequency / (1000 / sleeptime))) );
inc(cetick,trunc(sleeptime*acceleration));
sleep(sleeptime);
end;
tickerstopped:=true;
end;
end.