rendered paste body#include "Hooks.h"#include "AsmRewrites.h"#include <stdio.h>namespace Hooks{char g_sReplayName[MAX_PATH]; // If only replay names could have 260 characters :|const char* g_sReplayNameFormat = "%s-%s.%04d-%02d-%02d.%02d-%02d-%02d%s";const char* g_sPlayback = "playback:";void Init(){ HMODULE hSoulstorm = GetModuleHandle(NULL); // Insert one hook to grab the name of the replay unsigned char* pCallToOpenReplay = AsmRewrites::Find((unsigned char*)hSoulstorm, (unsigned char*)"\xE8\x0B\xAE\x06\x00\x84\xC0\x74\xDA\x8B", 10); AsmRewrites::HookOverCall(pCallToOpenReplay, (unsigned char*)CaptureReplayTitle_Thunk); // Insert one patch to change the name of the replay file unsigned char* pCallInOpenReplay = AsmRewrites::Find((unsigned char*)hSoulstorm, (unsigned char*)"\x68\x50\xB0\x7A\x00\x50\xFF\x15\x70\x39", 10); AsmRewrites::ApplyPatch(pCallInOpenReplay, 21, (unsigned char*)ChangeReplayFilename_Patch);}void Cleanup(){ // I'm lazy, don't want to clean up}__declspec(naked) void __cdecl CaptureReplayTitle_Thunk() { __asm{ // Save important registers push eax; push ebx; push ecx; push edx; push esi; // Call CaptureReplayTitle push [esp+108h+40]; call CaptureReplayTitle; // Restore important registers pop esi; pop edx; pop ecx; pop ebx; pop eax; // Finish ret;}}void __stdcall CaptureReplayTitle(const wchar_t* sReplayName){ sprintf(g_sReplayName, "%S", sReplayName); // Filenames cannot contain certain characters, so change them to '_' for(char* s = g_sReplayName; *s; ++s) { if( *s == '\\' || *s == '/' || *s == ':' || *s == '*' || *s == '?' || *s == '\"' || *s == '<' || *s == '>' || *s == '|') { *s = '_'; } }}__declspec(naked) void __cdecl ChangeReplayFilename_Patch() { __asm{ lea ecx, g_sReplayName; push ecx; mov ecx, dword ptr g_sReplayNameFormat; push ecx; push eax; call ds:sprintf; mov ecx, dword ptr g_sPlayback; add esp, 44; nop; nop; nop; nop; nop; // Space for a JMP to be written back to the original code}}};