Files
goldsrc-cheat/src/main.c

206 lines
6.2 KiB
C

#include <ctype.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "include/main.h"
#include "include/sdk.h"
#include "include/globals.h"
#include "include/settings.h"
#include "include/hooks.h"
#include "include/util.h"
#include "include/game_detection.h"
static bool loaded = false;
void debug_log(const char* message) {
FILE* logfile = fopen("/tmp/cheat-unload-debug.log", "a");
if (logfile) {
time_t now = time(NULL);
char timestamp[64];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", localtime(&now));
fprintf(logfile, "[%s] %s\n", timestamp, message);
fclose(logfile);
}
}
void safe_unload_with_debug(void) {
debug_log("Starting safe unload with debug logging");
char buf[256];
snprintf(buf, sizeof(buf), "Function addresses - self_unload: %p, unload: %p, hooks_restore: %p",
(void*)self_unload, (void*)unload, (void*)hooks_restore);
debug_log(buf);
debug_log("Resetting all settings to default values");
i_engine->pfnClientCmd("echo \"Step 0: Resetting all settings...\"");
settings_reset();
i_engine->pfnClientCmd("echo \"Step 1: Unhooking functions...\"");
debug_log("Unhooking all functions");
debug_log("Restoring OpenGL hooks");
debug_log("Restoring VMT hooks");
hooks_restore();
debug_log("Restoring globals");
globals_restore();
debug_log("Removing custom commands");
i_engine->pfnClientCmd("echo \"Step 2: Removing custom commands...\"");
debug_log("Waiting for hooks to settle");
i_engine->pfnClientCmd("echo \"Step 3: Waiting for hooks to settle...\"");
usleep(250000);
debug_log("Beginning library unload sequence");
i_engine->pfnClientCmd("echo \"Step 4: Unloading library...\"");
void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD);
snprintf(buf, sizeof(buf), "dlopen result: %p", self);
debug_log(buf);
if (self) {
/* Close the call we just made to dlopen() */
debug_log("Closing first dlopen reference");
int result = dlclose(self);
snprintf(buf, sizeof(buf), "First dlclose result: %d", result);
debug_log(buf);
/* Close the call our injector made */
debug_log("Closing second dlopen reference");
result = dlclose(self);
snprintf(buf, sizeof(buf), "Second dlclose result: %d", result);
debug_log(buf);
} else {
debug_log("ERROR: Failed to get handle to library");
const char* error = dlerror();
if (error) {
debug_log(error);
i_engine->pfnClientCmd("echo \"ERROR: Failed to get handle to library\"");
}
}
debug_log("Safe unload completed");
i_engine->pfnClientCmd("echo \"Unload procedure completed\"");
}
void UNINJECT_CommandHandler(void) {
i_engine->pfnClientCmd("echo \"Uninjecting goldsource-cheat with debug logging...\"");
safe_unload_with_debug();
}
void MENU_CommandHandler(void) {
extern bool g_menu_open;
g_menu_open = !g_menu_open;
i_engine->Con_Printf("Menu toggled to %s\n", g_menu_open ? "open" : "closed");
}
__attribute__((constructor))
void load(void) {
printf("goldsource-cheat injected!\n");
if (!globals_init()) {
fprintf(stderr, "goldsource-cheat: load: error loading globals, aborting\n");
self_unload();
return;
}
settings_init();
if (!hooks_init()) {
fprintf(stderr, "goldsource-cheat: load: error hooking functions, aborting\n");
self_unload();
return;
}
i_engine->pfnAddCommand("dz_uninject", UNINJECT_CommandHandler);
i_engine->pfnAddCommand("dz_menu", MENU_CommandHandler);
i_engine->pfnClientCmd("bind INS dz_menu");
i_engine->Con_Printf("Bound INSERT key to menu toggle\n");
if (IsCS16()) {
i_engine->pfnClientCmd("play weapons/knife_deploy1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsDayOfDefeat()) {
i_engine->pfnClientCmd("play weapons/kar_cock.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsTFC()) {
i_engine->pfnClientCmd("play misc/party2.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else if (IsDeathmatchClassic()) {
i_engine->pfnClientCmd("play items/r_item1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
else
{
i_engine->pfnClientCmd("play weapons/cbar_hit1.wav");
i_engine->pfnClientCmd("speak \"Cheat successfully loaded\"");
}
i_engine->pfnClientCmd("echo \"goldsource-cheat loaded successfully!\"");
i_engine->pfnClientCmd("echo \"Deadzone rulez!\"");
i_engine->pfnClientCmd("echo \"https://git.deadzone.lol/Wizzard/goldsrc-cheat\"");
GameType game = get_current_game();
switch(game) {
case GAME_HALFLIFE:
i_engine->pfnClientCmd("echo \"Detected Game: Half-Life 1\"");
break;
case GAME_CS16:
i_engine->pfnClientCmd("echo \"Detected Game: Counter-Strike 1.6\"");
break;
case GAME_DAY_OF_DEFEAT:
i_engine->pfnClientCmd("echo \"Detected Game: Day of Defeat\"");
break;
case GAME_TFC:
i_engine->pfnClientCmd("echo \"Detected Game: Team Fortress Classic\"");
break;
case GAME_DMC:
i_engine->pfnClientCmd("echo \"Detected Game: Deathmatch Classic\"");
break;
case GAME_SL:
i_engine->pfnClientCmd("echo \"Detected Game: Space Life: Finley's Revenge\"");
break;
default:
i_engine->pfnClientCmd("echo \"Detected Game: Unknown Game\"");
break;
}
loaded = true;
}
__attribute__((destructor))
void unload(void) {
if (loaded) {
settings_reset();
globals_restore();
hooks_restore();
}
printf("goldsource-cheat unloaded.\n\n");
}
void self_unload(void) {
void* self = dlopen("libhlcheat.so", RTLD_LAZY | RTLD_NOLOAD);
if (self) {
dlclose(self);
dlclose(self);
}
}