Added example scripts missing from last commit (NPOTB).
7 #include "GameConfigs.h"
8 #include "MemoryUtils.h"
14 char *game_binary = NULL;
15 char *engine_binary = NULL;
16 char *wgame_binary = NULL;
17 char *wengine_binary = NULL;
19 int main(int argc, char **argv)
21 char *gamedata = NULL;
26 while ((opt = getopt(argc, argv, "b:de:f:g:x:w:y:")) != -1)
49 engine_binary = optarg;
53 wgame_binary = optarg;
57 wengine_binary = optarg;
61 printf("Usage: ./gdc -g <game> -e <engine name> -f <gamedata file> -b <game binary> -x <engine binary> -w <win game binary> -y <win engine binary>\n");
69 if (!game || !engine || !gamedata || !game_binary || !engine_binary || !wgame_binary || !wengine_binary)
71 printf("Usage: ./gdc -g <game> -e <engine name> -f <gamedata file> -b <game binary> -x <engine binary> -w <win game binary> -y <win engine binary>\n");
75 printf("Game: %s\n", game);
78 printf("Engine: %s\nGame binary: %s\nEngine binary: %s\nWin game binary: %s\nWin engine binary: %s\n",
79 engine, game_binary, engine_binary, wgame_binary, wengine_binary
82 printf("Gamedata: %s\n\n", gamedata);
85 ghandle = dlopen(game_binary, RTLD_LAZY);
88 printf("Couldn't open %s (%s)\n", game_binary, dlerror());
92 ehandle = dlopen(engine_binary, RTLD_LAZY);
95 printf("Couldn't open %s (%s)\n", engine_binary, dlerror());
99 int wgfile = open(wgame_binary, O_RDONLY);
102 printf("Couldn't open %s\n", wgame_binary);
106 int wefile = open(wengine_binary, O_RDONLY);
109 printf("Couldn't open %s\n", wengine_binary);
115 if (!gc.EnterFile(gamedata, err, sizeof(err)))
117 printf("%s: %s\n", gamedata, err);
122 if (!symbols.EnterFile("symbols.txt", err, sizeof(err)))
124 printf("symbols.txt: %s\n", err);
128 const char *vtsym = symbols.GetKeyValue("vtsym");
131 printf("Couldn't find vtsym\n");
135 void **vt = (void**) mu.ResolveSymbol(ghandle, vtsym);
138 printf("Couldn't find vtable %s\n", vtsym);
148 for (list<Offset>::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++)
152 printf("DEBUG %s - l: %d w: %d\n", it->name, it->lin, it->win);
155 const char *symbol = symbols.GetKeyValue(it->name);
160 strcpy(symvt, it->name);
161 strcat(symvt, "_vt");
162 const char *newvtsym = symbols.GetKeyValue(symvt);
163 if (newvtsym && newvtsym[0])
165 void **newvt = (void**) mu.ResolveSymbol(ghandle, newvtsym);
168 printf("O: %-22s - can't find, skipping\n", symvt);
172 newOffset = findVFunc(ghandle, newvt, symbol);
176 newOffset = findVFunc(ghandle, vt, symbol);
179 if (newOffset == it->lin)
181 printf("O: %-22s - GOOD. current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin);
185 printf("O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n",
188 newOffset - (it->lin - it->win), newOffset
194 printf("O: %-22s - no Linux symbol, skipping\n", it->name);
198 printf("\nWindows offsets are (semi-)wild guesses!\n\n");
200 for (list<Sig>::iterator it = gc.m_Sigs.begin(); it != gc.m_Sigs.end(); it++)
204 printf("DEBUG %s - %s - l: %s\n", it->name, it->lib == Server ? "server" : "engine", it->lin);
207 const char *linSymbol = it->lin;
208 const char *winSymbol = it->win;
209 bool hasLinux = (linSymbol && linSymbol[0]);
210 bool hasWindows = (winSymbol && winSymbol[0]);
211 if (!hasLinux && !hasWindows)
213 printf("S: %-22s - hasn't linux nor windows data, skipping\n", it->name);
219 if (it->lib == Server)
224 else if (it->lib == Engine)
231 printf("S: %-22s - isn't from server nor engine, skipping\n", it->name);
235 bool foundLinux = (!hasLinux || checkSigStringL(linHandle, linSymbol));
236 bool foundWindows = (!hasWindows || checkSigStringW(winFile, winSymbol));
238 // Prepare for ternery ABUSE
240 if (foundLinux && foundWindows)
242 // too much clutter to print current data if it matches anyway, unlike with offsets
244 printf("%-22s (%s) - GOOD. current:\n\t[w:%s]\n\t[l:%s]\n",
246 (it->lib == Server) ? "server" : "engine",
247 winSymbol ? winSymbol : "",
248 linSymbol ? linSymbol : ""
251 printf("S: %-22s (%s) - GOOD.\n",
253 (it->lib == Server) ? "server" : "engine"
258 // extra \n at end is intentional to add buffer after possibly long sigs
259 printf("S: %-22s (%s) - w: %s - l: %s\n%s%s%s%s%s%s%s%s\n",
261 (it->lib == Server) ? "server" : "engine",
262 hasWindows ? (foundWindows ? "GOOD" : "CHANGED") : "UNKNOWN",
263 hasLinux ? (foundLinux ? "GOOD" : "CHANGED") : "UNKNOWN",
265 hasWindows ? "\tcurrent - w: " : "",
266 (hasWindows && foundWindows) ? " (found) \"" : (hasWindows ? "(NOT found) \"" : ""),
267 (hasWindows && winSymbol) ? winSymbol : "",
268 hasWindows ? "\"\n" : "",
270 hasLinux ? "\tcurrent - l: " : "",
271 (hasLinux && foundLinux) ? " (found) \"" : (hasLinux ? "(NOT found) \"" : ""),
272 (hasLinux && linSymbol) ? linSymbol : "",
273 hasLinux ? "\"\n" : ""
278 // j/k, no way that anyone could have been prepared for that
284 bool checkSigStringW(int file, const char* symbol)
287 bool isAt = (symbol[0] == '@');
288 // we can't support this on windows from here
292 unsigned char real_sig[511];
293 size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol);
297 addr = mu.FindPatternInFile(file, (char*)real_sig, real_bytes);
306 bool checkSigStringL(void *handle, const char* symbol)
309 bool isAt = (symbol[0] == '@');
313 addr = mu.ResolveSymbol(handle, symbol + 1);
317 unsigned char real_sig[511];
318 size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol);
322 addr = mu.FindPattern(handle, (char*)real_sig, real_bytes);
333 takes a mangled member function symbol and returns the position where the function name and parameters start
334 01234567890123456789012345678
335 _ZN9CTFPlayer12ForceRespawnEv
338 void findFuncPos(const char *sym, int &func, int ¶ms)
341 while ((sym[i] < '0') || (sym[i] > '9')) i++;
342 int classLen = atoi(sym + i);
343 func = i + (int)ceil(log10(classLen)) + classLen;
344 int funcLen = atoi(sym + func);
345 params = func + (int)ceil(log10(funcLen)) + funcLen;
348 int findVFunc(void *handle, void **vt, const char *symbol)
351 int funcPos, paramPos;
352 findFuncPos(symbol, funcPos, paramPos);
356 for (int i = 0; i < 1000; i++)
361 if (!(s = mu.ResolveAddr(handle, pFunc)))
364 if ((i > 1) && (strncmp(s, "_ZTI", 4) == 0))
368 int tempFuncPos, tempParamPos;
369 findFuncPos(s, tempFuncPos, tempParamPos);
371 if (strcmp(s + tempFuncPos, symbol + funcPos) == 0)
381 unsigned int strncopy(char *dest, const char *src, size_t count)
389 while ((*src) && (--count))
395 return (dest - start);
398 size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
402 size_t len = vsnprintf(buffer, maxlength, fmt, ap);
405 if (len >= maxlength)
407 buffer[maxlength - 1] = '\0';
408 return (maxlength - 1);
416 size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr)
419 size_t length = strlen(hexstr);
421 for (size_t i = 0; i < length; i++)
423 if (written >= maxlength)
426 buffer[written++] = hexstr[i];
427 if (hexstr[i] == '\\' && hexstr[i + 1] == 'x')
431 /* Get the hex part. */
434 s_byte[0] = hexstr[i + 2];
435 s_byte[1] = hexstr[i + 3];
437 /* Read it as an integer */
438 sscanf(s_byte, "%x", &r_byte);
440 buffer[written - 1] = r_byte;