rlm@1
|
1 #include <cstdlib>
|
rlm@1
|
2 #include <cstring>
|
rlm@1
|
3
|
rlm@1
|
4 #include "CheatSearch.h"
|
rlm@1
|
5
|
rlm@1
|
6 CheatSearchBlock cheatSearchBlocks[4];
|
rlm@1
|
7
|
rlm@1
|
8 CheatSearchData cheatSearchData = {
|
rlm@1
|
9 0,
|
rlm@1
|
10 cheatSearchBlocks
|
rlm@1
|
11 };
|
rlm@1
|
12
|
rlm@1
|
13 static bool cheatSearchEQ(u32 a, u32 b)
|
rlm@1
|
14 {
|
rlm@1
|
15 return a == b;
|
rlm@1
|
16 }
|
rlm@1
|
17
|
rlm@1
|
18 static bool cheatSearchNE(u32 a, u32 b)
|
rlm@1
|
19 {
|
rlm@1
|
20 return a != b;
|
rlm@1
|
21 }
|
rlm@1
|
22
|
rlm@1
|
23 static bool cheatSearchLT(u32 a, u32 b)
|
rlm@1
|
24 {
|
rlm@1
|
25 return a < b;
|
rlm@1
|
26 }
|
rlm@1
|
27
|
rlm@1
|
28 static bool cheatSearchLE(u32 a, u32 b)
|
rlm@1
|
29 {
|
rlm@1
|
30 return a <= b;
|
rlm@1
|
31 }
|
rlm@1
|
32
|
rlm@1
|
33 static bool cheatSearchGT(u32 a, u32 b)
|
rlm@1
|
34 {
|
rlm@1
|
35 return a > b;
|
rlm@1
|
36 }
|
rlm@1
|
37
|
rlm@1
|
38 static bool cheatSearchGE(u32 a, u32 b)
|
rlm@1
|
39 {
|
rlm@1
|
40 return a >= b;
|
rlm@1
|
41 }
|
rlm@1
|
42
|
rlm@1
|
43 static bool cheatSearchSignedEQ(s32 a, s32 b)
|
rlm@1
|
44 {
|
rlm@1
|
45 return a == b;
|
rlm@1
|
46 }
|
rlm@1
|
47
|
rlm@1
|
48 static bool cheatSearchSignedNE(s32 a, s32 b)
|
rlm@1
|
49 {
|
rlm@1
|
50 return a != b;
|
rlm@1
|
51 }
|
rlm@1
|
52
|
rlm@1
|
53 static bool cheatSearchSignedLT(s32 a, s32 b)
|
rlm@1
|
54 {
|
rlm@1
|
55 return a < b;
|
rlm@1
|
56 }
|
rlm@1
|
57
|
rlm@1
|
58 static bool cheatSearchSignedLE(s32 a, s32 b)
|
rlm@1
|
59 {
|
rlm@1
|
60 return a <= b;
|
rlm@1
|
61 }
|
rlm@1
|
62
|
rlm@1
|
63 static bool cheatSearchSignedGT(s32 a, s32 b)
|
rlm@1
|
64 {
|
rlm@1
|
65 return a > b;
|
rlm@1
|
66 }
|
rlm@1
|
67
|
rlm@1
|
68 static bool cheatSearchSignedGE(s32 a, s32 b)
|
rlm@1
|
69 {
|
rlm@1
|
70 return a >= b;
|
rlm@1
|
71 }
|
rlm@1
|
72
|
rlm@1
|
73 static bool (*cheatSearchFunc[])(u32, u32) = {
|
rlm@1
|
74 cheatSearchEQ,
|
rlm@1
|
75 cheatSearchNE,
|
rlm@1
|
76 cheatSearchLT,
|
rlm@1
|
77 cheatSearchLE,
|
rlm@1
|
78 cheatSearchGT,
|
rlm@1
|
79 cheatSearchGE
|
rlm@1
|
80 };
|
rlm@1
|
81
|
rlm@1
|
82 static bool (*cheatSearchSignedFunc[])(s32, s32) = {
|
rlm@1
|
83 cheatSearchSignedEQ,
|
rlm@1
|
84 cheatSearchSignedNE,
|
rlm@1
|
85 cheatSearchSignedLT,
|
rlm@1
|
86 cheatSearchSignedLE,
|
rlm@1
|
87 cheatSearchSignedGT,
|
rlm@1
|
88 cheatSearchSignedGE
|
rlm@1
|
89 };
|
rlm@1
|
90
|
rlm@1
|
91 void cheatSearchSetSavedAndBits(CheatSearchBlock *block)
|
rlm@1
|
92 {
|
rlm@1
|
93 if (!block->saved)
|
rlm@1
|
94 {
|
rlm@1
|
95 block->saved = (u8 *)malloc(block->size);
|
rlm@1
|
96 memcpy(block->saved, block->data, block->size);
|
rlm@1
|
97 }
|
rlm@1
|
98 if (!block->bits)
|
rlm@1
|
99 {
|
rlm@1
|
100 block->bits = (u8 *)malloc(block->size >> 3);
|
rlm@1
|
101 memset(block->bits, 0xff, block->size >> 3);
|
rlm@1
|
102 }
|
rlm@1
|
103 }
|
rlm@1
|
104
|
rlm@1
|
105 void cheatSearchZeroBlock(CheatSearchBlock *block)
|
rlm@1
|
106 {
|
rlm@1
|
107 block->data = 0;
|
rlm@1
|
108 block->offset = 0;
|
rlm@1
|
109 block->size = 0;
|
rlm@1
|
110 free(block->saved);
|
rlm@1
|
111 free(block->bits);
|
rlm@1
|
112 block->saved = 0;
|
rlm@1
|
113 block->bits = 0;
|
rlm@1
|
114 }
|
rlm@1
|
115
|
rlm@1
|
116 void cheatSearchCleanup(CheatSearchData *cs)
|
rlm@1
|
117 {
|
rlm@1
|
118 int count = cs->count;
|
rlm@1
|
119
|
rlm@1
|
120 for (int i = 0; i < count; i++)
|
rlm@1
|
121 {
|
rlm@1
|
122 CheatSearchBlock &block = cs->blocks[i];
|
rlm@1
|
123 free(block.saved);
|
rlm@1
|
124 free(block.bits);
|
rlm@1
|
125 block.saved = 0;
|
rlm@1
|
126 block.bits = 0;
|
rlm@1
|
127 }
|
rlm@1
|
128 cs->count = 0;
|
rlm@1
|
129 }
|
rlm@1
|
130
|
rlm@1
|
131 void cheatSearchStart(const CheatSearchData *cs)
|
rlm@1
|
132 {
|
rlm@1
|
133 int count = cs->count;
|
rlm@1
|
134
|
rlm@1
|
135 for (int i = 0; i < count; i++)
|
rlm@1
|
136 {
|
rlm@1
|
137 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
138
|
rlm@1
|
139 memset(block->bits, 0xff, block->size >> 3);
|
rlm@1
|
140 memcpy(block->saved, block->data, block->size);
|
rlm@1
|
141 }
|
rlm@1
|
142 }
|
rlm@1
|
143
|
rlm@1
|
144 s32 cheatSearchSignedRead(u8 *data, int off, int size)
|
rlm@1
|
145 {
|
rlm@1
|
146 u32 res = data[off++];
|
rlm@1
|
147
|
rlm@1
|
148 switch (size)
|
rlm@1
|
149 {
|
rlm@1
|
150 case BITS_8:
|
rlm@1
|
151 res <<= 24;
|
rlm@1
|
152 return ((s32)res) >> 24;
|
rlm@1
|
153 case BITS_16:
|
rlm@1
|
154 res |= ((u32)data[off++])<<8;
|
rlm@1
|
155 res <<= 16;
|
rlm@1
|
156 return ((s32)res) >> 16;
|
rlm@1
|
157 case BITS_32:
|
rlm@1
|
158 res |= ((u32)data[off++])<<8;
|
rlm@1
|
159 res |= ((u32)data[off++])<<16;
|
rlm@1
|
160 res |= ((u32)data[off++])<<24;
|
rlm@1
|
161 return (s32)res;
|
rlm@1
|
162 }
|
rlm@1
|
163 return (s32)res;
|
rlm@1
|
164 }
|
rlm@1
|
165
|
rlm@1
|
166 u32 cheatSearchRead(u8 *data, int off, int size)
|
rlm@1
|
167 {
|
rlm@1
|
168 u32 res = data[off++];
|
rlm@1
|
169 if (size == BITS_16)
|
rlm@1
|
170 res |= ((u32)data[off++])<<8;
|
rlm@1
|
171 else if (size == BITS_32)
|
rlm@1
|
172 {
|
rlm@1
|
173 res |= ((u32)data[off++])<<8;
|
rlm@1
|
174 res |= ((u32)data[off++])<<16;
|
rlm@1
|
175 res |= ((u32)data[off++])<<24;
|
rlm@1
|
176 }
|
rlm@1
|
177 return res;
|
rlm@1
|
178 }
|
rlm@1
|
179
|
rlm@1
|
180 void cheatSearch(const CheatSearchData *cs, int compare, int size,
|
rlm@1
|
181 bool isSigned)
|
rlm@1
|
182 {
|
rlm@1
|
183 if (compare < 0 || compare > SEARCH_GE)
|
rlm@1
|
184 return;
|
rlm@1
|
185 int inc = 1;
|
rlm@1
|
186 if (size == BITS_16)
|
rlm@1
|
187 inc = 2;
|
rlm@1
|
188 else if (size == BITS_32)
|
rlm@1
|
189 inc = 4;
|
rlm@1
|
190
|
rlm@1
|
191 if (isSigned)
|
rlm@1
|
192 {
|
rlm@1
|
193 bool (*func)(s32, s32) = cheatSearchSignedFunc[compare];
|
rlm@1
|
194
|
rlm@1
|
195 for (int i = 0; i < cs->count; i++)
|
rlm@1
|
196 {
|
rlm@1
|
197 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
198 int size2 = block->size;
|
rlm@1
|
199 u8 *bits = block->bits;
|
rlm@1
|
200 u8 *data = block->data;
|
rlm@1
|
201 u8 *saved = block->saved;
|
rlm@1
|
202
|
rlm@1
|
203 for (int j = 0; j < size2; j += inc)
|
rlm@1
|
204 {
|
rlm@1
|
205 if (IS_BIT_SET(bits, j))
|
rlm@1
|
206 {
|
rlm@1
|
207 s32 a = cheatSearchSignedRead(data, j, size);
|
rlm@1
|
208 s32 b = cheatSearchSignedRead(saved, j, size);
|
rlm@1
|
209
|
rlm@1
|
210 if (!func(a, b))
|
rlm@1
|
211 {
|
rlm@1
|
212 CLEAR_BIT(bits, j);
|
rlm@1
|
213 if (size == BITS_16)
|
rlm@1
|
214 CLEAR_BIT(bits, j+1);
|
rlm@1
|
215 if (size == BITS_32)
|
rlm@1
|
216 {
|
rlm@1
|
217 CLEAR_BIT(bits, j+2);
|
rlm@1
|
218 CLEAR_BIT(bits, j+3);
|
rlm@1
|
219 }
|
rlm@1
|
220 }
|
rlm@1
|
221 }
|
rlm@1
|
222 }
|
rlm@1
|
223 }
|
rlm@1
|
224 }
|
rlm@1
|
225 else
|
rlm@1
|
226 {
|
rlm@1
|
227 bool (*func)(u32, u32) = cheatSearchFunc[compare];
|
rlm@1
|
228
|
rlm@1
|
229 for (int i = 0; i < cs->count; i++)
|
rlm@1
|
230 {
|
rlm@1
|
231 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
232 int size2 = block->size;
|
rlm@1
|
233 u8 *bits = block->bits;
|
rlm@1
|
234 u8 *data = block->data;
|
rlm@1
|
235 u8 *saved = block->saved;
|
rlm@1
|
236
|
rlm@1
|
237 for (int j = 0; j < size2; j += inc)
|
rlm@1
|
238 {
|
rlm@1
|
239 if (IS_BIT_SET(bits, j))
|
rlm@1
|
240 {
|
rlm@1
|
241 u32 a = cheatSearchRead(data, j, size);
|
rlm@1
|
242 u32 b = cheatSearchRead(saved, j, size);
|
rlm@1
|
243
|
rlm@1
|
244 if (!func(a, b))
|
rlm@1
|
245 {
|
rlm@1
|
246 CLEAR_BIT(bits, j);
|
rlm@1
|
247 if (size == BITS_16)
|
rlm@1
|
248 CLEAR_BIT(bits, j+1);
|
rlm@1
|
249 if (size == BITS_32)
|
rlm@1
|
250 {
|
rlm@1
|
251 CLEAR_BIT(bits, j+2);
|
rlm@1
|
252 CLEAR_BIT(bits, j+3);
|
rlm@1
|
253 }
|
rlm@1
|
254 }
|
rlm@1
|
255 }
|
rlm@1
|
256 }
|
rlm@1
|
257 }
|
rlm@1
|
258 }
|
rlm@1
|
259 }
|
rlm@1
|
260
|
rlm@1
|
261 void cheatSearchValue(const CheatSearchData *cs, int compare, int size,
|
rlm@1
|
262 bool isSigned, u32 value)
|
rlm@1
|
263 {
|
rlm@1
|
264 if (compare < 0 || compare > SEARCH_GE)
|
rlm@1
|
265 return;
|
rlm@1
|
266 int inc = 1;
|
rlm@1
|
267 if (size == BITS_16)
|
rlm@1
|
268 inc = 2;
|
rlm@1
|
269 else if (size == BITS_32)
|
rlm@1
|
270 inc = 4;
|
rlm@1
|
271
|
rlm@1
|
272 if (isSigned)
|
rlm@1
|
273 {
|
rlm@1
|
274 bool (*func)(s32, s32) = cheatSearchSignedFunc[compare];
|
rlm@1
|
275
|
rlm@1
|
276 for (int i = 0; i < cs->count; i++)
|
rlm@1
|
277 {
|
rlm@1
|
278 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
279 int size2 = block->size;
|
rlm@1
|
280 u8 *bits = block->bits;
|
rlm@1
|
281 u8 *data = block->data;
|
rlm@1
|
282
|
rlm@1
|
283 for (int j = 0; j < size2; j += inc)
|
rlm@1
|
284 {
|
rlm@1
|
285 if (IS_BIT_SET(bits, j))
|
rlm@1
|
286 {
|
rlm@1
|
287 s32 a = cheatSearchSignedRead(data, j, size);
|
rlm@1
|
288 s32 b = (s32)value;
|
rlm@1
|
289
|
rlm@1
|
290 if (!func(a, b))
|
rlm@1
|
291 {
|
rlm@1
|
292 CLEAR_BIT(bits, j);
|
rlm@1
|
293 if (size == BITS_16)
|
rlm@1
|
294 CLEAR_BIT(bits, j+1);
|
rlm@1
|
295 if (size == BITS_32)
|
rlm@1
|
296 {
|
rlm@1
|
297 CLEAR_BIT(bits, j+2);
|
rlm@1
|
298 CLEAR_BIT(bits, j+3);
|
rlm@1
|
299 }
|
rlm@1
|
300 }
|
rlm@1
|
301 }
|
rlm@1
|
302 }
|
rlm@1
|
303 }
|
rlm@1
|
304 }
|
rlm@1
|
305 else
|
rlm@1
|
306 {
|
rlm@1
|
307 bool (*func)(u32, u32) = cheatSearchFunc[compare];
|
rlm@1
|
308
|
rlm@1
|
309 for (int i = 0; i < cs->count; i++)
|
rlm@1
|
310 {
|
rlm@1
|
311 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
312 int size2 = block->size;
|
rlm@1
|
313 u8 *bits = block->bits;
|
rlm@1
|
314 u8 *data = block->data;
|
rlm@1
|
315
|
rlm@1
|
316 for (int j = 0; j < size2; j += inc)
|
rlm@1
|
317 {
|
rlm@1
|
318 if (IS_BIT_SET(bits, j))
|
rlm@1
|
319 {
|
rlm@1
|
320 u32 a = cheatSearchRead(data, j, size);
|
rlm@1
|
321
|
rlm@1
|
322 if (!func(a, value))
|
rlm@1
|
323 {
|
rlm@1
|
324 CLEAR_BIT(bits, j);
|
rlm@1
|
325 if (size == BITS_16)
|
rlm@1
|
326 CLEAR_BIT(bits, j+1);
|
rlm@1
|
327 if (size == BITS_32)
|
rlm@1
|
328 {
|
rlm@1
|
329 CLEAR_BIT(bits, j+2);
|
rlm@1
|
330 CLEAR_BIT(bits, j+3);
|
rlm@1
|
331 }
|
rlm@1
|
332 }
|
rlm@1
|
333 }
|
rlm@1
|
334 }
|
rlm@1
|
335 }
|
rlm@1
|
336 }
|
rlm@1
|
337 }
|
rlm@1
|
338
|
rlm@1
|
339 int cheatSearchGetCount(const CheatSearchData *cs, int size)
|
rlm@1
|
340 {
|
rlm@1
|
341 int res = 0;
|
rlm@1
|
342 int inc = 1;
|
rlm@1
|
343 if (size == BITS_16)
|
rlm@1
|
344 inc = 2;
|
rlm@1
|
345 else if (size == BITS_32)
|
rlm@1
|
346 inc = 4;
|
rlm@1
|
347
|
rlm@1
|
348 for (int i = 0; i < cs->count; i++)
|
rlm@1
|
349 {
|
rlm@1
|
350 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
351
|
rlm@1
|
352 int size2 = block->size;
|
rlm@1
|
353 u8 *bits = block->bits;
|
rlm@1
|
354 for (int j = 0; j < size2; j += inc)
|
rlm@1
|
355 {
|
rlm@1
|
356 if (IS_BIT_SET(bits, j))
|
rlm@1
|
357 res++;
|
rlm@1
|
358 }
|
rlm@1
|
359 }
|
rlm@1
|
360 return res;
|
rlm@1
|
361 }
|
rlm@1
|
362
|
rlm@1
|
363 void cheatSearchUpdateValues(const CheatSearchData *cs)
|
rlm@1
|
364 {
|
rlm@1
|
365 for (int i = 0; i < cs->count; i++)
|
rlm@1
|
366 {
|
rlm@1
|
367 CheatSearchBlock *block = &cs->blocks[i];
|
rlm@1
|
368
|
rlm@1
|
369 memcpy(block->saved, block->data, block->size);
|
rlm@1
|
370 }
|
rlm@1
|
371 }
|