diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Memory.cpp | 34 | ||||
-rw-r--r-- | Source/Memory.h | 36 | ||||
-rw-r--r-- | Source/MemoryException.h | 53 | ||||
-rw-r--r-- | Source/PuzzleSerializer.cpp | 120 | ||||
-rw-r--r-- | Source/Randomizer.cpp | 35 | ||||
-rw-r--r-- | Source/Randomizer2.cpp | 8 | ||||
-rw-r--r-- | Source/Randomizer2.h | 6 | ||||
-rw-r--r-- | Source/Source.vcxproj | 1 |
8 files changed, 165 insertions, 128 deletions
diff --git a/Source/Memory.cpp b/Source/Memory.cpp index 55ef18a..80cd103 100644 --- a/Source/Memory.cpp +++ b/Source/Memory.cpp | |||
@@ -22,22 +22,22 @@ Memory::~Memory() { | |||
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
25 | void Memory::StartHeartbeat(HWND window, std::chrono::milliseconds beat) { | 25 | void Memory::StartHeartbeat(HWND window, WPARAM wParam, std::chrono::milliseconds beat) { |
26 | if (_threadActive) return; | 26 | if (_threadActive) return; |
27 | _threadActive = true; | 27 | _threadActive = true; |
28 | _thread = std::thread([sharedThis = shared_from_this(), window, beat]{ | 28 | _thread = std::thread([sharedThis = shared_from_this(), window, wParam, beat]{ |
29 | while (sharedThis->_threadActive) { | 29 | while (sharedThis->_threadActive) { |
30 | sharedThis->Heartbeat(window); | 30 | sharedThis->Heartbeat(window, wParam); |
31 | std::this_thread::sleep_for(beat); | 31 | std::this_thread::sleep_for(beat); |
32 | } | 32 | } |
33 | }); | 33 | }); |
34 | _thread.detach(); | 34 | _thread.detach(); |
35 | } | 35 | } |
36 | 36 | ||
37 | void Memory::Heartbeat(HWND window) { | 37 | void Memory::Heartbeat(HWND window, WPARAM wParam) { |
38 | if (!_handle && !Initialize()) { | 38 | if (!_handle && !Initialize()) { |
39 | // Couldn't initialize, definitely not running | 39 | // Couldn't initialize, definitely not running |
40 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::NotRunning); | 40 | PostMessage(window, WM_COMMAND, wParam, (LPARAM)ProcStatus::NotRunning); |
41 | return; | 41 | return; |
42 | } | 42 | } |
43 | 43 | ||
@@ -48,7 +48,7 @@ void Memory::Heartbeat(HWND window) { | |||
48 | // Process has exited, clean up. | 48 | // Process has exited, clean up. |
49 | _computedAddresses.clear(); | 49 | _computedAddresses.clear(); |
50 | _handle = NULL; | 50 | _handle = NULL; |
51 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::NotRunning); | 51 | PostMessage(window, WM_COMMAND, wParam, (LPARAM)ProcStatus::NotRunning); |
52 | return; | 52 | return; |
53 | } | 53 | } |
54 | 54 | ||
@@ -62,13 +62,13 @@ void Memory::Heartbeat(HWND window) { | |||
62 | if (frameDelta < 0 && currentFrame < 250) { | 62 | if (frameDelta < 0 && currentFrame < 250) { |
63 | // Some addresses (e.g. Entity Manager) may get re-allocated on newgame. | 63 | // Some addresses (e.g. Entity Manager) may get re-allocated on newgame. |
64 | _computedAddresses.clear(); | 64 | _computedAddresses.clear(); |
65 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::NewGame); | 65 | PostMessage(window, WM_COMMAND, wParam, (LPARAM)ProcStatus::NewGame); |
66 | return; | 66 | return; |
67 | } | 67 | } |
68 | 68 | ||
69 | // TODO: Some way to return ProcStatus::Randomized vs ProcStatus::NotRandomized vs ProcStatus::DeRandomized; | 69 | // TODO: Some way to return ProcStatus::Randomized vs ProcStatus::NotRandomized vs ProcStatus::DeRandomized; |
70 | 70 | ||
71 | PostMessage(window, WM_COMMAND, HEARTBEAT, (LPARAM)ProcStatus::Running); | 71 | PostMessage(window, WM_COMMAND, wParam, (LPARAM)ProcStatus::Running); |
72 | } | 72 | } |
73 | 73 | ||
74 | [[nodiscard]] | 74 | [[nodiscard]] |
@@ -151,16 +151,6 @@ int Memory::ExecuteSigScans() | |||
151 | return notFound; | 151 | return notFound; |
152 | } | 152 | } |
153 | 153 | ||
154 | void Memory::ThrowError() { | ||
155 | std::wstring message(256, '\0'); | ||
156 | DWORD error = GetLastError(); | ||
157 | int length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error, 1024, &message[0], static_cast<DWORD>(message.size()), nullptr); | ||
158 | message.resize(length); | ||
159 | #ifndef NDEBUG | ||
160 | MessageBox(NULL, message.c_str(), L"Please tell darkid about this", MB_OK); | ||
161 | #endif | ||
162 | } | ||
163 | |||
164 | void* Memory::ComputeOffset(std::vector<int> offsets) { | 154 | void* Memory::ComputeOffset(std::vector<int> offsets) { |
165 | // Leave off the last offset, since it will be either read/write, and may not be of type uintptr_t. | 155 | // Leave off the last offset, since it will be either read/write, and may not be of type uintptr_t. |
166 | int final_offset = offsets.back(); | 156 | int final_offset = offsets.back(); |
@@ -177,11 +167,11 @@ void* Memory::ComputeOffset(std::vector<int> offsets) { | |||
177 | #endif | 167 | #endif |
178 | // If the address is not yet computed, then compute it. | 168 | // If the address is not yet computed, then compute it. |
179 | uintptr_t computedAddress = 0; | 169 | uintptr_t computedAddress = 0; |
180 | if (bool result = !ReadProcessMemory(_handle, reinterpret_cast<LPVOID>(cumulativeAddress), &computedAddress, sizeof(uintptr_t), NULL)) { | 170 | if (!ReadProcessMemory(_handle, reinterpret_cast<LPVOID>(cumulativeAddress), &computedAddress, sizeof(uintptr_t), NULL)) { |
181 | ThrowError(); | 171 | MEMORY_THROW("Couldn't compute offset.", offsets); |
182 | } | 172 | } |
183 | if (computedAddress == 0) { // Attempting to dereference a nullptr | 173 | if (computedAddress == 0) { |
184 | ThrowError(); | 174 | MEMORY_THROW("Attempted to derefence NULL while computing offsets.", offsets); |
185 | } | 175 | } |
186 | _computedAddresses[cumulativeAddress] = computedAddress; | 176 | _computedAddresses[cumulativeAddress] = computedAddress; |
187 | #ifdef NDEBUG | 177 | #ifdef NDEBUG |
diff --git a/Source/Memory.h b/Source/Memory.h index 5332cc3..803a5f1 100644 --- a/Source/Memory.h +++ b/Source/Memory.h | |||
@@ -4,11 +4,12 @@ | |||
4 | #include <thread> | 4 | #include <thread> |
5 | #include <vector> | 5 | #include <vector> |
6 | #include <windows.h> | 6 | #include <windows.h> |
7 | #include <cassert> | ||
8 | #include "MemoryException.h" | ||
7 | 9 | ||
8 | // #define GLOBALS 0x5B28C0 | 10 | // #define GLOBALS 0x5B28C0 |
9 | #define GLOBALS 0x62D0A0 | 11 | #define GLOBALS 0x62D0A0 |
10 | 12 | ||
11 | #define HEARTBEAT 0x401 | ||
12 | enum class ProcStatus { | 13 | enum class ProcStatus { |
13 | NotRunning, | 14 | NotRunning, |
14 | Running, | 15 | Running, |
@@ -24,7 +25,7 @@ class Memory final : public std::enable_shared_from_this<Memory> { | |||
24 | public: | 25 | public: |
25 | Memory(const std::wstring& processName); | 26 | Memory(const std::wstring& processName); |
26 | ~Memory(); | 27 | ~Memory(); |
27 | void StartHeartbeat(HWND window, std::chrono::milliseconds beat = std::chrono::milliseconds(1000)); | 28 | void StartHeartbeat(HWND window, WPARAM wParam, std::chrono::milliseconds beat = std::chrono::milliseconds(1000)); |
28 | 29 | ||
29 | Memory(const Memory& memory) = delete; | 30 | Memory(const Memory& memory) = delete; |
30 | Memory& operator=(const Memory& other) = delete; | 31 | Memory& operator=(const Memory& other) = delete; |
@@ -63,40 +64,25 @@ public: | |||
63 | private: | 64 | private: |
64 | template<class T> | 65 | template<class T> |
65 | std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) { | 66 | std::vector<T> ReadData(const std::vector<int>& offsets, size_t numItems) { |
66 | if (numItems == 0) return {}; | 67 | assert(numItems); |
67 | std::vector<T> data; | 68 | std::vector<T> data; |
68 | data.resize(numItems); | 69 | data.resize(numItems); |
69 | void* computedOffset = ComputeOffset(offsets); | 70 | if (!ReadProcessMemory(_handle, ComputeOffset(offsets), &data[0], sizeof(T) * numItems, nullptr)) { |
70 | for (int i=0; i<5; i++) { | 71 | MEMORY_THROW("Failed to read data.", offsets, numItems); |
71 | if (ReadProcessMemory(_handle, computedOffset, &data[0], sizeof(T) * numItems, nullptr)) { | ||
72 | if (i != 0) { | ||
73 | int k = 0; | ||
74 | } | ||
75 | return data; | ||
76 | } | ||
77 | } | 72 | } |
78 | ThrowError(); | 73 | return data; |
79 | return {}; | ||
80 | } | 74 | } |
81 | 75 | ||
82 | template <class T> | 76 | template <class T> |
83 | void WriteData(const std::vector<int>& offsets, const std::vector<T>& data) { | 77 | void WriteData(const std::vector<int>& offsets, const std::vector<T>& data) { |
84 | if (data.empty()) return; | 78 | assert(data.size()); |
85 | void* computedOffset = ComputeOffset(offsets); | 79 | if (!WriteProcessMemory(_handle, ComputeOffset(offsets), &data[0], sizeof(T) * data.size(), nullptr)) { |
86 | for (int i=0; i<5; i++) { | 80 | MEMORY_THROW("Failed to write data.", offsets, data.size()); |
87 | if (WriteProcessMemory(_handle, computedOffset, &data[0], sizeof(T) * data.size(), nullptr)) { | ||
88 | if (i != 0) { | ||
89 | int k = 0; | ||
90 | } | ||
91 | return; | ||
92 | } | ||
93 | } | 81 | } |
94 | ThrowError(); | ||
95 | } | 82 | } |
96 | 83 | ||
97 | void Heartbeat(HWND window); | 84 | void Heartbeat(HWND window, WPARAM wParam); |
98 | bool Initialize(); | 85 | bool Initialize(); |
99 | void ThrowError(); | ||
100 | void* ComputeOffset(std::vector<int> offsets); | 86 | void* ComputeOffset(std::vector<int> offsets); |
101 | 87 | ||
102 | int _previousFrame = 0; | 88 | int _previousFrame = 0; |
diff --git a/Source/MemoryException.h b/Source/MemoryException.h new file mode 100644 index 0000000..ad2824d --- /dev/null +++ b/Source/MemoryException.h | |||
@@ -0,0 +1,53 @@ | |||
1 | #pragma once | ||
2 | #include <exception> | ||
3 | #include <string> | ||
4 | #include <vector> | ||
5 | |||
6 | #define MEMORY_CATCH(expr) \ | ||
7 | try { \ | ||
8 | (expr); \ | ||
9 | } catch (MemoryException exc) { \ | ||
10 | MemoryException::HandleException(exc); \ | ||
11 | } \ | ||
12 | do {} while (0) | ||
13 | |||
14 | #define MEMORY_THROW(...) throw MemoryException(__func__, __LINE__, ##__VA_ARGS__); | ||
15 | |||
16 | class MemoryException : public std::exception { | ||
17 | public: | ||
18 | inline MemoryException(const char* func, int32_t line, const char* message) noexcept | ||
19 | : MemoryException(func, line, message, {}, 0) {} | ||
20 | inline MemoryException(const char* func, int32_t line, const char* message, const std::vector<int>& offsets) noexcept | ||
21 | : MemoryException(func, line, message, offsets, 0) {} | ||
22 | inline MemoryException(const char* func, int32_t line, const char* message, const std::vector<int>& offsets, size_t numItems) noexcept | ||
23 | : _func(func), _line(line), _message(message), _offsets(offsets), _numItems(numItems) {} | ||
24 | |||
25 | ~MemoryException() = default; | ||
26 | inline const char* what() const noexcept { | ||
27 | return _message; | ||
28 | } | ||
29 | static void HandleException(const MemoryException& exc) noexcept { | ||
30 | std::string msg = "MemoryException thrown in function "; | ||
31 | msg += exc._func; | ||
32 | msg += " on line " + std::to_string(exc._line) + ":\n" + exc._message + "\nOffsets:"; | ||
33 | for (int offset : exc._offsets) { | ||
34 | msg += " " + std::to_string(offset); | ||
35 | } | ||
36 | msg += "\n"; | ||
37 | if (exc._numItems != 0) { | ||
38 | msg += "Num Items: " + std::to_string(exc._numItems) + "\n"; | ||
39 | } | ||
40 | OutputDebugStringA(msg.c_str()); | ||
41 | #ifndef NDEBUG | ||
42 | MessageBoxA(NULL, msg.c_str(), "Memory Exception Thrown", MB_OK); | ||
43 | #endif | ||
44 | } | ||
45 | |||
46 | private: | ||
47 | const char* _func; | ||
48 | int32_t _line; | ||
49 | const char* _message; | ||
50 | const std::vector<int> _offsets; | ||
51 | size_t _numItems = 0; | ||
52 | }; | ||
53 | |||
diff --git a/Source/PuzzleSerializer.cpp b/Source/PuzzleSerializer.cpp index fb4166b..3dffde1 100644 --- a/Source/PuzzleSerializer.cpp +++ b/Source/PuzzleSerializer.cpp | |||
@@ -8,73 +8,81 @@ | |||
8 | PuzzleSerializer::PuzzleSerializer(const std::shared_ptr<Memory>& memory) : _memory(memory) {} | 8 | PuzzleSerializer::PuzzleSerializer(const std::shared_ptr<Memory>& memory) : _memory(memory) {} |
9 | 9 | ||
10 | Puzzle PuzzleSerializer::ReadPuzzle(int id) { | 10 | Puzzle PuzzleSerializer::ReadPuzzle(int id) { |
11 | int width = _memory->ReadEntityData<int>(id, GRID_SIZE_X, 1)[0]; | ||
12 | int height = _memory->ReadEntityData<int>(id, GRID_SIZE_Y, 1)[0]; | ||
13 | if (width == 0) width = height; | ||
14 | if (height == 0) height = width; | ||
15 | if (width < 0 || height < 0) return Puzzle(); // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though. | ||
16 | |||
17 | _numGridLocations = width * height; // Highest location which represents a gridded intersection | ||
18 | _numIntersections = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; | ||
19 | _intersectionFlags = _memory->ReadArray<int>(id, DOT_FLAGS, _numIntersections); | ||
20 | int numConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; | ||
21 | _connectionsA = _memory->ReadArray<int>(id, DOT_CONNECTION_A, numConnections); | ||
22 | _connectionsB = _memory->ReadArray<int>(id, DOT_CONNECTION_B, numConnections); | ||
23 | _intersectionLocations = _memory->ReadArray<float>(id, DOT_POSITIONS, _numIntersections*2); | ||
24 | |||
25 | Puzzle p; | 11 | Puzzle p; |
26 | p.NewGrid(width - 1, height - 1); | 12 | try { |
27 | ReadIntersections(p); | 13 | int width = _memory->ReadEntityData<int>(id, GRID_SIZE_X, 1)[0]; |
28 | ReadExtras(p); | 14 | int height = _memory->ReadEntityData<int>(id, GRID_SIZE_Y, 1)[0]; |
29 | ReadDecorations(p, id); | 15 | if (width == 0) width = height; |
30 | ReadSequence(p, id); | 16 | if (height == 0) height = width; |
31 | ReadSymmetry(p, id); | 17 | if (width < 0 || height < 0) return Puzzle(); // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though. |
18 | |||
19 | _numGridLocations = width * height; // Highest location which represents a gridded intersection | ||
20 | _numIntersections = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; | ||
21 | _intersectionFlags = _memory->ReadArray<int>(id, DOT_FLAGS, _numIntersections); | ||
22 | int numConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; | ||
23 | _connectionsA = _memory->ReadArray<int>(id, DOT_CONNECTION_A, numConnections); | ||
24 | _connectionsB = _memory->ReadArray<int>(id, DOT_CONNECTION_B, numConnections); | ||
25 | _intersectionLocations = _memory->ReadArray<float>(id, DOT_POSITIONS, _numIntersections*2); | ||
26 | |||
27 | p.NewGrid(width - 1, height - 1); | ||
28 | ReadIntersections(p); | ||
29 | ReadExtras(p); | ||
30 | ReadDecorations(p, id); | ||
31 | ReadSequence(p, id); | ||
32 | ReadSymmetry(p, id); | ||
33 | } catch (MemoryException exc) { | ||
34 | MemoryException::HandleException(exc); | ||
35 | } | ||
32 | return p; | 36 | return p; |
33 | } | 37 | } |
34 | 38 | ||
35 | void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { | 39 | void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { |
36 | _intersectionFlags.clear(); | 40 | try { |
37 | _connectionsA.clear(); | 41 | _intersectionFlags.clear(); |
38 | _connectionsB.clear(); | 42 | _connectionsA.clear(); |
39 | _intersectionLocations.clear(); | 43 | _connectionsB.clear(); |
40 | _extraLocations.clear(); | 44 | _intersectionLocations.clear(); |
41 | 45 | _extraLocations.clear(); | |
42 | MIN = 0.1f; | 46 | |
43 | MAX = 0.9f; | 47 | MIN = 0.1f; |
44 | WIDTH_INTERVAL = (MAX - MIN) / (p.width/2); | 48 | MAX = 0.9f; |
45 | HEIGHT_INTERVAL = (MAX - MIN) / (p.height/2); | 49 | WIDTH_INTERVAL = (MAX - MIN) / (p.width/2); |
46 | GAP_SIZE = min(WIDTH_INTERVAL, HEIGHT_INTERVAL) / 2; | 50 | HEIGHT_INTERVAL = (MAX - MIN) / (p.height/2); |
47 | // @Improvement: This will make grid cells square... but how do I keep the puzzle centered? Maybe save extra metadata? | 51 | GAP_SIZE = min(WIDTH_INTERVAL, HEIGHT_INTERVAL) / 2; |
48 | // INTERVAL = (MAX - MIN) / (max(p.width, p.height) / 2); | 52 | // @Improvement: This will make grid cells square... but how do I keep the puzzle centered? Maybe save extra metadata? |
49 | // GAP_SIZE = INTERVAL / 2; | 53 | // INTERVAL = (MAX - MIN) / (max(p.width, p.height) / 2); |
54 | // GAP_SIZE = INTERVAL / 2; | ||
50 | 55 | ||
51 | WriteIntersections(p); | 56 | WriteIntersections(p); |
52 | WriteEndpoints(p); | 57 | WriteEndpoints(p); |
53 | WriteDots(p); | 58 | WriteDots(p); |
54 | WriteGaps(p); | 59 | WriteGaps(p); |
55 | WriteDecorations(p, id); | 60 | WriteDecorations(p, id); |
56 | WriteSequence(p, id); | 61 | WriteSequence(p, id); |
57 | WriteSymmetry(p, id); | 62 | WriteSymmetry(p, id); |
58 | 63 | ||
59 | #ifndef NDEBUG | 64 | #ifndef NDEBUG |
60 | int maxDots = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; | 65 | int maxDots = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; |
61 | assert(_intersectionFlags.size() <= maxDots); | 66 | assert(_intersectionFlags.size() <= maxDots); |
62 | assert(_intersectionLocations.size() <= maxDots*2); | 67 | assert(_intersectionLocations.size() <= maxDots*2); |
63 | 68 | ||
64 | int maxConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; | 69 | int maxConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; |
65 | assert(_connectionsA.size() <= maxConnections); | 70 | assert(_connectionsA.size() <= maxConnections); |
66 | assert(_connectionsB.size() <= maxConnections); | 71 | assert(_connectionsB.size() <= maxConnections); |
67 | #endif | 72 | #endif |
68 | 73 | ||
69 | _memory->WriteEntityData<int>(id, GRID_SIZE_X, {(p.width + 1)/2}); | 74 | _memory->WriteEntityData<int>(id, GRID_SIZE_X, {(p.width + 1)/2}); |
70 | _memory->WriteEntityData<int>(id, GRID_SIZE_Y, {(p.height + 1)/2}); | 75 | _memory->WriteEntityData<int>(id, GRID_SIZE_Y, {(p.height + 1)/2}); |
71 | _memory->WriteEntityData<int>(id, NUM_DOTS, {static_cast<int>(_intersectionFlags.size())}); | 76 | _memory->WriteEntityData<int>(id, NUM_DOTS, {static_cast<int>(_intersectionFlags.size())}); |
72 | _memory->WriteArray<float>(id, DOT_POSITIONS, _intersectionLocations); | 77 | _memory->WriteArray<float>(id, DOT_POSITIONS, _intersectionLocations); |
73 | _memory->WriteArray<int>(id, DOT_FLAGS, _intersectionFlags); | 78 | _memory->WriteArray<int>(id, DOT_FLAGS, _intersectionFlags); |
74 | _memory->WriteEntityData<int>(id, NUM_CONNECTIONS, {static_cast<int>(_connectionsA.size())}); | 79 | _memory->WriteEntityData<int>(id, NUM_CONNECTIONS, {static_cast<int>(_connectionsA.size())}); |
75 | _memory->WriteArray<int>(id, DOT_CONNECTION_A, _connectionsA); | 80 | _memory->WriteArray<int>(id, DOT_CONNECTION_A, _connectionsA); |
76 | _memory->WriteArray<int>(id, DOT_CONNECTION_B, _connectionsB); | 81 | _memory->WriteArray<int>(id, DOT_CONNECTION_B, _connectionsB); |
77 | _memory->WriteEntityData<int>(id, NEEDS_REDRAW, {1}); | 82 | _memory->WriteEntityData<int>(id, NEEDS_REDRAW, {1}); |
83 | } catch (MemoryException exc) { | ||
84 | MemoryException::HandleException(exc); | ||
85 | } | ||
78 | } | 86 | } |
79 | 87 | ||
80 | void PuzzleSerializer::ReadIntersections(Puzzle& p) { | 88 | void PuzzleSerializer::ReadIntersections(Puzzle& p) { |
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 13f381a..1427f4d 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp | |||
@@ -129,28 +129,28 @@ void Randomizer::Randomize() { | |||
129 | // Sig scans will be run during challenge randomization. | 129 | // Sig scans will be run during challenge randomization. |
130 | 130 | ||
131 | // Seed challenge first for future-proofing | 131 | // Seed challenge first for future-proofing |
132 | RandomizeChallenge(); | 132 | MEMORY_CATCH(RandomizeChallenge()); |
133 | 133 | ||
134 | // Content swaps -- must happen before squarePanels | 134 | // Content swaps -- must happen before squarePanels |
135 | Randomize(upDownPanels, SWAP::LINES | SWAP::COLORS); | 135 | MEMORY_CATCH(Randomize(upDownPanels, SWAP::LINES | SWAP::COLORS)); |
136 | Randomize(leftForwardRightPanels, SWAP::LINES | SWAP::COLORS); | 136 | MEMORY_CATCH(Randomize(leftForwardRightPanels, SWAP::LINES | SWAP::COLORS)); |
137 | 137 | ||
138 | Randomize(squarePanels, SWAP::LINES | SWAP::COLORS); | 138 | MEMORY_CATCH(Randomize(squarePanels, SWAP::LINES | SWAP::COLORS)); |
139 | 139 | ||
140 | // Individual area modifications | 140 | // Individual area modifications |
141 | RandomizeTutorial(); | 141 | MEMORY_CATCH(RandomizeTutorial()); |
142 | RandomizeDesert(); | 142 | MEMORY_CATCH(RandomizeDesert()); |
143 | RandomizeQuarry(); | 143 | MEMORY_CATCH(RandomizeQuarry()); |
144 | RandomizeTreehouse(); | 144 | MEMORY_CATCH(RandomizeTreehouse()); |
145 | RandomizeKeep(); | 145 | MEMORY_CATCH(RandomizeKeep()); |
146 | RandomizeShadows(); | 146 | MEMORY_CATCH(RandomizeShadows()); |
147 | RandomizeMonastery(); | 147 | MEMORY_CATCH(RandomizeMonastery()); |
148 | RandomizeBunker(); | 148 | MEMORY_CATCH(RandomizeBunker()); |
149 | RandomizeJungle(); | 149 | MEMORY_CATCH(RandomizeJungle()); |
150 | RandomizeSwamp(); | 150 | MEMORY_CATCH(RandomizeSwamp()); |
151 | RandomizeMountain(); | 151 | MEMORY_CATCH(RandomizeMountain()); |
152 | RandomizeTown(); | 152 | MEMORY_CATCH(RandomizeTown()); |
153 | RandomizeSymmetry(); | 153 | MEMORY_CATCH(RandomizeSymmetry()); |
154 | // RandomizeAudioLogs(); | 154 | // RandomizeAudioLogs(); |
155 | } | 155 | } |
156 | 156 | ||
@@ -210,6 +210,7 @@ void Randomizer::RandomizeQuarry() { | |||
210 | 210 | ||
211 | void Randomizer::RandomizeTreehouse() { | 211 | void Randomizer::RandomizeTreehouse() { |
212 | // Ensure that whatever pivot panels we have are flagged as "pivotable" | 212 | // Ensure that whatever pivot panels we have are flagged as "pivotable" |
213 | // @Bug: Can return {}, be careful! | ||
213 | int panelFlags = _memory->ReadEntityData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; | 214 | int panelFlags = _memory->ReadEntityData<int>(0x17DD1, STYLE_FLAGS, 1)[0]; |
214 | _memory->WriteEntityData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); | 215 | _memory->WriteEntityData<int>(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); |
215 | panelFlags = _memory->ReadEntityData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; | 216 | panelFlags = _memory->ReadEntityData<int>(0x17CE3, STYLE_FLAGS, 1)[0]; |
diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index c823567..782e248 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp | |||
@@ -1,5 +1,5 @@ | |||
1 | #include "Memory.h" | ||
2 | #include "Randomizer2.h" | 1 | #include "Randomizer2.h" |
2 | #include "PuzzleSerializer.h" | ||
3 | #include "Randomizer2Core.h" | 3 | #include "Randomizer2Core.h" |
4 | #include "Puzzle.h" | 4 | #include "Puzzle.h" |
5 | #include "Random.h" | 5 | #include "Random.h" |
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | #pragma warning (disable: 26451) | 11 | #pragma warning (disable: 26451) |
12 | 12 | ||
13 | Randomizer2::Randomizer2(const std::shared_ptr<Memory>& memory) : _memory(memory), _serializer(PuzzleSerializer(_memory)) {} | 13 | Randomizer2::Randomizer2(const PuzzleSerializer& serializer) : _serializer(serializer) {} |
14 | 14 | ||
15 | void Randomizer2::Randomize() { | 15 | void Randomizer2::Randomize() { |
16 | RandomizeTutorial(); | 16 | RandomizeTutorial(); |
@@ -361,9 +361,9 @@ void Randomizer2::SetGate(int panel, int X, int Y) { | |||
361 | } | 361 | } |
362 | 362 | ||
363 | SetPos(panel, x, y, 19.2f); | 363 | SetPos(panel, x, y, 19.2f); |
364 | _memory->WriteEntityData<float>(panel, ORIENTATION, {0.0f, 0.0f, z, w}); | 364 | // _memory->WriteEntityData<float>(panel, ORIENTATION, {0.0f, 0.0f, z, w}); |
365 | } | 365 | } |
366 | 366 | ||
367 | void Randomizer2::SetPos(int panel, float x, float y, float z) { | 367 | void Randomizer2::SetPos(int panel, float x, float y, float z) { |
368 | _memory->WriteEntityData<float>(panel, POSITION, {x, y, z}); | 368 | // _memory->WriteEntityData<float>(panel, POSITION, {x, y, z}); |
369 | } \ No newline at end of file | 369 | } \ No newline at end of file |
diff --git a/Source/Randomizer2.h b/Source/Randomizer2.h index 47a9ebd..c8c3db5 100644 --- a/Source/Randomizer2.h +++ b/Source/Randomizer2.h | |||
@@ -1,11 +1,10 @@ | |||
1 | #pragma once | 1 | #pragma once |
2 | #include <memory> | ||
3 | #include "PuzzleSerializer.h" | 2 | #include "PuzzleSerializer.h" |
4 | 3 | ||
5 | class Memory; | 4 | class Puzzle; |
6 | class Randomizer2 { | 5 | class Randomizer2 { |
7 | public: | 6 | public: |
8 | Randomizer2(const std::shared_ptr<Memory>& memory); | 7 | Randomizer2(const PuzzleSerializer& serializer); |
9 | void Randomize(); | 8 | void Randomize(); |
10 | void RandomizeTutorial(); | 9 | void RandomizeTutorial(); |
11 | void RandomizeSymmetry(); | 10 | void RandomizeSymmetry(); |
@@ -16,6 +15,5 @@ private: | |||
16 | void SetGate(int panel, int X, int Y); | 15 | void SetGate(int panel, int X, int Y); |
17 | void SetPos(int panel, float x, float y, float z); | 16 | void SetPos(int panel, float x, float y, float z); |
18 | 17 | ||
19 | std::shared_ptr<Memory> _memory; | ||
20 | PuzzleSerializer _serializer; | 18 | PuzzleSerializer _serializer; |
21 | }; | 19 | }; |
diff --git a/Source/Source.vcxproj b/Source/Source.vcxproj index 33e3697..5aaa0b0 100644 --- a/Source/Source.vcxproj +++ b/Source/Source.vcxproj | |||
@@ -159,6 +159,7 @@ | |||
159 | <ItemGroup> | 159 | <ItemGroup> |
160 | <ClInclude Include="ChallengeRandomizer.h" /> | 160 | <ClInclude Include="ChallengeRandomizer.h" /> |
161 | <ClInclude Include="Memory.h" /> | 161 | <ClInclude Include="Memory.h" /> |
162 | <ClInclude Include="MemoryException.h" /> | ||
162 | <ClInclude Include="Puzzle.h" /> | 163 | <ClInclude Include="Puzzle.h" /> |
163 | <ClInclude Include="Panels.h" /> | 164 | <ClInclude Include="Panels.h" /> |
164 | <ClInclude Include="PuzzleSerializer.h" /> | 165 | <ClInclude Include="PuzzleSerializer.h" /> |