diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Memory.cpp | 106 | ||||
-rw-r--r-- | Source/Memory.h | 15 | ||||
-rw-r--r-- | Source/Source.vcxproj | 2 |
3 files changed, 79 insertions, 44 deletions
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"> |