summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--App/Main.cpp87
-rw-r--r--Source/Memory.cpp25
-rw-r--r--Source/Memory.h8
3 files changed, 80 insertions, 40 deletions
diff --git a/App/Main.cpp b/App/Main.cpp index 2484577..b018892 100644 --- a/App/Main.cpp +++ b/App/Main.cpp
@@ -4,70 +4,103 @@
4 4
5#include <cassert> 5#include <cassert>
6#include <iostream> 6#include <iostream>
7#include <string>
8#include <thread>
7 9
8#include "Memory.h" 10#include "Memory.h"
11class Randomizer {
12public:
13 Randomizer(const std::shared_ptr<Memory>&) {}
14 void Randomize() {
15 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
16 }
17};
9 18
10#define EXE_NAME L"witness64_d3d11.exe" 19#define EXE_NAME L"witness64_d3d11.exe"
11
12#define PROC_ATTACH 0x401 20#define PROC_ATTACH 0x401
13#define IDC_TOGGLESPEED 0x402 21#define RANDOMIZE_READY 0x402
14#define IDC_SPEEDRUNNER 0x403 22#define RANDOMIZING 0403
15#define IDC_HARDMODE 0x404 23#define RANDOMIZE_DONE 0x404
16#define IDC_READ 0x405 24#define CHECK_NEWGAME 0x405
17#define IDC_RANDOM 0x406
18#define IDC_WRITE 0x407
19#define IDC_DUMP 0x408
20#define IDT_RANDOMIZED 0x409
21#define IDC_TOGGLELASERS 0x410
22#define IDC_TOGGLESNIPES 0x411
23 25
24// Globals 26// Globals
25HWND g_hwnd; 27HWND g_hwnd;
28HWND g_seed;
29HWND g_randomizerStatus;
26HINSTANCE g_hInstance; 30HINSTANCE g_hInstance;
27auto g_witnessProc = std::make_shared<Memory>(); 31auto g_witnessProc = std::make_shared<Memory>();
32std::shared_ptr<Randomizer> g_randomizer;
33
34// Notifications I need:
35// Game shutdown
36// Load game?
28 37
29LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { 38LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
30 if (message == WM_DESTROY) { 39 if (message == WM_DESTROY) {
31 PostQuitMessage(0); 40 PostQuitMessage(0);
32 } else if (message == WM_COMMAND) { 41 } else if (message == WM_COMMAND || message == WM_TIMER) {
33 switch (LOWORD(wParam)) { 42 switch (LOWORD(wParam)) {
34 case PROC_ATTACH: 43 case PROC_ATTACH:
35 if (!g_witnessProc->Initialize(EXE_NAME)) { 44 if (!g_witnessProc->Initialize(EXE_NAME)) {
36 OutputDebugString(L"Failed to initialize, trying again in 5 seconds"); 45 SetTimer(g_hwnd, PROC_ATTACH, 1000, NULL); // Retry in 1s
37 SetTimer(g_hwnd, PROC_ATTACH, 5000, NULL); // Re-attach in 10s 46 } else {
47 g_randomizer = std::make_shared<Randomizer>(g_witnessProc);
48 PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_READY, NULL);
49 SetTimer(g_hwnd, CHECK_NEWGAME, 1000, NULL); // Start checking for new game
50 }
51 break;
52 case CHECK_NEWGAME:
53 if (g_witnessProc) {
54 // It shouldn't be possible to pause earlier than this, so subsequent checks will fail.
55 if (g_witnessProc->GetCurrentFrame() < 80) { // New game
56 SetWindowText(g_seed, L"");
57 PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_READY, NULL);
58 }
59 SetTimer(g_hwnd, CHECK_NEWGAME, 1000, NULL); // Continue checking for new game
38 } 60 }
39 break; 61 break;
40 case IDC_TOGGLELASERS: 62 case RANDOMIZE_READY:
41 OutputDebugString(L"Hello, world!"); 63 SetWindowText(g_randomizerStatus, L"Randomize");
64 EnableWindow(g_randomizerStatus, TRUE);
65 break;
66 case RANDOMIZING:
67 if (!g_randomizer) break;
68 SetWindowText(g_randomizerStatus, L"Randomizing...");
69 std::thread([]{
70 g_randomizer->Randomize();
71 PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_DONE, NULL);
72 }).detach();
73 break;
74 case RANDOMIZE_DONE:
75 SetWindowText(g_randomizerStatus, L"Randomized!");
42 break; 76 break;
43 default: 77 default:
44 assert(false);
45 break; 78 break;
46 } 79 }
47 } 80 }
48 return DefWindowProc(hwnd, message, wParam, lParam); 81 return DefWindowProc(hwnd, message, wParam, lParam);
49} 82}
50 83
51void CreateLabel(int x, int y, int width, LPCWSTR text) { 84HWND CreateLabel(int x, int y, int width, LPCWSTR text) {
52 CreateWindow(L"STATIC", text, 85 return CreateWindow(L"STATIC", text,
53 WS_TABSTOP | WS_VISIBLE | WS_CHILD | SS_LEFT, 86 WS_TABSTOP | WS_VISIBLE | WS_CHILD | SS_LEFT,
54 x, y, width, 16, g_hwnd, NULL, g_hInstance, NULL); 87 x, y, width, 16, g_hwnd, NULL, g_hInstance, NULL);
55} 88}
56 89
57void CreateButton(int x, int y, int width, LPCWSTR text, int message) { 90HWND CreateButton(int x, int y, int width, LPCWSTR text, int message) {
58#pragma warning(push) 91#pragma warning(push)
59#pragma warning(disable: 4312) 92#pragma warning(disable: 4312)
60 CreateWindow(L"BUTTON", text, 93 return CreateWindow(L"BUTTON", text,
61 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 94 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
62 x, y, width, 26, g_hwnd, (HMENU)message, g_hInstance, NULL); 95 x, y, width, 26, g_hwnd, (HMENU)message, g_hInstance, NULL);
63#pragma warning(pop) 96#pragma warning(pop)
64} 97}
65 98
66/* 99HWND CreateText(int x, int y, int width, LPCWSTR defaultText = L"") {
67 hwndSeed = CreateWindow(MSFTEDIT_CLASS, L"", 100 return CreateWindow(MSFTEDIT_CLASS, L"",
68 WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER, 101 WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER,
69 100, 10, 50, 26, hwnd, NULL, hInstance, NULL); 102 x, y, width, 26, g_hwnd, NULL, g_hInstance, NULL);
70*/ 103}
71 104
72int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { 105int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
73 LoadLibrary(L"Msftedit.dll"); 106 LoadLibrary(L"Msftedit.dll");
@@ -93,7 +126,9 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
93 rect.right - 550, 200, 500, 500, nullptr, nullptr, hInstance, nullptr); 126 rect.right - 550, 200, 500, 500, nullptr, nullptr, hInstance, nullptr);
94 127
95 CreateLabel(390, 15, 90, L"Version: " VERSION_STR); 128 CreateLabel(390, 15, 90, L"Version: " VERSION_STR);
96 CreateButton(10, 72, 100, L"Button text", IDC_TOGGLELASERS); 129 g_seed = CreateText(10, 10, 100);
130 g_randomizerStatus = CreateButton(120, 10, 100, L"Randomize", RANDOMIZING);
131 EnableWindow(g_randomizerStatus, FALSE);
97 PostMessage(g_hwnd, WM_COMMAND, PROC_ATTACH, NULL); 132 PostMessage(g_hwnd, WM_COMMAND, PROC_ATTACH, NULL);
98 133
99 ShowWindow(g_hwnd, nCmdShow); 134 ShowWindow(g_hwnd, nCmdShow);
diff --git a/Source/Memory.cpp b/Source/Memory.cpp index 1f1ae0a..d7f0212 100644 --- a/Source/Memory.cpp +++ b/Source/Memory.cpp
@@ -2,6 +2,7 @@
2#include <psapi.h> 2#include <psapi.h>
3#include <tlhelp32.h> 3#include <tlhelp32.h>
4#include <iostream> 4#include <iostream>
5#include <cassert>
5 6
6#undef PROCESSENTRY32 7#undef PROCESSENTRY32
7#undef Process32Next 8#undef Process32Next
@@ -53,15 +54,15 @@ Memory::~Memory() {
53 } 54 }
54} 55}
55 56
56int Memory::GetCurrentFrame() 57int Memory::GetCurrentFrame() {
57{
58 int SCRIPT_FRAMES; 58 int SCRIPT_FRAMES;
59 if (GLOBALS == 0x5B28C0) { 59 if (GLOBALS == 0x5B28C0) {
60 SCRIPT_FRAMES = 0x5BE3B0; 60 SCRIPT_FRAMES = 0x5BE3B0;
61 } else if (GLOBALS == 0x62D0A0) { 61 } else if (GLOBALS == 0x62D0A0) {
62 SCRIPT_FRAMES = 0x63651C; 62 SCRIPT_FRAMES = 0x63954C;
63 } else { 63 } else {
64 throw std::exception("Unknown value for Globals!"); 64 assert(false);
65 return 0x7FFFFFFF;
65 } 66 }
66 return ReadData<int>({SCRIPT_FRAMES}, 1)[0]; 67 return ReadData<int>({SCRIPT_FRAMES}, 1)[0];
67} 68}
@@ -108,14 +109,15 @@ int Memory::ExecuteSigScans()
108} 109}
109 110
110void Memory::ThrowError() { 111void Memory::ThrowError() {
111 std::string message(256, '\0'); 112 std::wstring message(256, '\0');
112 int length = FormatMessageA(4096, nullptr, GetLastError(), 1024, &message[0], static_cast<DWORD>(message.size()), nullptr); 113 int length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 1024, &message[0], static_cast<DWORD>(message.size()), nullptr);
113 message.resize(length); 114 message.resize(length);
114 throw std::exception(message.c_str()); 115#ifndef NDEBUG
116 MessageBox(NULL, message.c_str(), L"Please tell darkid about this", MB_OK);
117#endif
115} 118}
116 119
117void* Memory::ComputeOffset(std::vector<int> offsets) 120void* Memory::ComputeOffset(std::vector<int> offsets) {
118{
119 // Leave off the last offset, since it will be either read/write, and may not be of type unitptr_t. 121 // Leave off the last offset, since it will be either read/write, and may not be of type unitptr_t.
120 int final_offset = offsets.back(); 122 int final_offset = offsets.back();
121 offsets.pop_back(); 123 offsets.pop_back();
@@ -128,7 +130,10 @@ void* Memory::ComputeOffset(std::vector<int> offsets)
128 if (search == std::end(_computedAddresses)) { 130 if (search == std::end(_computedAddresses)) {
129 // If the address is not yet computed, then compute it. 131 // If the address is not yet computed, then compute it.
130 uintptr_t computedAddress = 0; 132 uintptr_t computedAddress = 0;
131 if (!ReadProcessMemory(_handle, reinterpret_cast<LPVOID>(cumulativeAddress), &computedAddress, sizeof(uintptr_t), NULL)) { 133 if (bool result = !ReadProcessMemory(_handle, reinterpret_cast<LPVOID>(cumulativeAddress), &computedAddress, sizeof(uintptr_t), NULL)) {
134 if (GetLastError() == ERROR_PARTIAL_COPY) {
135 int k = 1;
136 }
132 ThrowError(); 137 ThrowError();
133 } 138 }
134 _computedAddresses[cumulativeAddress] = computedAddress; 139 _computedAddresses[cumulativeAddress] = computedAddress;
diff --git a/Source/Memory.h b/Source/Memory.h index 9c00dab..f70de6a 100644 --- a/Source/Memory.h +++ b/Source/Memory.h
@@ -11,8 +11,7 @@
11// http://stackoverflow.com/q/32798185 11// http://stackoverflow.com/q/32798185
12// http://stackoverflow.com/q/36018838 12// http://stackoverflow.com/q/36018838
13// http://stackoverflow.com/q/1387064 13// http://stackoverflow.com/q/1387064
14class Memory 14class Memory {
15{
16public: 15public:
17 Memory(); 16 Memory();
18 bool Initialize(const std::wstring& processName); 17 bool Initialize(const std::wstring& processName);
@@ -46,11 +45,12 @@ public:
46 void AddSigScan(const std::vector<byte>& scanBytes, const std::function<void(int index)>& scanFunc); 45 void AddSigScan(const std::vector<byte>& scanBytes, const std::function<void(int index)>& scanFunc);
47 int ExecuteSigScans(); 46 int ExecuteSigScans();
48 47
49 void ClearOffsets() {_computedAddresses = std::map<uintptr_t, uintptr_t>();}
50
51private: 48private:
52 template<class T> 49 template<class T>
53 std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) { 50 std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) {
51 if (GetExitCodeProcess(_process) != STILL_ACTIVE) {
52 // Signal error, somehow
53 }
54 std::vector<T> data; 54 std::vector<T> data;
55 data.resize(numItems); 55 data.resize(numItems);
56 for (int i=0; i<5; i++) { 56 for (int i=0; i<5; i++) {