about summary refs log tree commit diff stats
path: root/gba/source/libpayload.c
diff options
context:
space:
mode:
Diffstat (limited to 'gba/source/libpayload.c')
-rw-r--r--gba/source/libpayload.c312
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
14static void CryptBoxPokemon(struct BoxPokemon* pkm);
15static u16 crc16(const u8* data, u16 len);
16static 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*/
23void 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*/
32static 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*/
44void 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*/
53void 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*/
63void 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*/
75union 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*/
87union 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*/
109u16 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*/
130void 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*/
140struct 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*/
151struct 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*/
161struct 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*/
172struct 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*/
182struct 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*/
193struct 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*/
203struct 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*/
214struct 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*/
223u32 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*/
245u32 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 */
260u32 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 */
270u32 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 */
281static __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*/
299static 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