-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNearbySeeds.c
231 lines (203 loc) · 8.38 KB
/
NearbySeeds.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* Copyright (C) 2014-2015 Paul Fisher ("Fishaman P")
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY,
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* The source code and binaries for this software may be freely modified and redistributed, with
* only the following restrictions, lifted only by the express written consent of the author:
* - Both the copyright notice and this license must be reproduced, unmodified and in full,
* in all redistributed copies and derivative works.
* - You may not profit in any way from the redistribution of this software or any
* derivative works, including, but not limited to, direct sale of this software,
* charging for redistribution of this software, or advertising that profits
* specifically from this software.
*/
// The maximum amount of frame advances considered to be nearby.
#define MAX_DISTANCE 999999
#include <stdio.h>
static inline unsigned int gcrng(unsigned int input)
{
return (input * 0x343fd) + 0x269ec3;
}
static unsigned int gcrngr10000(unsigned int input)
{
register unsigned int i; // Loop counter
for (i = 0; i < 10000; i++) // 10000 is the number of frames considered "very nearby"
{
input = (input * 0xb9b33155) + 0xa170f641; // This reverses the GCRNG equation
}
return input;
}
static unsigned int distanceToSeed(unsigned int startSeed, unsigned int targetSeed)
{
register unsigned int distance;
for (distance = 0; startSeed != targetSeed; distance++)
{
startSeed = gcrng(startSeed);
}
return distance;
}
static void flush()
{
while (getchar() != '\n'); // Consume the rest of the line on the input
}
int main()
{
unsigned int currSeed; // The RNG seed to use as a base
unsigned int matches; // // The number of seeds that fit user requirements
unsigned int choiceValue; // All execution paths require a single 32bit integer
printf("Select from the following functionality:\n");
printf("1. Distance to seed\n");
printf("2. Custom TID\n");
printf("3. Make PID shiny\n");
printf("4. TID offset from target\n\n");
matches = 0;
do // Get the choice the user wants
{
printf("Enter the number for your selection: ");
matches = scanf("%u", &choiceValue); // Matches isn't meant to be used like this, but whatever
flush(); // Flush the input so we can check for a newline properly
}
while (!(matches && (choiceValue < 5) && (choiceValue != 0))); // Verify that the user entered a valid choice
matches = 0;
do // Get the current seed
{
if (choiceValue == 4)
{
printf("Target seed: 0x");
}
else
{
printf("Current seed: 0x");
}
matches = scanf("%x", &currSeed); // Matches isn't meant to be used like this, but whatever
flush(); // Flush the input so we can check for a newline properly
}
while (!matches); // Verify that the user entered a valid seed
switch (choiceValue)
{
case 1: // Distance to seed
{
unsigned int targetSeed; // The seed the user wants to hit
matches = 0;
do // Get the target seed
{
printf("Target seed: 0x");
matches = scanf("%x", &targetSeed); // Matches isn't meant to be used like this, but whatever
flush(); // Flush the input so we can check for a newline properly
}
while (!matches); // Verify that the user entered a valid seed
matches = distanceToSeed(currSeed, targetSeed);
if (matches == 0)
{
printf("Error: You are at the target seed already!\n");
}
else
{
printf("Advances needed: %u\n", matches);
}
break;
}
case 2: // Custom TID
{
unsigned int tid; // The Trainer ID the user wants to abuse for
unsigned int distance; // The number of frame advances required
matches = 0;
do // Get the Trainer ID
{
printf("Trainer ID: ");
matches = scanf("%u", &tid); // Matches isn't meant to be used like this, but whatever
flush(); // Flush the input so we can check for a newline properly
}
while (!(matches && (tid < 0x10000))); // Verify that the user entered a valid TID
matches = 0;
for (distance = 1; distance < MAX_DISTANCE; distance++)
{
currSeed = gcrng(currSeed);
if ((currSeed >> 16) == tid) // This seed will produce the desired TID
{
printf("%u/%u: %u advances\n", tid, gcrng(currSeed) >> 16, distance);
matches++;
}
}
if (matches == 0)
{
printf("Sorry, no nearby seeds will produce that TID.\n");
}
break;
}
case 3: // Make PID shiny
{
unsigned int pid; // The PID the user wants to make shiny
unsigned int distance; // The number of frame advances required
matches = 0;
do // Get the PID
{
printf("PID: 0x");
matches = scanf("%x", &pid); // Matches isn't meant to be used like this, but whatever
flush(); // Flush the input so we can check for a newline properly
}
while (!matches); // Verify that the user entered a valid PID
pid = (pid & 0x0000FFFF) ^ (pid >> 16); // xor the two halves of the PID to prep for calculations
matches = 0;
for (distance = 1; distance < MAX_DISTANCE; distance++)
{
currSeed = gcrng(currSeed);
if (((currSeed >> 16) ^ (gcrng(currSeed) >> 16) ^ pid) < 8) // This TID/SID combo will make the PID shiny
{
printf("%u/%u: %u advances\n", currSeed >> 16, gcrng(currSeed) >> 16, distance);
matches++;
}
}
if (matches == 0)
{
printf("Sorry, no nearby seeds will make that PID shiny.\n");
}
break;
}
case 4: // TID offset from target
{
unsigned int tid; // The Trainer ID the user actually got
int distance; // The number of frames the user was off
matches = 0;
do // Get the Trainer ID
{
printf("Actual Trainer ID: ");
matches = scanf("%u", &tid); // Matches isn't meant to be used like this, but whatever
flush(); // Flush the input so we can check for a newline properly
}
while (!(matches && (tid < 0x10000))); // Verify that the user entered a valid TID
if ((currSeed >> 16) == tid) // The target seed produces the TID the user got
{
printf("Error: You got your target Trainer ID!\n");
break;
}
matches = 0;
currSeed = gcrngr10000(currSeed); // Rewind the RNG to find earlier seeds
for (distance = 9999; distance > 0; distance--)
{
currSeed = gcrng(currSeed);
if ((currSeed >> 16) == tid) // A possible match was found
{
printf("%u/%u: %u frames early\n", tid, gcrng(currSeed) >> 16, distance);
matches++;
}
}
currSeed = gcrng(currSeed); // Consume the RNG frame for the target seed
for (distance = 1; distance < 10000; distance++)
{
currSeed = gcrng(currSeed);
if ((currSeed >> 16) == tid) // A possible match was found
{
printf("%u/%u: %u frames late\n", tid, gcrng(currSeed) >> 16, distance);
matches++;
}
}
if (matches == 0)
{
printf("Sorry, no nearby seeds give that Trainer ID.\n");
}
break;
}
}
}