diff options
| -rw-r--r-- | App/Main.cpp | 99 | ||||
| -rw-r--r-- | Source/Memory.cpp | 106 | ||||
| -rw-r--r-- | Source/Memory.h | 15 | ||||
| -rw-r--r-- | Source/Source.vcxproj | 2 |
4 files changed, 152 insertions, 70 deletions
| diff --git a/App/Main.cpp b/App/Main.cpp index 5adf22d..89765fb 100644 --- a/App/Main.cpp +++ b/App/Main.cpp | |||
| @@ -8,41 +8,41 @@ | |||
| 8 | #include <thread> | 8 | #include <thread> |
| 9 | 9 | ||
| 10 | #include "Memory.h" | 10 | #include "Memory.h" |
| 11 | #include <Random.h> | ||
| 11 | class Randomizer { | 12 | class Randomizer { |
| 12 | public: | 13 | public: |
| 13 | Randomizer(const std::shared_ptr<Memory>&) {} | 14 | Randomizer(const std::shared_ptr<Memory>&) {} |
| 14 | void Randomize() { | 15 | void Randomize(int seed) { |
| 15 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); | 16 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); |
| 16 | } | 17 | } |
| 18 | |||
| 19 | void RandomizeChallenge(int seed) { | ||
| 20 | Randomize(seed); | ||
| 21 | } | ||
| 17 | }; | 22 | }; |
| 18 | 23 | ||
| 19 | #define EXE_NAME L"witness64_d3d11.exe" | 24 | // Heartbeat is defined to 0x401 by Memory.h |
| 20 | #define HEARTBEAT 0x401 | ||
| 21 | #define RANDOMIZE_READY 0x402 | 25 | #define RANDOMIZE_READY 0x402 |
| 22 | #define RANDOMIZING 0403 | 26 | #define RANDOMIZING 0403 |
| 23 | #define RANDOMIZE_DONE 0x404 | 27 | #define RANDOMIZE_DONE 0x404 |
| 28 | #define RANDOMIZE_CHALLENGE_DONE 0x405 | ||
| 29 | #define CHALLENGE_ONLY 0x406 | ||
| 24 | 30 | ||
| 25 | // Globals | 31 | // Globals |
| 26 | HWND g_hwnd; | 32 | HWND g_hwnd; |
| 27 | HWND g_seed; | 33 | HWND g_seed; |
| 28 | HWND g_randomizerStatus; | 34 | HWND g_randomizerStatus; |
| 29 | HINSTANCE g_hInstance; | 35 | HINSTANCE g_hInstance; |
| 30 | auto g_witnessProc = std::make_shared<Memory>(); | 36 | auto g_witnessProc = std::make_shared<Memory>(L"witness64_d3d11.exe"); |
| 31 | std::shared_ptr<Randomizer> g_randomizer; | 37 | std::shared_ptr<Randomizer> g_randomizer; |
| 32 | 38 | ||
| 33 | // Notifications I need: | ||
| 34 | // Game shutdown | ||
| 35 | // Load game? | ||
| 36 | |||
| 37 | LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { | 39 | LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { |
| 38 | if (message == WM_DESTROY) { | 40 | if (message == WM_DESTROY) { |
| 39 | PostQuitMessage(0); | 41 | PostQuitMessage(0); |
| 40 | } else if (message == WM_COMMAND || message == WM_TIMER) { | 42 | } else if (message == WM_COMMAND || message == WM_TIMER) { |
| 41 | switch (LOWORD(wParam)) { | 43 | switch (LOWORD(wParam)) { |
| 42 | case HEARTBEAT: | 44 | case HEARTBEAT: |
| 43 | SetTimer(g_hwnd, HEARTBEAT, 1000, NULL); | 45 | switch ((ProcStatus)lParam) { |
| 44 | // Potential improvement: Change this call to be part of the HEARTBEAT message. | ||
| 45 | switch (g_witnessProc->Heartbeat(EXE_NAME)) { | ||
| 46 | case ProcStatus::NotRunning: | 46 | case ProcStatus::NotRunning: |
| 47 | // Shut down randomizer, wait for startup | 47 | // Shut down randomizer, wait for startup |
| 48 | if (g_randomizer) g_randomizer = nullptr; | 48 | if (g_randomizer) g_randomizer = nullptr; |
| @@ -60,21 +60,58 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) | |||
| 60 | } | 60 | } |
| 61 | break; | 61 | break; |
| 62 | case RANDOMIZE_READY: | 62 | case RANDOMIZE_READY: |
| 63 | SetWindowText(g_randomizerStatus, L"Randomize"); | ||
| 64 | EnableWindow(g_randomizerStatus, TRUE); | 63 | EnableWindow(g_randomizerStatus, TRUE); |
| 64 | if (IsDlgButtonChecked(hwnd, CHALLENGE_ONLY)) { | ||
| 65 | SetWindowText(g_randomizerStatus, L"Randomize Challenge"); | ||
| 66 | } else { | ||
| 67 | SetWindowText(g_randomizerStatus, L"Randomize"); | ||
| 68 | } | ||
| 65 | break; | 69 | break; |
| 66 | case RANDOMIZING: | 70 | case RANDOMIZING: |
| 67 | if (!g_randomizer) break; | 71 | if (!g_randomizer) { |
| 72 | assert(false); | ||
| 73 | break; | ||
| 74 | } | ||
| 68 | EnableWindow(g_randomizerStatus, FALSE); | 75 | EnableWindow(g_randomizerStatus, FALSE); |
| 69 | SetWindowText(g_randomizerStatus, L"Randomizing..."); | 76 | |
| 70 | std::thread([]{ | 77 | { |
| 71 | g_randomizer->Randomize(); | 78 | int seed = 0; |
| 72 | PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_DONE, NULL); | 79 | std::wstring text(128, L'\0'); |
| 73 | }).detach(); | 80 | int size = GetWindowText(g_seed, text.data(), static_cast<int>(text.size())); |
| 81 | if (size > 0) { // Set seed | ||
| 82 | seed = _wtoi(text.c_str()); | ||
| 83 | } else { // Random seed | ||
| 84 | seed = Random::RandInt(0, 999999); | ||
| 85 | SetWindowText(g_seed, std::to_wstring(seed).c_str()); | ||
| 86 | RedrawWindow(g_seed, NULL, NULL, RDW_UPDATENOW); | ||
| 87 | } | ||
| 88 | std::thread([hwnd, seed]{ | ||
| 89 | if (IsDlgButtonChecked(hwnd, CHALLENGE_ONLY)) { | ||
| 90 | SetWindowText(g_randomizerStatus, L"Randomizing Challenge..."); | ||
| 91 | g_randomizer->RandomizeChallenge(seed); | ||
| 92 | PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_CHALLENGE_DONE, NULL); | ||
| 93 | } else { | ||
| 94 | SetWindowText(g_randomizerStatus, L"Randomizing..."); | ||
| 95 | g_randomizer->Randomize(seed); | ||
| 96 | PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_DONE, NULL); | ||
| 97 | } | ||
| 98 | }).detach(); | ||
| 99 | } | ||
| 74 | break; | 100 | break; |
| 75 | case RANDOMIZE_DONE: | 101 | case RANDOMIZE_DONE: |
| 102 | EnableWindow(g_randomizerStatus, FALSE); | ||
| 76 | SetWindowText(g_randomizerStatus, L"Randomized!"); | 103 | SetWindowText(g_randomizerStatus, L"Randomized!"); |
| 77 | break; | 104 | break; |
| 105 | case RANDOMIZE_CHALLENGE_DONE: | ||
| 106 | EnableWindow(g_randomizerStatus, FALSE); | ||
| 107 | SetWindowText(g_randomizerStatus, L"Randomized Challenge!"); | ||
| 108 | break; | ||
| 109 | case CHALLENGE_ONLY: | ||
| 110 | CheckDlgButton(hwnd, CHALLENGE_ONLY, !IsDlgButtonChecked(hwnd, CHALLENGE_ONLY)); | ||
| 111 | if (IsWindowEnabled(g_randomizerStatus)) { | ||
| 112 | PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_READY, NULL); | ||
| 113 | } | ||
| 114 | break; | ||
| 78 | } | 115 | } |
| 79 | } | 116 | } |
| 80 | return DefWindowProc(hwnd, message, wParam, lParam); | 117 | return DefWindowProc(hwnd, message, wParam, lParam); |
| @@ -86,20 +123,26 @@ HWND CreateLabel(int x, int y, int width, LPCWSTR text) { | |||
| 86 | x, y, width, 16, g_hwnd, NULL, g_hInstance, NULL); | 123 | x, y, width, 16, g_hwnd, NULL, g_hInstance, NULL); |
| 87 | } | 124 | } |
| 88 | 125 | ||
| 89 | HWND CreateButton(int x, int y, int width, LPCWSTR text, int message) { | 126 | HWND CreateText(int x, int y, int width, LPCWSTR defaultText = L"") { |
| 127 | return CreateWindow(MSFTEDIT_CLASS, defaultText, | ||
| 128 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER, | ||
| 129 | x, y, width, 26, g_hwnd, NULL, g_hInstance, NULL); | ||
| 130 | } | ||
| 131 | |||
| 90 | #pragma warning(push) | 132 | #pragma warning(push) |
| 91 | #pragma warning(disable: 4312) | 133 | #pragma warning(disable: 4312) |
| 134 | HWND CreateButton(int x, int y, int width, LPCWSTR text, int message) { | ||
| 92 | return CreateWindow(L"BUTTON", text, | 135 | return CreateWindow(L"BUTTON", text, |
| 93 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, | 136 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, |
| 94 | x, y, width, 26, g_hwnd, (HMENU)message, g_hInstance, NULL); | 137 | x, y, width, 26, g_hwnd, (HMENU)message, g_hInstance, NULL); |
| 95 | #pragma warning(pop) | ||
| 96 | } | 138 | } |
| 97 | 139 | ||
| 98 | HWND CreateText(int x, int y, int width, LPCWSTR defaultText = L"") { | 140 | HWND CreateCheckbox(int x, int y, int message) { |
| 99 | return CreateWindow(MSFTEDIT_CLASS, L"", | 141 | return CreateWindow(L"BUTTON", L"", |
| 100 | WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER, | 142 | WS_VISIBLE | WS_CHILD | BS_CHECKBOX, |
| 101 | x, y, width, 26, g_hwnd, NULL, g_hInstance, NULL); | 143 | x, y, 12, 12, g_hwnd, (HMENU)message, g_hInstance, NULL); |
| 102 | } | 144 | } |
| 145 | #pragma warning(pop) | ||
| 103 | 146 | ||
| 104 | int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { | 147 | int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { |
| 105 | LoadLibrary(L"Msftedit.dll"); | 148 | LoadLibrary(L"Msftedit.dll"); |
| @@ -126,9 +169,13 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance | |||
| 126 | 169 | ||
| 127 | CreateLabel(390, 15, 90, L"Version: " VERSION_STR); | 170 | CreateLabel(390, 15, 90, L"Version: " VERSION_STR); |
| 128 | g_seed = CreateText(10, 10, 100); | 171 | g_seed = CreateText(10, 10, 100); |
| 129 | g_randomizerStatus = CreateButton(120, 10, 110, L"Randomize", RANDOMIZING); | 172 | g_randomizerStatus = CreateButton(120, 10, 180, L"Randomize", RANDOMIZING); |
| 130 | EnableWindow(g_randomizerStatus, FALSE); | 173 | EnableWindow(g_randomizerStatus, FALSE); |
| 131 | PostMessage(g_hwnd, WM_COMMAND, HEARTBEAT, NULL); | 174 | CreateCheckbox(10, 300, CHALLENGE_ONLY); |
| 175 | CreateLabel(30, 300, 200, L"Randomize the challenge only"); | ||
| 176 | EnableWindow(g_randomizerStatus, FALSE); | ||
| 177 | |||
| 178 | g_witnessProc->StartHeartbeat(g_hwnd); | ||
| 132 | 179 | ||
| 133 | ShowWindow(g_hwnd, nCmdShow); | 180 | ShowWindow(g_hwnd, nCmdShow); |
| 134 | UpdateWindow(g_hwnd); | 181 | UpdateWindow(g_hwnd); |
| diff --git a/Source/Memory.cpp b/Source/Memory.cpp index b0e2e9d..7b4b9c7 100644 --- a/Source/Memory.cpp +++ b/Source/Memory.cpp | |||
| @@ -2,25 +2,87 @@ | |||
| 2 | #include <psapi.h> | 2 | #include <psapi.h> |
| 3 | #include <tlhelp32.h> | 3 | #include <tlhelp32.h> |
| 4 | #include <iostream> | 4 | #include <iostream> |
| 5 | #include <string> | ||
| 5 | #include <cassert> | 6 | #include <cassert> |
| 6 | 7 | ||
| 7 | #undef PROCESSENTRY32 | 8 | #undef PROCESSENTRY32 |
| 8 | #undef Process32Next | 9 | #undef Process32Next |
| 9 | 10 | ||
| 11 | Memory::Memory(const std::wstring& processName) : _processName(processName) { | ||
| 12 | } | ||
| 13 | |||
| 14 | Memory::~Memory() { | ||
| 15 | if (_threadActive) { | ||
| 16 | _threadActive = false; | ||
| 17 | _thread.join(); | ||
| 18 | } | ||
| 19 | if (_handle != nullptr) { | ||
| 20 | CloseHandle(_handle); | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | void Memory::StartHeartbeat(HWND window, std::chrono::milliseconds beat) { | ||
| 25 | if (_threadActive) return; | ||
| 26 | _threadActive = true; | ||
| 27 | _thread = std::thread([sharedThis = shared_from_this(), window, beat]{ | ||
| 28 | while (sharedThis->_threadActive) { | ||
| 29 | sharedThis->Heartbeat(window); | ||
| 30 | std::this_thread::sleep_for(beat); | ||
| 31 | } | ||
| 32 | }); | ||
| 33 | _thread.detach(); | ||
| 34 | } | ||
| 35 | |||
| 36 | void Memory::Heartbeat(HWND window) { | ||
| 37 | if (!_handle && !Initialize()) { | ||
| 38 | // Couldn't initialize, definitely not running | ||
| 39 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::NotRunning); | ||
| 40 | return; | ||
| 41 | } | ||
| 42 | |||
| 43 | DWORD exitCode = 0; | ||
| 44 | assert(_handle); | ||
| 45 | GetExitCodeProcess(_handle, &exitCode); | ||
| 46 | if (exitCode != STILL_ACTIVE) { | ||
| 47 | // Process has exited, clean up. | ||
| 48 | _computedAddresses.clear(); | ||
| 49 | _handle = NULL; | ||
| 50 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::NotRunning); | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | |||
| 54 | #if GLOBALS == 0x5B28C0 | ||
| 55 | int currentFrame = ReadData<int>({0x5BE3B0}, 1)[0]; | ||
| 56 | #elif GLOBALS == 0x62D0A0 | ||
| 57 | int currentFrame = ReadData<int>({0x63954C}, 1)[0]; | ||
| 58 | #endif | ||
| 59 | int frameDelta = currentFrame - _previousFrame; | ||
| 60 | _previousFrame = currentFrame; | ||
| 61 | if (frameDelta < 0 && currentFrame < 250) { | ||
| 62 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::NewGame); | ||
| 63 | return; | ||
| 64 | } | ||
| 65 | |||
| 66 | // TODO: Some way to return ProcStatus::Randomized vs ProcStatus::NotRandomized vs ProcStatus::DeRandomized; | ||
| 67 | |||
| 68 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::Running); | ||
| 69 | } | ||
| 70 | |||
| 71 | |||
| 10 | [[nodiscard]] | 72 | [[nodiscard]] |
| 11 | bool Memory::Initialize(const std::wstring& processName) { | 73 | bool Memory::Initialize() { |
| 12 | // First, get the handle of the process | 74 | // First, get the handle of the process |
| 13 | PROCESSENTRY32W entry; | 75 | PROCESSENTRY32W entry; |
| 14 | entry.dwSize = sizeof(entry); | 76 | entry.dwSize = sizeof(entry); |
| 15 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | 77 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); |
| 16 | while (Process32NextW(snapshot, &entry)) { | 78 | while (Process32NextW(snapshot, &entry)) { |
| 17 | if (processName == entry.szExeFile) { | 79 | if (_processName == entry.szExeFile) { |
| 18 | _handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); | 80 | _handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); |
| 19 | break; | 81 | break; |
| 20 | } | 82 | } |
| 21 | } | 83 | } |
| 22 | if (!_handle) { | 84 | if (!_handle) { |
| 23 | std::cerr << "Couldn't find " << processName.c_str() << ", is it open?" << std::endl; | 85 | std::cerr << "Couldn't find " << _processName.c_str() << ", is it open?" << std::endl; |
| 24 | return false; | 86 | return false; |
| 25 | } | 87 | } |
| 26 | 88 | ||
| @@ -33,7 +95,7 @@ bool Memory::Initialize(const std::wstring& processName) { | |||
| 33 | for (DWORD i = 0; i < numModules / sizeof(HMODULE); i++) { | 95 | for (DWORD i = 0; i < numModules / sizeof(HMODULE); i++) { |
| 34 | int length = GetModuleBaseNameW(_handle, moduleList[i], &name[0], static_cast<DWORD>(name.size())); | 96 | int length = GetModuleBaseNameW(_handle, moduleList[i], &name[0], static_cast<DWORD>(name.size())); |
| 35 | name.resize(length); | 97 | name.resize(length); |
| 36 | if (processName == name) { | 98 | if (_processName == name) { |
| 37 | _baseAddress = (uintptr_t)moduleList[i]; | 99 | _baseAddress = (uintptr_t)moduleList[i]; |
| 38 | break; | 100 | break; |
| 39 | } | 101 | } |
| @@ -45,42 +107,6 @@ bool Memory::Initialize(const std::wstring& processName) { | |||
| 45 | return true; | 107 | return true; |
| 46 | } | 108 | } |
| 47 | 109 | ||
| 48 | ProcStatus Memory::Heartbeat(const std::wstring& processName) { | ||
| 49 | if (!_handle && !Initialize(processName)) { | ||
| 50 | // Couldn't initialize, definitely not running | ||
| 51 | return ProcStatus::NotRunning; | ||
| 52 | } | ||
| 53 | |||
| 54 | DWORD exitCode = 0; | ||
| 55 | GetExitCodeProcess(_handle, &exitCode); | ||
| 56 | if (exitCode != STILL_ACTIVE) { | ||
| 57 | // Process has exited, clean up. | ||
| 58 | _computedAddresses.clear(); | ||
| 59 | _handle = NULL; | ||
| 60 | return ProcStatus::NotRunning; | ||
| 61 | } | ||
| 62 | |||
| 63 | int currentFrame = 0x7FFFFFFF; | ||
| 64 | if (GLOBALS == 0x5B28C0) { | ||
| 65 | currentFrame = ReadData<int>({0x5BE3B0}, 1)[0]; | ||
| 66 | } else if (GLOBALS == 0x62D0A0) { | ||
| 67 | currentFrame = ReadData<int>({0x63954C}, 1)[0]; | ||
| 68 | } else { | ||
| 69 | assert(false); | ||
| 70 | } | ||
| 71 | if (currentFrame < 80) return ProcStatus::NewGame; | ||
| 72 | |||
| 73 | // TODO: Some way to return ProcStatus::Randomized vs ProcStatus::NotRandomized vs ProcStatus::DeRandomized; | ||
| 74 | |||
| 75 | return ProcStatus::Running; | ||
| 76 | } | ||
| 77 | |||
| 78 | Memory::~Memory() { | ||
| 79 | if (_handle != nullptr) { | ||
| 80 | CloseHandle(_handle); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | void Memory::AddSigScan(const std::vector<byte>& scanBytes, const std::function<void(int index)>& scanFunc) | 110 | void Memory::AddSigScan(const std::vector<byte>& scanBytes, const std::function<void(int index)>& scanFunc) |
| 85 | { | 111 | { |
| 86 | _sigScans[scanBytes] = {scanFunc, false}; | 112 | _sigScans[scanBytes] = {scanFunc, false}; |
| diff --git a/Source/Memory.h b/Source/Memory.h index d7552c5..c19d92b 100644 --- a/Source/Memory.h +++ b/Source/Memory.h | |||
| @@ -1,12 +1,14 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | #include <functional> | 2 | #include <functional> |
| 3 | #include <map> | 3 | #include <map> |
| 4 | #include <thread> | ||
| 4 | #include <vector> | 5 | #include <vector> |
| 5 | #include <windows.h> | 6 | #include <windows.h> |
| 6 | 7 | ||
| 7 | // #define GLOBALS 0x5B28C0 | 8 | // #define GLOBALS 0x5B28C0 |
| 8 | #define GLOBALS 0x62D0A0 | 9 | #define GLOBALS 0x62D0A0 |
| 9 | 10 | ||
| 11 | #define HEARTBEAT 0x401 | ||
| 10 | enum class ProcStatus { | 12 | enum class ProcStatus { |
| 11 | NotRunning, | 13 | NotRunning, |
| 12 | Running, | 14 | Running, |
| @@ -17,11 +19,11 @@ enum class ProcStatus { | |||
| 17 | // http://stackoverflow.com/q/32798185 | 19 | // http://stackoverflow.com/q/32798185 |
| 18 | // http://stackoverflow.com/q/36018838 | 20 | // http://stackoverflow.com/q/36018838 |
| 19 | // http://stackoverflow.com/q/1387064 | 21 | // http://stackoverflow.com/q/1387064 |
| 20 | class Memory { | 22 | class Memory final : public std::enable_shared_from_this<Memory> { |
| 21 | public: | 23 | public: |
| 22 | Memory() = default; | 24 | Memory(const std::wstring& processName); |
| 23 | ProcStatus Heartbeat(const std::wstring& processName); | ||
| 24 | ~Memory(); | 25 | ~Memory(); |
| 26 | void StartHeartbeat(HWND window, std::chrono::milliseconds beat = std::chrono::milliseconds(1000)); | ||
| 25 | 27 | ||
| 26 | Memory(const Memory& memory) = delete; | 28 | Memory(const Memory& memory) = delete; |
| 27 | Memory& operator=(const Memory& other) = delete; | 29 | Memory& operator=(const Memory& other) = delete; |
| @@ -74,10 +76,15 @@ private: | |||
| 74 | ThrowError(); | 76 | ThrowError(); |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | bool Initialize(const std::wstring& processName); | 79 | void Heartbeat(HWND window); |
| 80 | bool Initialize(); | ||
| 78 | void ThrowError(); | 81 | void ThrowError(); |
| 79 | void* ComputeOffset(std::vector<int> offsets); | 82 | void* ComputeOffset(std::vector<int> offsets); |
| 80 | 83 | ||
| 84 | int _previousFrame = 0; | ||
| 85 | bool _threadActive = false; | ||
| 86 | std::thread _thread; | ||
| 87 | std::wstring _processName; | ||
| 81 | std::map<uintptr_t, uintptr_t> _computedAddresses; | 88 | std::map<uintptr_t, uintptr_t> _computedAddresses; |
| 82 | uintptr_t _baseAddress = 0; | 89 | uintptr_t _baseAddress = 0; |
| 83 | HANDLE _handle = nullptr; | 90 | HANDLE _handle = nullptr; |
| diff --git a/Source/Source.vcxproj b/Source/Source.vcxproj index 3e66f83..e7f716c 100644 --- a/Source/Source.vcxproj +++ b/Source/Source.vcxproj | |||
| @@ -158,9 +158,11 @@ | |||
| 158 | </ItemDefinitionGroup> | 158 | </ItemDefinitionGroup> |
| 159 | <ItemGroup> | 159 | <ItemGroup> |
| 160 | <ClInclude Include="Memory.h" /> | 160 | <ClInclude Include="Memory.h" /> |
| 161 | <ClInclude Include="Random.h" /> | ||
| 161 | </ItemGroup> | 162 | </ItemGroup> |
| 162 | <ItemGroup> | 163 | <ItemGroup> |
| 163 | <ClCompile Include="Memory.cpp" /> | 164 | <ClCompile Include="Memory.cpp" /> |
| 165 | <ClCompile Include="Random.cpp" /> | ||
| 164 | </ItemGroup> | 166 | </ItemGroup> |
| 165 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | 167 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
| 166 | <ImportGroup Label="ExtensionTargets"> | 168 | <ImportGroup Label="ExtensionTargets"> |
