Skip to content

Commit

Permalink
WIP s10 port
Browse files Browse the repository at this point in the history
  • Loading branch information
Kethen committed Sep 27, 2024
1 parent 0e90d62 commit 8ef2899
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 39 deletions.
12 changes: 12 additions & 0 deletions d3d9.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[GlobalSets]
LoadPlugins=1
LoadFromScriptsOnly=0
DontLoadFromDllMain=0
;LoadFromAPI=GetSystemTimeAsFileTime
FindModule=0
UseD3D8to9=0
DisableCrashDumps=0
Direct3D8DisableMaximizedWindowedModeShim=0

[FileLoader]
OverloadFromFolder=update
94 changes: 55 additions & 39 deletions s4_league_fps_unlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ NtSetTimerResolution(

static ULONG min_nt_delay_100ns;

#define ENABLE_LOGGING 0
#define ENABLE_LOGGING 1

#if ENABLE_LOGGING
FILE *log_file = NULL;
Expand Down Expand Up @@ -224,18 +224,18 @@ struct __attribute__ ((packed)) game_context{
uint8_t fps_limiter_toggle;
};

static struct game_context *(*fetch_game_context)(void) = (struct game_context *(*)(void)) 0x004ad790;
static void (__attribute__((thiscall)) *update_time_delta)(struct time_context *ctx) = (void (__attribute__((thiscall)) *)(struct time_context *ctx)) 0x00ff7f30;
static struct game_context *(*fetch_game_context)(void) = (struct game_context *(*)(void)) 0x004aeb70;
static void (__attribute__((thiscall)) *update_time_delta)(struct time_context *ctx) = (void (__attribute__((thiscall)) *)(struct time_context *ctx)) 0x010ada90;

// contains actor state
struct ctx_01642f30{
struct ctx_01b29540{
uint8_t unknown[0xb0];
uint8_t actor_state;
uint8_t unknown_2[0x3];
uint32_t actor_substate_1;
uint32_t actor_substate_2;
};
static struct ctx_01642f30 *(*fetch_ctx_01642f30)(void) = (struct ctx_01642f30 *(*)(void)) 0x004ae0a0;
static struct ctx_01b29540 *(*fetch_ctx_01b29540)(void) = (struct ctx_01b29540 *(*)(void)) 0x004af440;

struct funny_value{
uint32_t value_xor;
Expand Down Expand Up @@ -497,7 +497,9 @@ void __attribute__((thiscall)) patched_move_actor_by(struct move_actor_by_ctx *c

void *ret_addr = __builtin_return_address(0);

struct ctx_01642f30* actx = fetch_ctx_01642f30();
struct ctx_01b29540* actx = fetch_ctx_01b29540();

// something odd is happening here after porting from s8 to s10, might have to reserve a float register here somehow

LOG_VERBOSE("%s: ctx 0x%08x, param_1 %f, param_2 %f, param_3 %f", __FUNCTION__, ctx, param_1, param_2, param_3);
LOG_VERBOSE("%s: called from 0x%08x -> 0x%08x -> 0x%08x", __FUNCTION__, __builtin_return_address(2), __builtin_return_address(1), ret_addr);
Expand All @@ -509,7 +511,7 @@ void __attribute__((thiscall)) patched_move_actor_by(struct move_actor_by_ctx *c

float y = param_2;
// in air
if(ret_addr == (void*)0x00527467){
if(ret_addr == (void*)0x0052c487){
// fly
static bool was_flying = false;
bool flying = false;
Expand Down Expand Up @@ -577,10 +579,10 @@ void __attribute__((thiscall)) patched_move_actor_by(struct move_actor_by_ctx *c
}

// on ground
if(ret_addr == (void *)0x00526f0e){
if(ret_addr == (void *)0x0052bf2e){
}

if(ret_addr == (void *)0x00526f0e || ret_addr == (void*)0x00527467){
if(ret_addr == (void *)0x0052c487 || ret_addr == (void*)0x0052bf2e){
LOG_VERBOSE("%s: ctx 0x%08x, param_1 %f, param_2 %f, param_3 %f", __FUNCTION__, ctx, param_1, param_2, param_3);
LOG_VERBOSE("%s: called from 0x%08x -> 0x%08x -> 0x%08x", __FUNCTION__, __builtin_return_address(2), __builtin_return_address(1), __builtin_return_address(0));
LOG_VERBOSE("%s: actx->actor_state %u", __FUNCTION__, actx->actor_state);
Expand All @@ -595,12 +597,12 @@ static void hook_move_actor_by(){
uint8_t intended_trampoline[] = {
// space for original instruction
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// MOV eax,0x0051c2fa
0xb8, 0xfa, 0xc2, 0x51, 0x00,
// MOV eax,0052103a
0xb8, 0x3a, 0x10, 0x52, 0x00,
// JMP eax
0xff, 0xe0
};
memcpy((void *)intended_trampoline, (void *)0x0051c2f0, 10);
memcpy((void *)intended_trampoline, (void *)0x00521030, 10);

uint8_t intended_patch[] = {
// MOV eax, patched_move_actor_by
Expand All @@ -617,9 +619,10 @@ static void hook_move_actor_by(){
DWORD old_protect;
VirtualProtect((void *)orig_move_actor_by, sizeof(intended_trampoline), PAGE_EXECUTE_READ, &old_protect);

memcpy((void *)0x0051c2f0, intended_patch, sizeof(intended_patch));
memcpy((void *)0x00521030, intended_patch, sizeof(intended_patch));
}

// TODO find s10 offset, this function is also not used at the moment
// it seems that every intended coord change goes here, then it gets processed before applied
struct __attribute__ ((packed)) move_actor_exact_ctx{
// float 0x684 x, 0x688 y, 0x68c z
Expand Down Expand Up @@ -698,31 +701,31 @@ static void redirect_speed_dampeners(){
memcpy(&speed_dampeners[i], value, sizeof value);
}

uint32_t *patch_location = (uint32_t *)0x00563c0e;
uint32_t *patch_location = (uint32_t *)0x0056b25e;
*patch_location = (uint32_t)&speed_dampeners[0];

patch_location = (uint32_t *)0x007b063d;
patch_location = (uint32_t *)0x007d040d;
*patch_location = (uint32_t)&speed_dampeners[1];

patch_location = (uint32_t *)0x007b06aa;
patch_location = (uint32_t *)0x007d047a;
*patch_location = (uint32_t)&speed_dampeners[2];

patch_location = (uint32_t *)0x007b1204;
patch_location = (uint32_t *)0x007d0fd4;
*patch_location = (uint32_t)&speed_dampeners[3];

patch_location = (uint32_t *)0x007b120c;
patch_location = (uint32_t *)0x007d0fdc;
*patch_location = (uint32_t)&speed_dampeners[4];

patch_location = (uint32_t *)0x007b1973;
patch_location = (uint32_t *)0x007d1743;
*patch_location = (uint32_t)&speed_dampeners[5];

patch_location = (uint32_t *)0x007b19a9;
patch_location = (uint32_t *)0x007d1779;
*patch_location = (uint32_t)&speed_dampeners[6];

patch_location = (uint32_t *)0x007b1edc;
patch_location = (uint32_t *)0x007d1cac;
*patch_location = (uint32_t)&speed_dampeners[7];

patch_location = (uint32_t *)0x007b2363;
patch_location = (uint32_t *)0x007d2133;
*patch_location = (uint32_t)&speed_dampeners[8];
}

Expand All @@ -737,8 +740,13 @@ void __attribute__((thiscall)) patched_game_tick(void *tick_ctx){

static struct time_context tctx;

struct game_context *ctx = fetch_game_context();
LOG_VERBOSE("game context at 0x%08x", (uint32_t)ctx);

bool should_limit = ctx->fps_limiter_toggle != 0;

pthread_mutex_lock(&config_mutex);
if(config.max_framerate > 0){
if(config.max_framerate > 0 && should_limit){
static struct timespec last_tick = {0};
struct timespec this_tick;
clock_gettime(CLOCK_MONOTONIC, &this_tick);
Expand Down Expand Up @@ -788,11 +796,10 @@ void __attribute__((thiscall)) patched_game_tick(void *tick_ctx){
}
pthread_mutex_unlock(&config_mutex);

struct game_context *ctx = fetch_game_context();
LOG_VERBOSE("game context at 0x%08x", (uint32_t)ctx);
uint8_t fps_limiter_toggle_orig = ctx->fps_limiter_toggle;
ctx->fps_limiter_toggle = 0;

orig_game_tick(tick_ctx);
ctx->fps_limiter_toggle = fps_limiter_toggle_orig;

update_time_delta(&tctx);

Expand All @@ -814,20 +821,19 @@ static void hook_game_tick(){
uint8_t intended_trampoline[] = {
// original 9 bytes
0, 0, 0, 0, 0, 0, 0, 0, 0,
// MOV EAX,0x00871979
0xb8, 0x79, 0x19, 0x87, 0x00,
// MOV EAX,0x0089f409
0xb8, 0x09, 0xf4, 0x89, 0x00,
// JMP EAX
0xff, 0xe0
};
memcpy(intended_trampoline, (void *)0x00871970, 9);
memcpy(intended_trampoline, (void *)0x0089f400, 9);
DWORD old_protect;
orig_game_tick = (void (__attribute__((thiscall)) *)(void *)) VirtualAlloc(NULL, sizeof(intended_trampoline), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

memcpy((void *)orig_game_tick, intended_trampoline, sizeof(intended_trampoline));
VirtualProtect((void *)orig_game_tick, sizeof(intended_trampoline), PAGE_EXECUTE_READ, &old_protect);

uint32_t patched_function_location = (uint32_t)patched_game_tick;
uint8_t *patch_location = (uint8_t*)0x00871970;
uint8_t intended_patch[] = {
// MOV EAX,patched_game_tick
0xb8, 0, 0, 0, 0,
Expand All @@ -837,7 +843,7 @@ static void hook_game_tick(){
0x90, 0x90
};
memcpy((void *)&intended_patch[1], (void *)&patched_function_location, 4);
memcpy((void *)0x00871970, intended_patch, sizeof(intended_patch));
memcpy((void *)0x0089f400, intended_patch, sizeof(intended_patch));
}

static void patch_min_frametime(double min_frametime){
Expand Down Expand Up @@ -875,8 +881,7 @@ static void prepare_nt_timer(){
LOG("NtDelayExecution now has a %u * 100ns resolution accuracy", min_nt_delay_100ns);
}

__attribute__((constructor))
int init(){
static void *delayed_init_thread(void *arg){
#if ENABLE_LOGGING
log_file = fopen("s4_league_fps_unlock.log", "w");
if(pthread_mutex_init(&log_mutex, NULL)){
Expand All @@ -889,29 +894,40 @@ int init(){
printf("config mutex init failed\n");
return 0;
}
LOG("delayed init thread started");
sleep(5);

LOG("mhmm library loaded");
// might need to pause all threads here before hooking

prepare_nt_timer();

parse_config();


redirect_speed_dampeners();


hook_game_tick();
//hook_move_actor_exact();
hook_move_actor_by();
//hook_switch_weapon_slot();
hook_fun_005e4020();
hook_fun_00766000();
hook_calculate_weapon_spread();
//hook_fun_005e4020();
//hook_fun_00766000();
//hook_calculate_weapon_spread();

experinmental_static_patches();

LOG("now starting main thread");
pthread_t thread;
pthread_create(&thread, NULL, main_thread, NULL);

prepare_nt_timer();
return NULL;
}

__attribute__((constructor))
int init(){
pthread_t thread;
pthread_create(&thread, NULL, delayed_init_thread, NULL);

LOG("gcc constructor ending");
return 0;
}

0 comments on commit 8ef2899

Please sign in to comment.