1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "shadowdive/error.h"
5 #include "shadowdive/pilot.h"
6
7 #define PILOT_BLOCK_LENGTH 428
8
sd_pilot_create(sd_pilot * pilot)9 int sd_pilot_create(sd_pilot *pilot) {
10 if(pilot == NULL) {
11 return SD_INVALID_INPUT;
12 }
13 memset(pilot, 0, sizeof(sd_pilot));
14 return SD_SUCCESS;
15 }
16
sd_pilot_free(sd_pilot * pilot)17 void sd_pilot_free(sd_pilot *pilot) {
18 for(int m = 0; m < 10; m++) {
19 free(pilot->quotes[m]);
20 }
21 }
22
23 // Reads exactly 24 + 8 + 11 = 43 bytes
sd_pilot_load_player_from_mem(sd_mreader * mr,sd_pilot * pilot)24 void sd_pilot_load_player_from_mem(sd_mreader *mr, sd_pilot *pilot) {
25 sd_mread_buf(mr, pilot->name, 18);
26 pilot->wins = sd_mread_uword(mr);
27 pilot->losses = sd_mread_uword(mr);
28 pilot->rank = sd_mread_ubyte(mr);
29 pilot->har_id = sd_mread_ubyte(mr);
30
31 uint16_t stats_a = sd_mread_uword(mr);
32 uint16_t stats_b = sd_mread_uword(mr);
33 uint16_t stats_c = sd_mread_uword(mr);
34 uint8_t stats_d = sd_mread_ubyte(mr);
35 pilot->arm_power = (stats_a >> 0) & 0x1F;
36 pilot->leg_power = (stats_a >> 5) & 0x1F;
37 pilot->arm_speed = (stats_a >> 10) & 0x1F;
38 pilot->leg_speed = (stats_b >> 0) & 0x1F;
39 pilot->armor = (stats_b >> 5) & 0x1F;
40 pilot->stun_resistance = (stats_b >> 10) & 0x1F;
41 pilot->agility = (stats_c >> 0) & 0x7F;
42 pilot->power = (stats_c >> 7) & 0x7F;
43 pilot->endurance = (stats_d >> 0) & 0x7F;
44 sd_mskip(mr, 1);
45
46 pilot->offense = sd_mread_uword(mr);
47 pilot->defense = sd_mread_uword(mr);
48 pilot->money = sd_mread_udword(mr);
49 pilot->color_1 = sd_mread_ubyte(mr);
50 pilot->color_2 = sd_mread_ubyte(mr);
51 pilot->color_3 = sd_mread_ubyte(mr);
52 }
53
sd_pilot_load_from_mem(sd_mreader * mr,sd_pilot * pilot)54 void sd_pilot_load_from_mem(sd_mreader *mr, sd_pilot *pilot) {
55 pilot->unknown_a = sd_mread_udword(mr);
56
57 sd_pilot_load_player_from_mem(mr, pilot);
58
59 sd_mread_buf(mr, pilot->trn_name, 13);
60 sd_mread_buf(mr, pilot->trn_desc, 31);
61 sd_mread_buf(mr, pilot->trn_image, 13);
62
63 pilot->unk_f_c = sd_mread_float(mr);
64 pilot->unk_f_d = sd_mread_float(mr);
65 sd_mskip(mr, 40); // Pointless pointers
66 pilot->pilot_id = sd_mread_ubyte(mr);
67 pilot->unknown_k = sd_mread_ubyte(mr);
68 pilot->force_arena = sd_mread_uword(mr);
69 pilot->difficulty = (sd_mread_ubyte(mr) >> 3) & 0x3; // 155-156
70 sd_mread_buf(mr, pilot->unk_block_b, 2);
71 pilot->movement = sd_mread_ubyte(mr);
72 sd_mread_buf(mr, (char*)pilot->unk_block_c, 6);
73 sd_mread_buf(mr, pilot->enhancements, 11);
74
75 // Flags (3)
76 sd_mskip(mr, 1); // Nothing here
77 uint8_t req_flags = sd_mread_ubyte(mr); // Secret, only fight once flags
78 pilot->secret = (req_flags & 0x02) ? 1 : 0;
79 pilot->only_fight_once = (req_flags & 0x08) ? 1 : 0;
80 sd_mskip(mr, 1); // Nothing here either
81
82 // Requirements (10)
83 uint16_t reqs[5];
84 sd_mread_buf(mr, (char*)reqs, 10);
85 pilot->req_rank = reqs[0] & 0xFF;
86 pilot->req_max_rank = (reqs[0] >> 8) & 0xFF;
87 pilot->req_fighter = reqs[1] & 0x1F;
88 pilot->req_difficulty = (reqs[2] >> 8) & 0x0F;
89 pilot->req_enemy = (reqs[2] & 0xFF);
90 pilot->req_vitality = reqs[3] & 0x7F;
91 pilot->req_accuracy = (reqs[3] >> 7) & 0x7F;
92 pilot->req_avg_dmg = reqs[4] & 0x7F;
93 pilot->req_scrap = (reqs[4] & 0x80) ? 1 : 0;
94 pilot->req_destroy = ((reqs[4] >> 8) & 0x01) ? 1 : 0;
95
96 // Attitude
97 uint16_t att[3];
98 sd_mread_buf(mr, (char*)att, 6);
99 pilot->att_normal = (att[0] >> 4) & 0x7F;
100 pilot->att_hyper = att[1] & 0x7F;
101 pilot->att_jump = (att[1] >> 7) & 0x7F;
102 pilot->att_def = att[2] & 0x7F;
103 pilot->att_sniper = (att[2] >> 7) & 0x7F;
104
105 sd_mread_buf(mr, (char*)pilot->unk_block_d, 6);
106
107 pilot->ap_throw = sd_mread_word(mr);
108 pilot->ap_special = sd_mread_word(mr);
109 pilot->ap_jump = sd_mread_word(mr);
110 pilot->ap_high = sd_mread_word(mr);
111 pilot->ap_low = sd_mread_word(mr);
112 pilot->ap_middle = sd_mread_word(mr);
113 pilot->pref_jump = sd_mread_word(mr);
114 pilot->pref_fwd = sd_mread_word(mr);
115 pilot->pref_back = sd_mread_word(mr);
116
117 pilot->unknown_e = sd_mread_udword(mr);
118 pilot->learning = sd_mread_float(mr);
119 pilot->forget = sd_mread_float(mr);
120 sd_mread_buf(mr, pilot->unk_block_f, 14);
121 pilot->enemies_inc_unranked = sd_mread_uword(mr);
122 pilot->enemies_ex_unranked = sd_mread_uword(mr);
123 pilot->unk_d_a = sd_mread_uword(mr);
124 pilot->unk_d_b = sd_mread_udword(mr);
125 pilot->winnings = sd_mread_udword(mr);
126 pilot->total_value = sd_mread_udword(mr);
127 pilot->unk_f_a = sd_mread_float(mr);
128 pilot->unk_f_b = sd_mread_float(mr);
129 sd_mskip(mr, 8);
130 sd_palette_create(&pilot->palette);
131 sd_palette_mload_range(mr, &pilot->palette, 0, 48);
132 pilot->unk_block_i = sd_mread_uword(mr);
133
134 pilot->photo_id = sd_mread_uword(mr) & 0x3FF;
135 }
136
sd_pilot_load(sd_reader * reader,sd_pilot * pilot)137 int sd_pilot_load(sd_reader *reader, sd_pilot *pilot) {
138 if(reader == NULL || pilot == NULL) {
139 return SD_INVALID_INPUT;
140 }
141
142 // Read block, XOR, Read to pilot, free memory
143 sd_mreader *mr = sd_mreader_open_from_reader(reader, PILOT_BLOCK_LENGTH);
144 sd_mreader_xor(mr, PILOT_BLOCK_LENGTH & 0xFF);
145 sd_pilot_load_from_mem(mr, pilot);
146 sd_mreader_close(mr);
147
148 // Quote block
149 for(int m = 0; m < 10; m++) {
150 pilot->quotes[m] = sd_read_variable_str(reader);
151 }
152 return SD_SUCCESS;
153 }
154
sd_pilot_save_player_to_mem(sd_mwriter * w,const sd_pilot * pilot)155 void sd_pilot_save_player_to_mem(sd_mwriter *w, const sd_pilot *pilot) {
156 sd_mwrite_buf(w, pilot->name, 18);
157 sd_mwrite_uword(w, pilot->wins);
158 sd_mwrite_uword(w, pilot->losses);
159 sd_mwrite_ubyte(w, pilot->rank);
160 sd_mwrite_ubyte(w, pilot->har_id);
161
162 uint16_t stats_a = 0, stats_b = 0, stats_c = 0;
163 uint8_t stats_d = 0;
164 stats_a |= (pilot->arm_power & 0x1F) << 0;
165 stats_a |= (pilot->leg_power & 0x1F) << 5;
166 stats_a |= (pilot->arm_speed & 0x1F) << 10;
167 stats_b |= (pilot->leg_speed & 0x1F) << 0;
168 stats_b |= (pilot->armor & 0x1F) << 5;
169 stats_b |= (pilot->stun_resistance & 0x1F) << 10;
170 stats_c |= (pilot->agility & 0x7F) << 0;
171 stats_c |= (pilot->power & 0x7F) << 7;
172 stats_d |= (pilot->endurance & 0x7F) << 0;
173 sd_mwrite_uword(w, stats_a);
174 sd_mwrite_uword(w, stats_b);
175 sd_mwrite_uword(w, stats_c);
176 sd_mwrite_ubyte(w, stats_d);
177 sd_mwrite_fill(w, 0, 1);
178
179 sd_mwrite_uword(w, pilot->offense);
180 sd_mwrite_uword(w, pilot->defense);
181 sd_mwrite_udword(w, pilot->money);
182 sd_mwrite_ubyte(w, pilot->color_1);
183 sd_mwrite_ubyte(w, pilot->color_2);
184 sd_mwrite_ubyte(w, pilot->color_3);
185 }
186
sd_pilot_save_to_mem(sd_mwriter * w,const sd_pilot * pilot)187 void sd_pilot_save_to_mem(sd_mwriter *w, const sd_pilot *pilot) {
188 // Write the pilot block
189 sd_mwrite_udword(w, pilot->unknown_a);
190
191 sd_pilot_save_player_to_mem(w, pilot);
192
193 sd_mwrite_buf(w, pilot->trn_name, 13);
194 sd_mwrite_buf(w, pilot->trn_desc, 31);
195 sd_mwrite_buf(w, pilot->trn_image, 13);
196
197 sd_mwrite_float(w, pilot->unk_f_c);
198 sd_mwrite_float(w, pilot->unk_f_d);
199 sd_mwrite_fill(w, 0, 40);
200 sd_mwrite_ubyte(w, pilot->pilot_id);
201 sd_mwrite_ubyte(w, pilot->unknown_k);
202 sd_mwrite_uword(w, pilot->force_arena);
203 sd_mwrite_ubyte(w, (pilot->difficulty & 0x3) << 3);
204 sd_mwrite_buf(w, pilot->unk_block_b, 2);
205 sd_mwrite_ubyte(w, pilot->movement);
206 sd_mwrite_buf(w, (char*)pilot->unk_block_c, 6);
207 sd_mwrite_buf(w, pilot->enhancements, 11);
208
209 // Flags
210 sd_mwrite_ubyte(w, 0);
211 uint8_t req_flags = 0;
212 if(pilot->secret)
213 req_flags |= 0x02;
214 if(pilot->only_fight_once)
215 req_flags |= 0x08;
216 sd_mwrite_ubyte(w, req_flags);
217 sd_mwrite_ubyte(w, 0);
218
219 // Requirements (10)
220 uint16_t reqs[5];
221 memset((char*)reqs, 0, 10);
222 reqs[0] |= (pilot->req_max_rank & 0xFF) << 8;
223 reqs[0] |= (pilot->req_rank & 0xFF);
224 reqs[1] |= (pilot->req_fighter & 0x1F);
225 reqs[2] |= (pilot->req_difficulty & 0x0F) << 8;
226 reqs[2] |= (pilot->req_enemy & 0xFF);
227 reqs[3] |= (pilot->req_accuracy & 0x7F) << 7;
228 reqs[3] |= (pilot->req_vitality & 0x7F);
229 reqs[4] |= (pilot->req_destroy & 0x01) << 8;
230 reqs[4] |= (pilot->req_scrap & 0x01) << 7;
231 reqs[4] |= (pilot->req_avg_dmg & 0x7F);
232 sd_mwrite_buf(w, (char*)reqs, 10);
233
234 // Attitude
235 uint16_t att[3];
236 memset((char*)att, 0, 6);
237 att[0] |= (pilot->att_normal & 0x7F) << 4;
238 att[1] |= (pilot->att_jump & 0x7F) << 7;
239 att[1] |= (pilot->att_hyper & 0x7F);
240 att[2] |= (pilot->att_sniper & 0x7F) << 7;
241 att[2] |= (pilot->att_def & 0x7F);
242 sd_mwrite_buf(w, (char*)att, 6);
243
244 sd_mwrite_buf(w, (char*)pilot->unk_block_d, 6);
245
246 sd_mwrite_word(w, pilot->ap_throw);
247 sd_mwrite_word(w, pilot->ap_special);
248 sd_mwrite_word(w, pilot->ap_jump);
249 sd_mwrite_word(w, pilot->ap_high);
250 sd_mwrite_word(w, pilot->ap_low);
251 sd_mwrite_word(w, pilot->ap_middle);
252 sd_mwrite_word(w, pilot->pref_jump);
253 sd_mwrite_word(w, pilot->pref_fwd);
254 sd_mwrite_word(w, pilot->pref_back);
255
256 sd_mwrite_udword(w, pilot->unknown_e);
257 sd_mwrite_float(w, pilot->learning);
258 sd_mwrite_float(w, pilot->forget);
259 sd_mwrite_buf(w, pilot->unk_block_f, 14);
260 sd_mwrite_uword(w, pilot->enemies_inc_unranked);
261 sd_mwrite_uword(w, pilot->enemies_ex_unranked);
262 sd_mwrite_uword(w, pilot->unk_d_a);
263 sd_mwrite_udword(w, pilot->unk_d_b);
264 sd_mwrite_udword(w, pilot->winnings);
265 sd_mwrite_udword(w, pilot->total_value);
266 sd_mwrite_float(w, pilot->unk_f_a);
267 sd_mwrite_float(w, pilot->unk_f_b);
268 sd_mwrite_fill(w, 0, 8);
269 sd_palette_msave_range(w, &pilot->palette, 0, 48);
270 sd_mwrite_uword(w, pilot->unk_block_i);
271
272 sd_mwrite_uword(w, pilot->photo_id & 0x3FF);
273 }
274
sd_pilot_save(sd_writer * fw,const sd_pilot * pilot)275 int sd_pilot_save(sd_writer *fw, const sd_pilot *pilot) {
276 if(fw == NULL || pilot == NULL) {
277 return SD_INVALID_INPUT;
278 }
279
280 // Copy, XOR, save and close
281 sd_mwriter *w = sd_mwriter_open();
282 sd_pilot_save_to_mem(w, pilot);
283 sd_mwriter_xor(w, PILOT_BLOCK_LENGTH & 0xFF);
284 sd_mwriter_save(w, fw);
285 sd_mwriter_close(w);
286
287 // Quote block
288 for(int m = 0; m < 10; m++) {
289 sd_write_variable_str(fw, pilot->quotes[m]);
290 }
291 return SD_SUCCESS;
292 }