diff options
author | slipstream/RoL <l33twax@yahoo.com> | 2017-02-26 14:27:20 +0000 |
---|---|---|
committer | slipstream/RoL <l33twax@yahoo.com> | 2017-02-26 14:27:20 +0000 |
commit | e37cc7de9583b00166e96a6632ba25edefff43ca (patch) | |
tree | 592e49249f8e171a29cf3c140081ef054975eb59 /gba/source/libpayload.c | |
parent | fac6ea00fd51e5be1d99db44746ed046378a6c65 (diff) | |
download | gen3uploader-e37cc7de9583b00166e96a6632ba25edefff43ca.tar.gz gen3uploader-e37cc7de9583b00166e96a6632ba25edefff43ca.tar.bz2 gen3uploader-e37cc7de9583b00166e96a6632ba25edefff43ca.zip |
Major changes
- Added saveblock structures. - Changed example payload, now it warps to Hall of Fame. - Added helper library for Pokémon manipulation, checksum calculation, etc. - Removed libSave, it's not needed.
Diffstat (limited to 'gba/source/libpayload.c')
-rw-r--r-- | gba/source/libpayload.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/gba/source/libpayload.c b/gba/source/libpayload.c new file mode 100644 index 0000000..f13a34f --- /dev/null +++ b/gba/source/libpayload.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* | ||
2 | * Example Gen3-multiboot payload by slipstream/RoL 2017. | ||
3 | * | ||
4 | * This software may be modified and distributed under the terms | ||
5 | * of the MIT license. See the LICENSE file for details. | ||
6 | * | ||
7 | * libpayload.c: contains helper functions for the payload | ||
8 | */ | ||
9 | |||
10 | #include <gba.h> | ||
11 | #include "payload.h" | ||
12 | |||
13 | // private functions | ||
14 | static void CryptBoxPokemon(struct BoxPokemon* pkm); | ||
15 | static u16 crc16(const u8* data, u16 len); | ||
16 | static u32 CalculateRamScriptDataChecksum(struct RamScriptData* ramScript); | ||
17 | |||
18 | /** | ||
19 | * Decrypts the substructures of a Pokémon structure, so they can be viewed or modified easily. | ||
20 | * Remember to call EncryptPokemon() afterwards. | ||
21 | * @param struct Pokemon* pkm The Pokémon to decrypt the substructures of. | ||
22 | */ | ||
23 | void DecryptPokemon(struct Pokemon* pkm) { | ||
24 | struct BoxPokemon* boxMon = &(pkm->box); | ||
25 | CryptBoxPokemon(boxMon); | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * Private function that does the actual work of crypting the substructures of a BoxPokemon. | ||
30 | * @param struct BoxPokemon* pkm The BoxPokemon whose substructures will be crypted. | ||
31 | */ | ||
32 | static void CryptBoxPokemon(struct BoxPokemon* pkm) { | ||
33 | for (u32 i = 0; i < 12; i++) { | ||
34 | pkm->secure.raw[i] ^= (pkm->otId ^ pkm->personality); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * Decrypts the substructures of a core Pokémon structure, so they can be viewed or modified easily. | ||
40 | * Used by DecryptPokemon(). | ||
41 | * Remember to call EncryptPokemon() afterwards. | ||
42 | * @param struct BoxPokemon* pkm The BoxPokemon to decrypt the substructures of. | ||
43 | */ | ||
44 | void DecryptBoxPokemon(struct BoxPokemon* pkm) { | ||
45 | CryptBoxPokemon(pkm); | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Encrypts the substructures of a Pokémon structure, and fixes the checksum. | ||
50 | * Must be used after DecryptPokemon() has been called, otherwise the Pokémon you decrypted and forgot to re-encrypt will become a Bad Egg. | ||
51 | * @param struct Pokemon* pkm The Pokémon to encrypt the substructures and fix the checksum of. | ||
52 | */ | ||
53 | void EncryptPokemon(struct Pokemon* pkm) { | ||
54 | struct BoxPokemon* boxMon = &(pkm->box); | ||
55 | EncryptBoxPokemon(boxMon); | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Encrypts the substructures of a core Pokémon structure, and fixes the checksum. | ||
60 | * Must be used after DecryptBoxPokemon() has been called, otherwise the Pokémon you decrypted and forgot to re-encrypt will become a Bad Egg. | ||
61 | * @param struct BoxPokemon* pkm The BoxPokemon to encrypt the substructures and fix the checksum of. | ||
62 | */ | ||
63 | void EncryptBoxPokemon(struct BoxPokemon* pkm) { | ||
64 | FixBoxPokemonChecksum(pkm); | ||
65 | CryptBoxPokemon(pkm); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * Gets a substructure of a Pokémon structure. | ||
70 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
71 | * @param struct Pokemon* pkm The Pokemon to get a substructure of. | ||
72 | * @param u8 substructId The substructure to get. | ||
73 | * @return union PokemonSubstruct* The substructure. | ||
74 | */ | ||
75 | union PokemonSubstruct* GetPokemonSubstruct(struct Pokemon* pkm,u8 substructId) { | ||
76 | struct BoxPokemon* boxMon = &(pkm->box); | ||
77 | return GetBoxPokemonSubstruct(boxMon,substructId); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * Gets a substructure of a core Pokémon structure. | ||
82 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
83 | * @param struct Pokemon* pkm The Pokemon to get a substructure of. | ||
84 | * @param u8 substructId The substructure to get. | ||
85 | * @return union PokemonSubstruct* The substructure. | ||
86 | */ | ||
87 | union PokemonSubstruct* GetBoxPokemonSubstruct(struct BoxPokemon* pkm,u8 substructId) { | ||
88 | if (substructId > 3) return NULL; | ||
89 | u32 personality = pkm->personality; | ||
90 | // Staring at the substruct indexes, I noticed the last two columns are the reverse of the first two! | ||
91 | // that is, substructId==2 column is the reverse of substructId==1, substructId==3 is the reverse of substructId==0 | ||
92 | // At least that means there's no need to hardcode all four. | ||
93 | u8 substruct_idxes[2][24] = { | ||
94 | { 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3 }, | ||
95 | { 1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2 } | ||
96 | }; | ||
97 | u32 modulo = (personality % 24); | ||
98 | if (substructId < 2) { | ||
99 | return &( pkm->secure.substructs[ substruct_idxes[substructId][modulo] ] ); | ||
100 | } | ||
101 | return &( pkm->secure.substructs[ substruct_idxes[3 - substructId][23 - modulo] ] ); | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Gets the checksum of a core Pokémon structure. | ||
106 | * @param struct BoxPokemon* pkm The BoxPokemon to calculate the checksum of. | ||
107 | * @return u16 The checksum. | ||
108 | */ | ||
109 | u16 CalculateBoxPokemonChecksum(struct BoxPokemon* pkm) { | ||
110 | u16 checksum = 0; | ||
111 | union PokemonSubstruct* substructs[4] = { | ||
112 | GetBoxPokemonSubstruct(pkm,0), | ||
113 | GetBoxPokemonSubstruct(pkm,1), | ||
114 | GetBoxPokemonSubstruct(pkm,2), | ||
115 | GetBoxPokemonSubstruct(pkm,3) | ||
116 | }; | ||
117 | |||
118 | for (int substruct = 0; substruct < 4; substruct++) { | ||
119 | for (int i = 0; i < 6; i++) { | ||
120 | checksum += substructs[substruct]->raw[i]; | ||
121 | } | ||
122 | } | ||
123 | return checksum; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Fixes the checksum of a core Pokémon structure. | ||
128 | * @param struct BoxPokemon* pkm The BoxPokemon to fix the checksum of. | ||
129 | */ | ||
130 | void FixBoxPokemonChecksum(struct BoxPokemon* pkm) { | ||
131 | pkm->checksum = CalculateBoxPokemonChecksum(pkm); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Gets the zeroth substructure ("Growth") of a Pokémon structure. | ||
136 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
137 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
138 | * @return struct PokemonSubstruct0* The substructure. | ||
139 | */ | ||
140 | struct PokemonSubstruct0* GetPokemonSubstruct0(struct Pokemon* pkm) { | ||
141 | struct BoxPokemon* boxMon = &(pkm->box); | ||
142 | return GetBoxPokemonSubstruct0(boxMon); | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * Gets the zeroth substructure ("Growth") of a core Pokémon structure. | ||
147 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
148 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
149 | * @return struct PokemonSubstruct0* The substructure. | ||
150 | */ | ||
151 | struct PokemonSubstruct0* GetBoxPokemonSubstruct0(struct BoxPokemon* pkm) { | ||
152 | return &( GetBoxPokemonSubstruct(pkm,0)->type0 ); | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Gets the first substructure ("Attacks") of a Pokémon structure. | ||
157 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
158 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
159 | * @return struct PokemonSubstruct0* The substructure. | ||
160 | */ | ||
161 | struct PokemonSubstruct1* GetPokemonSubstruct1(struct Pokemon* pkm) { | ||
162 | struct BoxPokemon* boxMon = &(pkm->box); | ||
163 | return GetBoxPokemonSubstruct1(boxMon); | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Gets the first substructure ("Attacks") of a core Pokémon structure. | ||
168 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
169 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
170 | * @return struct PokemonSubstruct1* The substructure. | ||
171 | */ | ||
172 | struct PokemonSubstruct1* GetBoxPokemonSubstruct1(struct BoxPokemon* pkm) { | ||
173 | return &( GetBoxPokemonSubstruct(pkm,1)->type1 ); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * Gets the second substructure ("EVs & Condition") of a Pokémon structure. | ||
178 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
179 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
180 | * @return struct PokemonSubstruct0* The substructure. | ||
181 | */ | ||
182 | struct PokemonSubstruct2* GetPokemonSubstruct2(struct Pokemon* pkm) { | ||
183 | struct BoxPokemon* boxMon = &(pkm->box); | ||
184 | return GetBoxPokemonSubstruct2(boxMon); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * Gets the second substructure ("EVs & Condition") of a core Pokémon structure. | ||
189 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
190 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
191 | * @return struct PokemonSubstruct2* The substructure. | ||
192 | */ | ||
193 | struct PokemonSubstruct2* GetBoxPokemonSubstruct2(struct BoxPokemon* pkm) { | ||
194 | return &( GetBoxPokemonSubstruct(pkm,2)->type2 ); | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * Gets the third substructure ("Miscellaneous") of a Pokémon structure. | ||
199 | * Call DecryptPokemon() first or the substructure data will be encrypted. | ||
200 | * @param struct Pokemon* pkm The Pokémon to get a substructure of. | ||
201 | * @return struct PokemonSubstruct0* The substructure. | ||
202 | */ | ||
203 | struct PokemonSubstruct3* GetPokemonSubstruct3(struct Pokemon* pkm) { | ||
204 | struct BoxPokemon* boxMon = &(pkm->box); | ||
205 | return GetBoxPokemonSubstruct3(boxMon); | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Gets the third substructure ("Miscellaneous") of a core Pokémon structure. | ||
210 | * Call DecryptBoxPokemon() first or the substructure data will be encrypted. | ||
211 | * @param struct BoxPokemon* pkm The BoxPokemon to get the substructure of. | ||
212 | * @return struct PokemonSubstruct3* The substructure. | ||
213 | */ | ||
214 | struct PokemonSubstruct3* GetBoxPokemonSubstruct3(struct BoxPokemon* pkm) { | ||
215 | return &( GetBoxPokemonSubstruct(pkm,3)->type3 ); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * Calculates the checksum for an R/S-specific Enigma Berry structure in SaveBlock1. | ||
220 | * @param struct EnigmaBerry* enigmaBerry The R/S-specific Enigma Berry to calculate the checksum for. | ||
221 | * @return u32 The checksum. | ||
222 | */ | ||
223 | u32 CalculateEnigmaBerryChecksumRS(struct EnigmaBerry* enigmaBerry) { | ||
224 | if (!GAME_RS) return 0; // Enigma Berry structure changed in FR/LG, use CalculateEnigmaBerryChecksumFRLGE() instead. | ||
225 | u32 checksum = 0; | ||
226 | // Save off and zero out the original Enigma Berry description pointers. | ||
227 | const u8* description[2] = { enigmaBerry->berry.description1, enigmaBerry->berry.description2 }; | ||
228 | enigmaBerry->berry.description1 = enigmaBerry->berry.description2 = NULL; | ||
229 | u8* enigmaBerryBytes = (u8*)enigmaBerry; | ||
230 | // Calculate the checksum. | ||
231 | for (u32 i = 0; i < 1324; i++) { | ||
232 | checksum += enigmaBerryBytes[i]; | ||
233 | } | ||
234 | // Restore the saved description. | ||
235 | enigmaBerry->berry.description1 = description[0]; | ||
236 | enigmaBerry->berry.description2 = description[1]; | ||
237 | return checksum; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * Calculates the checksum for an FR/LG/Emerald-specific Enigma Berry structure in SaveBlock1. | ||
242 | * @param struct EnigmaBerryFRLGE* enigmaBerry The FR/LG/Emerald-specific Enigma Berry to calculate the checksum for. | ||
243 | * @return u32 The checksum. | ||
244 | */ | ||
245 | u32 CalculateEnigmaBerryChecksumFRLGE(struct EnigmaBerryFRLGE* enigmaBerry) { | ||
246 | if (GAME_RS) return 0; // Enigma Berry structure is different in R/S, use CalculateEnigmaBerryChecksumRS() instead. | ||
247 | u32 checksum = 0; | ||
248 | u8* enigmaBerryBytes = (u8*)enigmaBerry; | ||
249 | for (int i = 0; i < 0x30; i++) { | ||
250 | checksum += enigmaBerryBytes[i]; | ||
251 | } | ||
252 | return checksum; | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * Calculates the checksum for an unspecified Enigma Berry structure in SaveBlock1. (detected by current game) | ||
257 | * @param void* enigmaBerry The Enigma Berry structure to calculate the checksum for. | ||
258 | * @return u32 The checksum. | ||
259 | */ | ||
260 | u32 CalculateEnigmaBerryChecksum(void* enigmaBerry) { | ||
261 | if (GAME_RS) return CalculateEnigmaBerryChecksumRS( (struct EnigmaBerry*) enigmaBerry ); | ||
262 | return CalculateEnigmaBerryChecksumFRLGE( (struct EnigmaBerryFRLGE*) enigmaBerry ); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Calculates the checksum for a RAM script structure in SaveBlock1. | ||
267 | * @param struct RamScript* ramScript The RAM script structure to calculate the checksum for. | ||
268 | * @return u32 The checksum. | ||
269 | */ | ||
270 | u32 CalculateRamScriptChecksum(struct RamScript* ramScript) { | ||
271 | asm(""); // make sure the call to CalculateRamScriptDataChecksum() is *not* inlined. | ||
272 | // For some reason, if it gets inlined, something happens, and the wrong length is used when checksumming... | ||
273 | return CalculateRamScriptDataChecksum(&ramScript->data); | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * Calculates the checksum for a RAM script structure in SaveBlock1. | ||
278 | * @param struct RamScript* ramScript The RAM script structure to calculate the checksum for. | ||
279 | * @return u32 The checksum. | ||
280 | */ | ||
281 | static __attribute__ ((noinline)) u32 CalculateRamScriptDataChecksum(struct RamScriptData* ramScript) { | ||
282 | u32 checksum = 0; | ||
283 | u32 i = 0; | ||
284 | u8* ramScriptBytes = (u8*)(ramScript); | ||
285 | if (GAME_RS) { | ||
286 | for (i = 0; i < sizeof(struct RamScriptData); i++) checksum += ramScriptBytes[i]; | ||
287 | return checksum; | ||
288 | } | ||
289 | |||
290 | return (u32)crc16(ramScriptBytes,sizeof(struct RamScriptData) + 1); | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * Private function to CRC-16, (used by FR/LG/Emerald ramscript checksum). Adapted from http://forums.glitchcity.info/index.php?topic=7114.0 | ||
295 | * @param u8* Data to checksum | ||
296 | * @param u16 Length of data | ||
297 | * @return u16 The checksum | ||
298 | */ | ||
299 | static u16 crc16(const u8* data, u16 len) { | ||
300 | u16 crc = 0x1121; | ||
301 | for (u16 i = 0; i < len; ++i) { | ||
302 | crc ^= data[i]; | ||
303 | for (u16 j = 0; j < 8; ++j) { | ||
304 | if(crc & 1) { | ||
305 | crc = (crc >> 1) ^ 0x8408; | ||
306 | } else { | ||
307 | crc >>= 1; | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | return ~crc; | ||
312 | } \ No newline at end of file | ||