about summary refs log tree commit diff stats
path: root/gba/source/serialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'gba/source/serialize.c')
-rw-r--r--gba/source/serialize.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/gba/source/serialize.c b/gba/source/serialize.c new file mode 100644 index 0000000..6303772 --- /dev/null +++ b/gba/source/serialize.c
@@ -0,0 +1,227 @@
1#include "serialize.h"
2#include "gamedata.h"
3#include "link.h"
4
5#define UNOWN_SPECIES_INDEX 201
6#define SHEDINJA_SPECIES_INDEX 303
7
8enum Stat {
9 StatAttack,
10 StatDefense,
11 StatSpeed,
12 StatSpAttack,
13 StatSpDefense
14};
15
16u32 CalculateStat(
17 u8 base,
18 u32 iv,
19 u8 ev,
20 u8 level,
21 u8 statIndex,
22 u8 nature)
23{
24 u32 n = (((2 * base + iv + ev / 4) * level) / 100) + 5;
25
26 u8 naturePlus = (nature / 5);
27 u8 natureMinus = (nature % 5);
28
29 if (naturePlus != natureMinus)
30 {
31 if (statIndex == naturePlus)
32 {
33 return (u32)(n * 110) / 100;
34 } else if (statIndex == natureMinus)
35 {
36 return (u32)(n * 90) / 100;
37 }
38 }
39
40 return n;
41}
42
43void PokemonIntermediateInit(
44 struct PokemonIntermediate* pki,
45 struct BoxPokemon* bpkm,
46 u16 trainerId,
47 u16 secretId,
48 const struct GameData* gameData)
49{
50 DecryptBoxPokemon(bpkm);
51
52 struct PokemonSubstruct0* sub0 = GetBoxPokemonSubstruct0(bpkm);
53 struct PokemonSubstruct1* sub1 = GetBoxPokemonSubstruct1(bpkm);
54 struct PokemonSubstruct2* sub2 = GetBoxPokemonSubstruct2(bpkm);
55 struct PokemonSubstruct3* sub3 = GetBoxPokemonSubstruct3(bpkm);
56
57 struct BaseStats* baseStats = &gameData->baseStats[sub0->species];
58
59 for (int i=0; i<POKEMON_NAME_LENGTH; i++)
60 {
61 pki->nickname[i] = bpkm->nickname[i];
62 }
63
64 for (int i=0; i<OT_NAME_LENGTH; i++)
65 {
66 pki->otName[i] = bpkm->otName[i];
67 }
68
69 pki->otId = bpkm->otId;
70 pki->otGender = sub3->otGender;
71 pki->species = gameData->natOrder[sub0->species - 1];
72 pki->heldItem = sub0->heldItem;
73 pki->experience = sub0->experience;
74
75 pki->moves[0] = sub1->moves[0];
76 pki->moves[1] = sub1->moves[1];
77 pki->moves[2] = sub1->moves[2];
78 pki->moves[3] = sub1->moves[3];
79
80 pki->ppBonuses = sub0->ppBonuses;
81 pki->metLevel = sub3->metLevel;
82 pki->metLocation = sub3->metLocation;
83 pki->pokeball = sub3->pokeball;
84 pki->altAbility = sub3->altAbility;
85
86 // Derive nature from the personality value.
87 pki->nature = (bpkm->personality % 25);
88
89 // Derive gender from the personality value.
90 int genderThreshold = baseStats->genderRatio;
91
92 if ((genderThreshold == 0) || (genderThreshold == 255))
93 {
94 pki->gender = 0;
95 } else if (genderThreshold == 254)
96 {
97 pki->gender = 1;
98 } else {
99 u8 genderDeterminer = bpkm->personality & 0x000000FF;
100
101 if (genderDeterminer >= genderThreshold)
102 {
103 pki->gender = 0;
104 } else {
105 pki->gender = 1;
106 }
107 }
108
109 // Determine shininess from the personality value.
110 u16 shinyDeterminer =
111 (trainerId)
112 ^ (secretId)
113 ^ ((bpkm->personality >> 16) & 0x0000FFFF)
114 ^ (bpkm->personality & 0x0000FFFF);
115
116 if (shinyDeterminer < 8)
117 {
118 pki->shiny = 1;
119 } else {
120 pki->shiny = 0;
121 }
122
123 // Determine Unown letter from the personality value.
124 if (sub0->species == UNOWN_SPECIES_INDEX)
125 {
126 u8 unownDeterminer =
127 ((bpkm->personality & 0x07000000) >> 18)
128 | ((bpkm->personality & 0x00070000) >> 12)
129 | ((bpkm->personality & 0x00000700) >> 6)
130 | (bpkm->personality & 0x00000007);
131
132 pki->unownLetter = (unownDeterminer % 28);
133 }
134
135 // Calculate level from experience.
136 pki->level = 1;
137
138 const u32* expTable = gameData->expTables[baseStats->growthRate];
139 while ((pki->level <= 100) && (expTable[pki->level] <= sub0->experience))
140 {
141 pki->level++;
142 }
143
144 pki->level--;
145
146 // Calculate stats.
147 if (sub0->species == SHEDINJA_SPECIES_INDEX)
148 {
149 pki->hp = 1;
150 } else {
151 u32 n = 2 * baseStats->baseHP + sub3->hpIV;
152 pki->hp = (((n + sub2->hpEV / 4) * pki->level) / 100) + pki->level + 10;
153 }
154
155 pki->attack = CalculateStat(
156 baseStats->baseAttack,
157 sub3->attackIV,
158 sub2->attackEV,
159 pki->level,
160 0,
161 pki->nature);
162
163 pki->defense = CalculateStat(
164 baseStats->baseDefense,
165 sub3->defenseIV,
166 sub2->defenseEV,
167 pki->level,
168 1,
169 pki->nature);
170
171 pki->speed = CalculateStat(
172 baseStats->baseSpeed,
173 sub3->speedIV,
174 sub2->speedEV,
175 pki->level,
176 2,
177 pki->nature);
178
179 pki->spAttack = CalculateStat(
180 baseStats->baseSpAttack,
181 sub3->spAttackIV,
182 sub2->spAttackEV,
183 pki->level,
184 3,
185 pki->nature);
186
187 pki->spDefense = CalculateStat(
188 baseStats->baseSpDefense,
189 sub3->spDefenseIV,
190 sub2->spDefenseEV,
191 pki->level,
192 4,
193 pki->nature);
194
195 // Approximate the values of the contest conditions.
196 pki->cool = ((u16)(sub2->cool) * 10) / 255;
197 pki->beauty = ((u16)(sub2->beauty) * 10) / 255;
198 pki->cute = ((u16)(sub2->cute) * 10) / 255;
199 pki->smart = ((u16)(sub2->smart) * 10) / 255;
200 pki->tough = ((u16)(sub2->tough) * 10) / 255;
201 pki->sheen = ((u16)(sub2->sheen) * 10) / 255;
202
203 // Determine Pokerus status.
204 if (sub3->pokerus & 0xF0)
205 {
206 if (sub3->pokerus & 0x0F)
207 {
208 pki->pokerus = 1;
209 } else {
210 pki->pokerus = 2;
211 }
212 } else {
213 pki->pokerus = 0;
214 }
215
216 EncryptBoxPokemon(bpkm);
217}
218
219void PokemonIntermediateStream(struct PokemonIntermediate* pki)
220{
221 u32* raw = (u32*)pki;
222
223 for (int i=0; i<(sizeof(struct PokemonIntermediate)/4); i++)
224 {
225 directSendU32(raw[i]);
226 }
227}