summary refs log tree commit diff stats
path: root/Source
diff options
context:
space:
mode:
authorjbzdarkid <jbzdarkid@gmail.com>2018-11-19 09:27:29 -0800
committerjbzdarkid <jbzdarkid@gmail.com>2018-11-19 09:27:29 -0800
commiteb420604814dfdfa37fd542dda9ba7477c198b39 (patch)
tree449794ffbdbe111e48ec7d5dc05fe563339d8f3a /Source
parent0d4ebf34bfb93dbb215f49e9ca64b58fd7284a2b (diff)
downloadwitness-tutorializer-eb420604814dfdfa37fd542dda9ba7477c198b39.tar.gz
witness-tutorializer-eb420604814dfdfa37fd542dda9ba7477c198b39.tar.bz2
witness-tutorializer-eb420604814dfdfa37fd542dda9ba7477c198b39.zip
Cleanup packaging story, add more settings
Diffstat (limited to 'Source')
-rw-r--r--Source/ChallengeRandomizer.cpp218
-rw-r--r--Source/ChallengeRandomizer.h5
-rw-r--r--Source/Memory.h4
-rw-r--r--Source/Randomizer.cpp29
-rw-r--r--Source/Randomizer.h3
5 files changed, 150 insertions, 109 deletions
diff --git a/Source/ChallengeRandomizer.cpp b/Source/ChallengeRandomizer.cpp index 0bc51f6..401771e 100644 --- a/Source/ChallengeRandomizer.cpp +++ b/Source/ChallengeRandomizer.cpp
@@ -16,116 +16,33 @@ int find(const std::vector<byte> &data, const std::vector<byte>& search, size_t
16 return -1; 16 return -1;
17} 17}
18 18
19// Reads the (relative!) address of the RNG, then shifts it to point at RNG2
19void ChallengeRandomizer::AdjustRng(int offset) { 20void ChallengeRandomizer::AdjustRng(int offset) {
20 int currentRng = _memory->ReadData<int>({offset}, 0x1)[0]; 21 int currentRng = _memory->ReadData<int>({offset}, 0x1)[0];
21 _memory->WriteData<int>({offset}, {currentRng + 0x20}); 22 _memory->WriteData<int>({offset}, {currentRng + 0x20});
22} 23}
23 24
25// Overwrite the pointer for the lightmap_generator (which is unused, afaict) to point to a secondary RNG.
26// Then, adjust all the RNG functions in challenge/doors to use this RNG.
24ChallengeRandomizer::ChallengeRandomizer(const std::shared_ptr<Memory>& memory, int seed) : _memory(memory) 27ChallengeRandomizer::ChallengeRandomizer(const std::shared_ptr<Memory>& memory, int seed) : _memory(memory)
25{ 28{
26 int RNG_ADDR = _memory->ReadData<int>({GLOBALS + 0x10}, 1)[0]; 29 RNG_ADDR = _memory->ReadData<int>({GLOBALS + 0x10}, 1)[0];
27 int RNG2_ADDR = _memory->ReadData<int>({GLOBALS + 0x30}, 1)[0]; 30 RNG2_ADDR = _memory->ReadData<int>({GLOBALS + 0x30}, 1)[0];
28 _memory->WriteData<int>({GLOBALS + 0x30}, {RNG_ADDR + 4}); 31 bool alreadyInjected = (RNG2_ADDR == RNG_ADDR + 4);
29 if (RNG2_ADDR == RNG_ADDR + 4) return; // Already applied hack 32
33 if (!alreadyInjected) _memory->WriteData<int>({GLOBALS + 0x30}, {RNG_ADDR + 4});
34 _memory->WriteData<int>({GLOBALS + 0x30, 0}, {seed});
30 35
31 int shuffle_integers = -1;
32 int cut_random_edges = -1;
33 int get_empty_decoration_slot = -1;
34 int get_empty_dot_spot = -1;
35 int add_exactly_this_many_bisection_dots = -1;
36 int make_a_shaper = -1;
37 int init_pattern_data_lotus = -1;
38 int reroll_lotus_eater_stuff = -1;
39 int do_lotus_minutes = -1;
40 int do_lotus_eighths = -1;
41 int do_success_side_effects = -1; 36 int do_success_side_effects = -1;
42 37
43 for (int i=0; i<0x200000; i+=0x1000) { 38 for (int i=0; i<0x200000; i+=0x1000) {
44 std::vector<byte> data = _memory->ReadData<byte>({i}, 0x1100); 39 std::vector<byte> data = _memory->ReadData<byte>({i}, 0x1100);
45 std::cout << data.size() << std::endl; 40 std::cout << data.size() << std::endl;
46 41
47 if (shuffle_integers == -1) { 42 if (!alreadyInjected) HandleSigScans(i, data);
48 int index = find(data, {0x48, 0x89, 0x5C, 0x24, 0x10, 0x56, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x63, 0xDA, 0x48, 0x8B, 0xF1, 0x83, 0xFB, 0x01}); 43
49 if (index != -1) {
50 shuffle_integers = i + index;
51 AdjustRng(shuffle_integers + 0x23);
52 }
53 }
54 if (cut_random_edges == -1) {
55 int index = find(data, {0x89, 0x44, 0x24, 0x3C, 0x33, 0xC0, 0x85, 0xC0, 0x75, 0xFA});
56 if (index != -1) {
57 cut_random_edges = i + index - 0x22;
58 AdjustRng(cut_random_edges + 0x5D);
59 }
60 }
61 if (get_empty_decoration_slot == -1) {
62 int index = find(data, {0x57, 0x48, 0x83, 0xEC, 0x20, 0x8B, 0xB9, 0x38, 0x04}); // TODO: Sync versions
63 if (index != -1) {
64 get_empty_decoration_slot = i + index - 0x5;
65 AdjustRng(get_empty_decoration_slot + 0x16);
66 }
67 }
68 if (get_empty_dot_spot == -1) {
69 int index = find(data, {0xF7, 0xF3, 0x85, 0xD2, 0x74, 0xEC}); // TODO: Sync versions
70 if (index != -1) {
71 get_empty_dot_spot = i + index - 0x2E;
72 AdjustRng(get_empty_dot_spot + 0x23);
73 }
74 }
75 if (add_exactly_this_many_bisection_dots == -1) {
76 int index = find(data, {0x48, 0x8B, 0xB4, 0x24, 0xB8, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xBC, 0x24, 0xB0, 0x00, 0x00, 0x00}); // TODO: Sync versions
77 if (index != -1) {
78 add_exactly_this_many_bisection_dots = i + index - 0x20;
79 AdjustRng(add_exactly_this_many_bisection_dots + 0x1C);
80 }
81 }
82 if (make_a_shaper == -1) {
83 int index = find(data, {0xF7, 0xE3, 0xD1, 0xEA, 0x8D, 0x0C, 0x52}); // TODO: Sync versions
84 if (index != -1) {
85 make_a_shaper = i + index - 0x19;
86 AdjustRng(make_a_shaper + 0x9);
87 AdjustRng(make_a_shaper + 0x35);
88 AdjustRng(make_a_shaper + 0x62);
89 }
90 }
91 if (/*Entity_Machine_Panel::*/init_pattern_data_lotus == -1) {
92 int index = find(data, {0x40, 0x55, 0x56, 0x48, 0x8D, 0x6C, 0x24, 0xB1}); // TODO: Sync versions
93 if (index != -1) {
94 init_pattern_data_lotus = i + index;
95 AdjustRng(init_pattern_data_lotus + 0x433);
96 AdjustRng(init_pattern_data_lotus + 0x45B);
97 AdjustRng(init_pattern_data_lotus + 0x5A7);
98 AdjustRng(init_pattern_data_lotus + 0x5D6);
99 AdjustRng(init_pattern_data_lotus + 0x6F6);
100 AdjustRng(init_pattern_data_lotus + 0xD17);
101 AdjustRng(init_pattern_data_lotus + 0xFDA);
102 }
103 }
104 if (/*Entity_Record_Player::*/reroll_lotus_eater_stuff == -1) {
105 int index = find(data, {0xB8, 0xAB, 0xAA, 0xAA, 0xAA, 0x41, 0xC1, 0xE8}); // TODO: Sync versions
106 if (index != -1) {
107 reroll_lotus_eater_stuff = i + index - 0x37;
108 AdjustRng(reroll_lotus_eater_stuff + 0x24);
109 AdjustRng(reroll_lotus_eater_stuff + 0x6B);
110 }
111 }
112 // These disable the random locations on timer panels, which would otherwise increment the RNG.
113 if (do_lotus_minutes == -1) {
114 int index = find(data, {0x0F, 0xBE, 0x6C, 0x08, 0xFF, 0x45}); // TODO: Sync versions
115 if (index != -1) {
116 do_lotus_minutes = i + index - 0x2B;
117 _memory->WriteData<byte>({do_lotus_minutes + 0x43B}, {0x31, 0xC0, 0x90, 0x90, 0x90}); // xor eax, eax ;RNG returns 0
118 _memory->WriteData<byte>({do_lotus_minutes + 0x5B3}, {0x31, 0xC0, 0x90, 0x90, 0x90}); // xor eax, eax ;RNG returns 0
119 }
120 }
121 if (do_lotus_eighths == -1) {
122 int index = find(data, {0x75, 0xF5, 0x0F, 0xBE, 0x44, 0x08, 0xFF}); // TODO: Sync versions
123 if (index != -1) {
124 do_lotus_eighths = i + index - 0x39;
125 _memory->WriteData<byte>({do_lotus_eighths + 0x1E7}, {0x31, 0xC0, 0x90, 0x90, 0x90}); // xor eax, eax ;RNG returns 0
126 }
127 }
128 // This injection ensures that the seed is set every time the challenge is started. 44 // This injection ensures that the seed is set every time the challenge is started.
45 // We always do this sigscan since it affects the seed.
129 if (do_success_side_effects == -1) { 46 if (do_success_side_effects == -1) {
130 int index = find(data, {0xFF, 0xC8, 0x99, 0x2B, 0xC2, 0xD1, 0xF8, 0x8B, 0xD0}); 47 int index = find(data, {0xFF, 0xC8, 0x99, 0x2B, 0xC2, 0xD1, 0xF8, 0x8B, 0xD0});
131 if (index != -1) { 48 if (index != -1) {
@@ -144,3 +61,114 @@ ChallengeRandomizer::ChallengeRandomizer(const std::shared_ptr<Memory>& memory,
144 } 61 }
145 } 62 }
146} 63}
64
65void ChallengeRandomizer::HandleSigScans(int i, const std::vector<byte>& data) {
66 static int shuffle_integers = -1;
67 static int shuffle_int = -1;
68 static int cut_random_edges = -1;
69 static int get_empty_decoration_slot = -1;
70 static int get_empty_dot_spot = -1;
71 static int add_exactly_this_many_bisection_dots = -1;
72 static int make_a_shaper = -1;
73 static int init_pattern_data_lotus = -1;
74 static int reroll_lotus_eater_stuff = -1;
75 static int do_lotus_minutes = -1;
76 static int do_lotus_tenths = -1;
77 static int do_lotus_eighths = -1;
78
79 if (shuffle_integers == -1) {
80 int index = find(data, {0x48, 0x89, 0x5C, 0x24, 0x10, 0x56, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x63, 0xDA, 0x48, 0x8B, 0xF1, 0x83, 0xFB, 0x01});
81 if (index != -1) {
82 shuffle_integers = i + index;
83 AdjustRng(shuffle_integers + 0x23);
84 }
85 }
86 // shuffle<int>
87 if (shuffle_int == -1) {
88 int index = find(data, {0x33, 0xF6, 0x48, 0x8B, 0xD9, 0x39, 0x31, 0x7E, 0x51});
89 if (index != -1) {
90 shuffle_int = i + index - 0x16;
91 AdjustRng(shuffle_int + 0x12);
92 }
93 }
94 if (cut_random_edges == -1) {
95 int index = find(data, {0x89, 0x44, 0x24, 0x3C, 0x33, 0xC0, 0x85, 0xC0, 0x75, 0xFA});
96 if (index != -1) {
97 cut_random_edges = i + index - 0x22;
98 AdjustRng(cut_random_edges + 0x5D);
99 }
100 }
101 if (get_empty_decoration_slot == -1) {
102 int index = find(data, {0x42, 0x83, 0x3C, 0x80, 0x00, 0x75, 0xDF});
103 if (index != -1) {
104 get_empty_decoration_slot = i + index - 0x2D;
105 AdjustRng(get_empty_decoration_slot + 0x16);
106 }
107 }
108 if (get_empty_dot_spot == -1) {
109 int index = find(data, {0xF7, 0xF3, 0x85, 0xD2, 0x74, 0xEC});
110 if (index != -1) {
111 get_empty_dot_spot = i + index - 0x2E;
112 AdjustRng(get_empty_dot_spot + 0x23);
113 }
114 }
115 if (add_exactly_this_many_bisection_dots == -1) {
116 int index = find(data, {0x48, 0x8B, 0xB4, 0x24, 0xB8, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xBC, 0x24, 0xB0, 0x00, 0x00, 0x00});
117 if (index != -1) {
118 add_exactly_this_many_bisection_dots = i + index - 0x20;
119 AdjustRng(add_exactly_this_many_bisection_dots + 0x1C);
120 }
121 }
122 if (make_a_shaper == -1) {
123 int index = find(data, {0xF7, 0xE3, 0xD1, 0xEA, 0x8D, 0x0C, 0x52});
124 if (index != -1) {
125 make_a_shaper = i + index - 0x19;
126 AdjustRng(make_a_shaper + 0x9);
127 AdjustRng(make_a_shaper + 0x35);
128 AdjustRng(make_a_shaper + 0x62);
129 }
130 }
131 if (/*Entity_Machine_Panel::*/init_pattern_data_lotus == -1) {
132 int index = find(data, {0x40, 0x55, 0x56, 0x48, 0x8D, 0x6C, 0x24, 0xB1});
133 if (index != -1) {
134 init_pattern_data_lotus = i + index;
135 AdjustRng(init_pattern_data_lotus + 0x433);
136 AdjustRng(init_pattern_data_lotus + 0x45B);
137 AdjustRng(init_pattern_data_lotus + 0x5A7);
138 AdjustRng(init_pattern_data_lotus + 0x5D6);
139 AdjustRng(init_pattern_data_lotus + 0x6F6);
140 AdjustRng(init_pattern_data_lotus + 0xD17);
141 AdjustRng(init_pattern_data_lotus + 0xFDA);
142 }
143 }
144 if (/*Entity_Record_Player::*/reroll_lotus_eater_stuff == -1) {
145 int index = find(data, {0xB8, 0xAB, 0xAA, 0xAA, 0xAA, 0x41, 0xC1, 0xE8});
146 if (index != -1) {
147 reroll_lotus_eater_stuff = i + index - 0x37;
148 AdjustRng(reroll_lotus_eater_stuff + 0x24);
149 AdjustRng(reroll_lotus_eater_stuff + 0x6B);
150 }
151 }
152 // These disable the random locations on timer panels, which would otherwise increment the RNG.
153 if (do_lotus_minutes == -1) {
154 int index = find(data, {0x0F, 0xBE, 0x6C, 0x08, 0xFF, 0x45});
155 if (index != -1) {
156 do_lotus_minutes = i + index - 0x2B;
157 _memory->WriteData<byte>({do_lotus_minutes + 0x43B}, {0x31, 0xC0, 0x90, 0x90, 0x90}); // xor eax, eax ;RNG returns 0
158 }
159 }
160 if (do_lotus_tenths == -1) {
161 int index = find(data, {0x00, 0x04, 0x00, 0x00, 0x41, 0x8D, 0x50, 0x09});
162 if (index != -1) {
163 do_lotus_tenths = i + index - 0x61;
164 _memory->WriteData<byte>({do_lotus_tenths + 0x103}, {0x31, 0xC0, 0x90, 0x90, 0x90}); // xor eax, eax ;RNG returns 0
165 }
166 }
167 if (do_lotus_eighths == -1) {
168 int index = find(data, {0x75, 0xF5, 0x0F, 0xBE, 0x44, 0x08, 0xFF});
169 if (index != -1) {
170 do_lotus_eighths = i + index - 0x39;
171 _memory->WriteData<byte>({do_lotus_eighths + 0x1E7}, {0x31, 0xC0, 0x90, 0x90, 0x90}); // xor eax, eax ;RNG returns 0
172 }
173 }
174} \ No newline at end of file
diff --git a/Source/ChallengeRandomizer.h b/Source/ChallengeRandomizer.h index 267c5cb..e642685 100644 --- a/Source/ChallengeRandomizer.h +++ b/Source/ChallengeRandomizer.h
@@ -7,6 +7,11 @@ public:
7 ChallengeRandomizer(const std::shared_ptr<Memory>& memory, int seed); 7 ChallengeRandomizer(const std::shared_ptr<Memory>& memory, int seed);
8 8
9private: 9private:
10 void HandleSigScans(int i, const std::vector<byte>& data);
11
10 void AdjustRng(int offset); 12 void AdjustRng(int offset);
11 std::shared_ptr<Memory> _memory; 13 std::shared_ptr<Memory> _memory;
14
15 int RNG_ADDR;
16 int RNG2_ADDR;
12}; 17};
diff --git a/Source/Memory.h b/Source/Memory.h index 278ce36..403b94a 100644 --- a/Source/Memory.h +++ b/Source/Memory.h
@@ -3,8 +3,8 @@
3#include <map> 3#include <map>
4#include <windows.h> 4#include <windows.h>
5 5
6#define GLOBALS 0x5B28C0 6// #define GLOBALS 0x5B28C0
7// #define GLOBALS 0x62A080 7#define GLOBALS 0x62A080
8 8
9// https://github.com/erayarslan/WriteProcessMemory-Example 9// https://github.com/erayarslan/WriteProcessMemory-Example
10// http://stackoverflow.com/q/32798185 10// http://stackoverflow.com/q/32798185
diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 2f3e72a..48e9a4b 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp
@@ -89,6 +89,22 @@ void Randomizer::AdjustSpeed() {
89 _memory->WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x 89 _memory->WritePanelData<float>(0x09EEC, OPEN_RATE, {0.075f}); // 3x
90} 90}
91 91
92void Randomizer::RandomizeLasers() {
93 Randomize(lasers, SWAP::TARGETS);
94 // Read the target of keep front laser, and write it to keep back laser.
95 std::vector<int> keepFrontLaserTarget = _memory->ReadPanelData<int>(0x0360E, TARGET, 1);
96 _memory->WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget);
97}
98
99void Randomizer::PreventSnipes()
100{
101 // Distance-gate swamp snipe 1 to prevent RNG swamp snipe
102 _memory->WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0});
103 // Distance-gate shadows laser to prevent sniping through the bars
104 _memory->WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5});
105}
106
107// Private methods
92void Randomizer::RandomizeTutorial() { 108void Randomizer::RandomizeTutorial() {
93 // Disable tutorial cursor speed modifications (not working?) 109 // Disable tutorial cursor speed modifications (not working?)
94 _memory->WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0}); 110 _memory->WritePanelData<float>(0x00295, CURSOR_SPEED_SCALE, {1.0});
@@ -130,8 +146,6 @@ void Randomizer::RandomizeKeep() {
130} 146}
131 147
132void Randomizer::RandomizeShadows() { 148void Randomizer::RandomizeShadows() {
133 // Distance-gate shadows laser to prevent sniping through the bars
134 _memory->WritePanelData<float>(0x19650, MAX_BROADCAST_DISTANCE, {2.5});
135 // Change the shadows tutorial cable to only activate avoid 149 // Change the shadows tutorial cable to only activate avoid
136 _memory->WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0}); 150 _memory->WritePanelData<int>(0x319A8, CABLE_TARGET_2, {0});
137 // Change shadows avoid 8 to power shadows follow 151 // Change shadows avoid 8 to power shadows follow
@@ -182,13 +196,10 @@ void Randomizer::RandomizeJungle() {
182} 196}
183 197
184void Randomizer::RandomizeSwamp() { 198void Randomizer::RandomizeSwamp() {
185 // Distance-gate swamp snipe 1 to prevent RNG swamp snipe
186 _memory->WritePanelData<float>(0x17C05, MAX_BROADCAST_DISTANCE, {15.0});
187} 199}
188 200
189void Randomizer::RandomizeMountain() { 201void Randomizer::RandomizeMountain() {
190 // Randomize lasers & some of mountain 202 // Randomize multipanel
191 Randomize(lasers, SWAP::TARGETS);
192 Randomize(mountainMultipanel, SWAP::LINES); 203 Randomize(mountainMultipanel, SWAP::LINES);
193 204
194 // Randomize final pillars order 205 // Randomize final pillars order
@@ -210,14 +221,10 @@ void Randomizer::RandomizeMountain() {
210 // Turn on new starting panels 221 // Turn on new starting panels
211 _memory->WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); 222 _memory->WritePanelData<float>(pillars[randomOrder[0]], POWER, {1.0f, 1.0f});
212 _memory->WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); 223 _memory->WritePanelData<float>(pillars[randomOrder[5]], POWER, {1.0f, 1.0f});
213
214 // Read the target of keep front laser, and write it to keep back laser.
215 std::vector<int> keepFrontLaserTarget = _memory->ReadPanelData<int>(0x0360E, TARGET, 1);
216 _memory->WritePanelData<int>(0x03317, TARGET, keepFrontLaserTarget);
217} 224}
218 225
219void Randomizer::RandomizeChallenge() { 226void Randomizer::RandomizeChallenge() {
220 ChallengeRandomizer cr(_memory, Random::RandInt(1, 0x1000)); 227 ChallengeRandomizer cr(_memory, Random::RandInt(1, 0x7FFFFFFF)); // 0 will trigger an "RNG not initialized" block
221} 228}
222 229
223void Randomizer::RandomizeAudioLogs() { 230void Randomizer::RandomizeAudioLogs() {
diff --git a/Source/Randomizer.h b/Source/Randomizer.h index 1180d43..88afcc6 100644 --- a/Source/Randomizer.h +++ b/Source/Randomizer.h
@@ -8,6 +8,8 @@ public:
8 bool GameIsRandomized(); 8 bool GameIsRandomized();
9 9
10 void AdjustSpeed(); 10 void AdjustSpeed();
11 void RandomizeLasers();
12 void PreventSnipes();
11 13
12 void ClearOffsets() {_memory->ClearOffsets();} 14 void ClearOffsets() {_memory->ClearOffsets();}
13 15
@@ -19,7 +21,6 @@ public:
19 }; 21 };
20 22
21private: 23private:
22
23 int _lastRandomizedFrame = 1 << 30; 24 int _lastRandomizedFrame = 1 << 30;
24 void RandomizeTutorial(); 25 void RandomizeTutorial();
25 void RandomizeSymmetry(); 26 void RandomizeSymmetry();