FS2_Open
Open source remastering of the Freespace 2 engine
csg_convert.cpp
Go to the documentation of this file.
1 
2 /* WARNING:
3  * This is magic-number central, but these numbers are set specifically
4  * to the acceptable defaults or range values that were used when the
5  * pl2/plr files were created. Standard game defines should not be used in
6  * place of these major numbers for /any/ reason, *ever*!
7  */
8 
9 #include "cfile/cfilesystem.h"
10 #include "cutscene/cutscenes.h"
11 #include "menuui/techmenu.h"
13 #include "ship/ship.h"
14 #include "stats/medals.h"
15 #include "weapon/weapon.h"
16 
17 #include <iostream>
18 #include <sstream>
19 
20 // copy of old scoring struct * NORMAL PILOTS *
21 typedef struct scoring_conv_t {
22  int flags;
23 
24  int score;
25  int rank;
26  int medals[18];
27 
28  int kills[130];
29  int assists;
32  unsigned int p_shots_fired;
33  unsigned int s_shots_fired;
34 
35  unsigned int p_shots_hit;
36  unsigned int s_shots_hit;
37 
38  unsigned int p_bonehead_hits;
39  unsigned int s_bonehead_hits;
41 
42  unsigned int missions_flown;
43  unsigned int flight_time;
46 
47  // Mission total
51 
52  int m_score;
53  int m_kills[130];
54  int m_okKills[130];
57  int m_assists;
58  unsigned int mp_shots_fired;
59  unsigned int ms_shots_fired;
60  unsigned int mp_shots_hit;
61  unsigned int ms_shots_hit;
62  unsigned int mp_bonehead_hits;
63  unsigned int ms_bonehead_hits;
66 
69 
70 static const size_t SCORING_SIZE = 1808;
71 
72 // copy of old scoring struct * INFERNO PILOTS *
73 typedef struct scoring_conv_INF_t {
74  int flags;
75 
76  int score;
77  int rank;
78  int medals[18];
79 
80  int kills[250];
81  int assists;
84  unsigned int p_shots_fired;
85  unsigned int s_shots_fired;
86 
87  unsigned int p_shots_hit;
88  unsigned int s_shots_hit;
89 
90  unsigned int p_bonehead_hits;
91  unsigned int s_bonehead_hits;
93 
94  unsigned int missions_flown;
95  unsigned int flight_time;
98 
99  // Mission total
103 
104  int m_score;
105  int m_kills[250];
106  int m_okKills[250];
110  unsigned int mp_shots_fired;
111  unsigned int ms_shots_fired;
112  unsigned int mp_shots_hit;
113  unsigned int ms_shots_hit;
114  unsigned int mp_bonehead_hits;
115  unsigned int ms_bonehead_hits;
118 
121 
122 static const size_t SCORING_INF_SIZE = 3248;
123 
124 
126 {
127  sig = 0;
128  cutscenes = 0;
129 
130  main_hall = "";
131  prev_mission = -1;
132  next_mission = -1;
133  loop_reentry = 0;
134  loop_enabled = 0;
135  num_completed = 0;
136 
138 }
139 
141 {
142 
143 }
144 
145 void pilotfile_convert::csg_import_ships_weapons()
146 {
147  index_list_t ilist;
148  char name[35];
149  int idx;
150  int list_size = 0;
151 
152  int ship_count = cfread_int(cfp);
153  int weap_count = cfread_int(cfp);
154 
155  for (idx = 0; idx < ship_count; idx++) {
156  ubyte allowed = cfread_ubyte(cfp);
157  csg->ships_allowed.push_back( (allowed != 0) );
158 
159  cfread_string_len(name, sizeof(name), cfp);
160 
161  ilist.name = name;
162  ilist.index = ship_info_lookup(name);
163 
164  if (ilist.index < 0) {
165  std::ostringstream error_msg;
166  error_msg << "Data mismatch (ship lookup: " << ilist.name << ")!";
167  throw std::runtime_error(error_msg.str().c_str());
168  }
169 
170  csg->ship_list.push_back( ilist );
171  }
172 
173  for (idx = 0; idx < weap_count; idx++) {
174  ubyte allowed = cfread_ubyte(cfp);
175  csg->weapons_allowed.push_back( allowed != 0 );
176 
177  cfread_string_len(name, sizeof(name), cfp);
178 
179  ilist.name = name;
180  ilist.index = weapon_info_lookup(name);
181 
182  if (ilist.index < 0) {
183  std::ostringstream error_msg;
184  error_msg << "Data mismatch (weapon lookup: " << ilist.name << ")!";
185  throw std::runtime_error(error_msg.str().c_str());
186  }
187 
188  csg->weapon_list.push_back( ilist );
189  }
190 
191  // get last ship flown index
192  for (idx = 0; idx < ship_count; idx++) {
193  if ( csg->ship_list[idx].name.compare(plr->last_ship_flown) == 0 ) {
194  csg->last_ship_flown_index = idx;
195  break;
196  }
197  }
198 
199  if (csg->last_ship_flown_index < 0) {
200  std::ostringstream error_msg;
201  error_msg << "Data mismatch (player ship: " << csg->last_ship_flown_index << ")!";
202  throw std::runtime_error(error_msg.str().c_str());
203  }
204 
205  // create list of medals (since it's missing from the old files)
206  list_size = Num_medals;
207 
208  for (idx = 0; idx < list_size; idx++) {
209  ilist.name = Medals[idx].name;
210  ilist.index = idx;
211 
212  csg->medals_list.push_back( ilist );
213  }
214 
215  // stuff intel list as well (present but burried in old files)
216  list_size = Intel_info_size;
217 
218  for (idx = 0; idx < list_size; idx++) {
219  ilist.name = Intel_info[idx].name;
220  ilist.index = idx;
221 
222  csg->intel_list.push_back( ilist );
223  }
224 }
225 
226 void pilotfile_convert::csg_import_missions(bool inferno)
227 {
228  cmission_conv_t miss;
229  int idx, j;
230  int count;
231  int list_size = 0, k;
232  scoring_conv_t t_score;
233  scoring_conv_INF_t t_inf_score;
234 
235  Assert( sizeof(scoring_conv_t) == SCORING_SIZE );
236  Assert( sizeof(scoring_conv_INF_t) == SCORING_INF_SIZE );
237 
238  int ship_list_size = (int)csg->ship_list.size();
239 
240  int num_missions = cfread_int(cfp);
241 
242  csg->missions.reserve(num_missions);
243 
244  for (idx = 0; idx < num_missions; idx++) {
245  miss.index = cfread_int(cfp);
246 
247  // goals
248  count = cfread_int(cfp);
249 
250  if (count > 0) {
251  mgoal n_goal;
252 
253  miss.goals.reserve(count);
254 
255  for (j = 0; j < count; j++) {
256  memset(&n_goal, 0, sizeof(mgoal));
257 
258  cfread_string_len(n_goal.name, sizeof(n_goal.name), cfp);
259  n_goal.status = cfread_char(cfp);
260 
261  miss.goals.push_back( n_goal );
262  }
263  }
264 
265  // events
266  count = cfread_int(cfp);
267 
268  if (count > 0) {
269  mevent n_event;
270 
271  miss.events.reserve(count);
272 
273  for (j = 0; j < count; j++) {
274  memset(&n_event, 0, sizeof(mevent));
275 
276  cfread_string_len(n_event.name, sizeof(n_event.name), cfp);
277  n_event.status = cfread_char(cfp);
278 
279  miss.events.push_back( n_event );
280  }
281  }
282 
283  // variables
284  count = cfread_int(cfp);
285 
286  if (count > 0) {
287  sexp_variable n_variable;
288 
289  miss.variables.reserve(count);
290 
291  for (j = 0; j < count; j++) {
292  memset(&n_variable, 0, sizeof(sexp_variable));
293 
294  n_variable.type = cfread_int(cfp);
295  cfread_string_len(n_variable.text, sizeof(n_variable.text), cfp);
296  cfread_string_len(n_variable.variable_name, sizeof(n_variable.variable_name), cfp);
297 
298  miss.variables.push_back( n_variable );
299  }
300  }
301 
302  // stats
303  miss.stats.ship_kills = csg->ship_list;
304  miss.stats.medals_earned = csg->medals_list;
305 
306  if (inferno) {
307  cfread(&t_inf_score, sizeof(scoring_conv_INF_t), 1, cfp);
308 
309  for (j = 0; j < ship_list_size; j++) {
310  miss.stats.ship_kills[j].val = INTEL_INT(t_inf_score.kills[j]);
311  }
312 
313  miss.stats.score = INTEL_INT(t_inf_score.score);
314  miss.stats.rank = INTEL_INT(t_inf_score.rank);
315  miss.stats.assists = INTEL_INT(t_inf_score.assists);
316  miss.stats.kill_count = INTEL_INT(t_inf_score.kill_count);
317  miss.stats.kill_count_ok = INTEL_INT(t_inf_score.kill_count_ok);
318  miss.stats.p_shots_fired = INTEL_INT(t_inf_score.p_shots_fired);
319  miss.stats.s_shots_fired = INTEL_INT(t_inf_score.s_shots_fired);
320  miss.stats.p_shots_hit = INTEL_INT(t_inf_score.p_shots_hit);
321  miss.stats.s_shots_hit = INTEL_INT(t_inf_score.s_shots_hit);
322  miss.stats.p_bonehead_hits = INTEL_INT(t_inf_score.p_bonehead_hits);
323  miss.stats.s_bonehead_hits = INTEL_INT(t_inf_score.s_bonehead_hits);
324  miss.stats.bonehead_kills = INTEL_INT(t_inf_score.bonehead_kills);
325 
326  for (j = 0; j < 18; j++) {
327  miss.stats.medals_earned[j].val = INTEL_INT(t_inf_score.medals[j]);
328  }
329  } else {
330  cfread(&t_score, sizeof(scoring_conv_t), 1, cfp);
331 
332  for (j = 0; j < ship_list_size; j++) {
333  miss.stats.ship_kills[j].val = INTEL_INT(t_score.kills[j]);
334  }
335 
336  miss.stats.score = INTEL_INT(t_score.score);
337  miss.stats.rank = INTEL_INT(t_score.rank);
338  miss.stats.assists = INTEL_INT(t_score.assists);
339  miss.stats.kill_count = INTEL_INT(t_score.kill_count);
340  miss.stats.kill_count_ok = INTEL_INT(t_score.kill_count_ok);
341  miss.stats.p_shots_fired = INTEL_INT(t_score.p_shots_fired);
342  miss.stats.s_shots_fired = INTEL_INT(t_score.s_shots_fired);
343  miss.stats.p_shots_hit = INTEL_INT(t_score.p_shots_hit);
344  miss.stats.s_shots_hit = INTEL_INT(t_score.s_shots_hit);
348 
349  for (j = 0; j < 18; j++) {
350  miss.stats.medals_earned[j].val = INTEL_INT(t_score.medals[j]);
351  }
352  }
353 
354  // flags
355  miss.flags = cfread_int(cfp);
356 
357 
358  // now add to list
359  csg->missions.push_back( miss );
360  }
361 
362  // finally, convert old mission variables to proper campaign variables
363  for (idx = 0; idx < num_missions; idx++) {
364  count = (int)csg->missions[idx].variables.size();
365 
366  for (j = 0; j < count; j++) {
367  bool add_it = true;
368 
369  list_size = (int)csg->variables.size();
370 
371  for (k = 0; k < list_size; k++) {
372  if ( !stricmp(csg->variables[k].variable_name, csg->missions[idx].variables[j].variable_name) ) {
373  csg->variables[k] = csg->missions[idx].variables[j];
374  add_it = false;
375  break;
376  }
377  }
378 
379  if (add_it) {
380  csg->variables.push_back( csg->missions[idx].variables[j] );
381  }
382  }
383  }
384 }
385 
386 void pilotfile_convert::csg_import_red_alert()
387 {
388  int idx, i, j;
389  int count;
390  char t_string[35] = { '\0' };
391  float val;
392  wep_t weapons;
393 
394  count = cfread_int(cfp);
395 
396  if (count <= 0) {
397  return;
398  }
399 
400  csg->wingman_status.reserve( count );
401 
402  cfread_string(t_string, sizeof(t_string)-1, cfp);
403  csg->precursor_mission = t_string;
404 
405  int ship_list_size = (int)csg->ship_list.size();
406  int weapon_list_size = (int)csg->weapon_list.size();
407 
408  for (idx = 0; idx < count; idx++) {
409  red_alert_ship_status ras;
410 
411  // ship name
412  cfread_string(t_string, sizeof(t_string)-1, cfp);
413  ras.name = t_string;
414 
415  ras.hull = cfread_float(cfp);
416  ras.ship_class = cfread_int(cfp);
417 
418  if (ras.ship_class >= ship_list_size) {
419  throw std::runtime_error("Data failure (RedAlert-ship)!");
420  }
421 
422  // system status
423  ras.subsys_current_hits.reserve(64);
424 
425  for (j = 0; j < 64; j++) {
426  val = cfread_float(cfp);
427  ras.subsys_current_hits.push_back( val );
428  }
429 
430  ras.subsys_aggregate_current_hits.reserve(12);
431 
432  for (j = 0; j < 12; j++) {
433  val = cfread_float(cfp);
434  ras.subsys_aggregate_current_hits.push_back( val );
435  }
436 
437  // loadout
438  ras.primary_weapons.reserve(3);
439 
440  for (j = 0; j < 3; j++) {
441  i = cfread_int(cfp);
442 
443  if (i >= weapon_list_size || i < -1) {
444  throw std::runtime_error("Data check failure (RedAlert-weapon)!");
445  } else if (i >= 0) {
446  weapons.index = csg->weapon_list[i].index;
447  } else {
448  weapons.index = -1;
449  }
450 
451  weapons.count = cfread_int(cfp);
452 
453  if (weapons.index >= 0) {
454  ras.primary_weapons.push_back( weapons );
455  }
456  }
457 
458  ras.secondary_weapons.reserve(4);
459 
460  for (j = 0; j < 4; j++) {
461  i = cfread_int(cfp);
462 
463  if (i >= weapon_list_size || i < -1) {
464  throw std::runtime_error("Data check failure (RedAlert-weapon)!");
465  } else if (i >= 0) {
466  weapons.index = csg->weapon_list[i].index;
467  } else {
468  weapons.index = -1;
469  }
470 
471  weapons.count = cfread_int(cfp);
472 
473  if (weapons.index >= 0) {
474  ras.secondary_weapons.push_back( weapons );
475  }
476  }
477 
478  // add to list
479  csg->wingman_status.push_back( ras );
480  }
481 }
482 
483 void pilotfile_convert::csg_import_techroom()
484 {
485  int idx, list_size = 0;
486  bool visible;
487  unsigned char in = 0;
488 
489  // intel entry count
490  int intel_count = cfread_int(cfp);
491 
492  csg->ships_techroom.reserve( csg->ship_list.size() );
493  csg->weapons_techroom.reserve( csg->weapon_list.size() );
494  csg->intel_techroom.reserve( intel_count );
495 
496  // ships
497  list_size = (int)csg->ship_list.size();
498 
499  for (idx = 0; idx < list_size; idx++) {
500  in = cfread_ubyte(cfp);
501 
502  if (in > 1) {
503  throw std::runtime_error("Data check failure (techroom-ship)!");
504  }
505 
506  visible = (in == 1) ? true : false;
507 
508  csg->ships_techroom.push_back( visible );
509  }
510 
511  // weapons
512  list_size = (int)csg->weapon_list.size();
513 
514  for (idx = 0; idx < list_size; idx++) {
515  in = cfread_ubyte(cfp);
516 
517  if (in > 1) {
518  throw std::runtime_error("Data check failure (techroom-weapon)!");
519  }
520 
521  visible = (in == 1) ? true : false;
522 
523  csg->weapons_techroom.push_back( visible );
524  }
525 
526  // intel
527  list_size = intel_count;
528 
529  for (idx = 0; idx < list_size; idx++) {
530  in = cfread_ubyte(cfp);
531 
532  if (in > 1) {
533  throw std::runtime_error("Data check failure (techroom-intel)!");
534  }
535 
536  visible = (in == 1) ? true : false;
537 
538  csg->intel_techroom.push_back( visible );
539  }
540 }
541 
542 void pilotfile_convert::csg_import_loadout()
543 {
544  int idx, j;
545  int list_size = 0, count;
546  char t_string[50] = { '\0' };
547 
548  // mission name/status
549  cfread_string_len(t_string, sizeof(t_string), cfp);
550  csg->loadout.filename = t_string;
551 
552  cfread_string_len(t_string, sizeof(t_string), cfp);
553  csg->loadout.last_modified = t_string;
554 
555  // ship pool
556  list_size = csg->ship_list.size();
557  csg->loadout.ship_pool.reserve(list_size);
558 
559  for (idx = 0; idx < list_size; idx++) {
560  count = cfread_int(cfp);
561  csg->loadout.ship_pool.push_back( count );
562  }
563 
564  // weapon pool
565  list_size = csg->weapon_list.size();
566  csg->loadout.weapon_pool.reserve(list_size);
567 
568  for (idx = 0; idx < list_size; idx++) {
569  count = cfread_int(cfp);
570  csg->loadout.weapon_pool.push_back( count );
571  }
572 
573  // loadout info
574  for (idx = 0; idx < MAX_WSS_SLOTS_CONV; idx++) {
575  csg->loadout.slot[idx].ship_index = cfread_int(cfp);
576 
577  for (j = 0; j < MAX_SHIP_WEAPONS_CONV; j++) {
578  csg->loadout.slot[idx].wep[j] = cfread_int(cfp);
579  csg->loadout.slot[idx].wep_count[j] = cfread_int(cfp);
580  }
581  }
582 }
583 
584 void pilotfile_convert::csg_import_stats()
585 {
586  int list_size = 0;
587  int idx;
588 
589  csg->stats.score = cfread_int(cfp);
590  csg->stats.rank = cfread_int(cfp);
591  csg->stats.assists = cfread_int(cfp);
592 
593  csg->stats.medals_earned = csg->medals_list;
594 
595  list_size = (int)csg->stats.medals_earned.size();
596 
597  for (idx = 0; idx < list_size; idx++) {
598  csg->stats.medals_earned[idx].val = cfread_int(cfp);
599  }
600 
601  csg->stats.ship_kills = csg->ship_list;
602 
603  list_size = cfread_int(cfp);
604 
605  // NOTE: could be less, but never greater than
606  if ( list_size > (int)csg->stats.ship_kills.size() ) {
607  throw std::runtime_error("Data check failure (kills size)!");
608  }
609 
610  for (idx = 0; idx < list_size; idx++) {
611  csg->stats.ship_kills[idx].val = (int)cfread_ushort(cfp);
612  }
613 
614  csg->stats.kill_count = cfread_int(cfp);
615  csg->stats.kill_count_ok = cfread_int(cfp);
616 
617  csg->stats.p_shots_fired = cfread_uint(cfp);
618  csg->stats.s_shots_fired = cfread_uint(cfp);
619  csg->stats.p_shots_hit = cfread_uint(cfp);
620  csg->stats.s_shots_hit = cfread_uint(cfp);
621 
622  csg->stats.p_bonehead_hits = cfread_uint(cfp);
623  csg->stats.s_bonehead_hits = cfread_uint(cfp);
624  csg->stats.bonehead_kills = cfread_uint(cfp);
625 }
626 
627 void pilotfile_convert::csg_import(bool inferno)
628 {
629  Assert( cfp != NULL );
630 
631  char name[35];
632 
633  unsigned int csg_id = cfread_uint(cfp);
634 
635  if (csg_id != 0xbeefcafe) {
636  throw std::runtime_error("Invalid file signature!");
637  }
638 
639  fver = cfread_uint(cfp);
640 
641  if (fver != 15) {
642  throw std::runtime_error("Unsupported file version!");
643  }
644 
645  // campaign type (single/multi)
646  csg->sig = cfread_int(cfp);
647 
648  // trash
649  cfread_string_len(name, sizeof(name), cfp);
650 
651  csg->prev_mission = cfread_int(cfp);
652  csg->next_mission = cfread_int(cfp);
653  csg->loop_reentry = cfread_int(cfp);
654  csg->loop_enabled = cfread_int(cfp);
655 
656  csg_import_ships_weapons();
657 
658  csg_import_missions(inferno);
659 
660  csg->main_hall = cfread_ubyte(cfp);
661 
662  csg_import_red_alert();
663 
664  csg_import_techroom();
665 
666  csg_import_loadout();
667 
668  csg_import_stats();
669 
670  csg->cutscenes = cfread_int(cfp);
671 
672  // final data checks
673  if ( csg->ship_list.size() != csg->ships_allowed.size() ) {
674  throw std::runtime_error("Data check failure (ship size)!");
675  } else if ( csg->ship_list.size() != csg->ships_techroom.size() ) {
676  throw std::runtime_error("Data check failure (ship size)!");
677  } else if ( csg->weapon_list.size() != csg->weapons_allowed.size() ) {
678  throw std::runtime_error("Data check failure (weapon size)!");
679  } else if ( csg->weapon_list.size() != csg->weapons_techroom.size() ) {
680  throw std::runtime_error("Data check failure (weapon size)!");
681  } else if ( csg->intel_list.size() != csg->intel_techroom.size() ) {
682  throw std::runtime_error("Data check failure (intel size)!");
683  }
684 
685 
686  // and... we're done!
687 }
688 
689 void pilotfile_convert::csg_export_flags()
690 {
691  startSection(Section::Flags);
692 
693  // tips
694  cfwrite_ubyte((ubyte)plr->tips, cfp);
695 
696  // special rank
697  cfwrite_int(csg->stats.rank, cfp);
698 
699  endSection();
700 }
701 
702 void pilotfile_convert::csg_export_info()
703 {
704  int list_size = 0;
705  int idx;
706  ubyte visible;
707 
708  startSection(Section::Info);
709 
710  // ship list
711  list_size = (int)csg->ship_list.size();
712  cfwrite_int(list_size, cfp);
713 
714  for (idx = 0; idx < list_size; idx++) {
715  cfwrite_string_len(csg->ship_list[idx].name.c_str(), cfp);
716  }
717 
718  // weapon list
719  list_size = (int)csg->weapon_list.size();
720  cfwrite_int(list_size, cfp);
721 
722  for (idx = 0; idx < list_size; idx++) {
723  cfwrite_string_len(csg->weapon_list[idx].name.c_str(), cfp);
724  }
725 
726  // intel list
727  list_size = (int)csg->intel_list.size();
728  cfwrite_int(list_size, cfp);
729 
730  for (idx = 0; idx < list_size; idx++) {
731  cfwrite_string_len(csg->intel_list[idx].name.c_str(), cfp);
732  }
733 
734  // medals list
735  list_size = (int)csg->stats.medals_earned.size();
736  cfwrite_int(list_size, cfp);
737 
738  for (idx = 0; idx < list_size; idx++) {
739  cfwrite_string_len(csg->stats.medals_earned[idx].name.c_str(), cfp);
740  }
741 
742  // last ship flown
744 
745  // progression state
746  cfwrite_int(csg->prev_mission, cfp);
747  cfwrite_int(csg->next_mission, cfp);
748 
749  // loop state
750  cfwrite_int(csg->loop_enabled, cfp);
751  cfwrite_int(csg->loop_reentry, cfp);
752 
753  // missions completed
754  list_size = (int)csg->missions.size();
755  cfwrite_int(list_size, cfp);
756 
757  // allowed ships
758  list_size = (int)csg->ships_allowed.size();
759  for (idx = 0; idx < list_size; idx++) {
760  visible = csg->ships_allowed[idx] ? 1 : 0;
761  cfwrite_ubyte(visible, cfp);
762  }
763 
764  // allowed weapons
765  list_size = (int)csg->weapons_allowed.size();
766  for (idx = 0; idx < list_size; idx++) {
767  visible = csg->weapons_allowed[idx] ? 1 : 0;
768  cfwrite_ubyte(visible, cfp);
769  }
770 
771  // single/campaign squad name & image, make it the same as multi
772  cfwrite_string_len(plr->squad_name, cfp);
774 
775  endSection();
776 }
777 
778 void pilotfile_convert::csg_export_missions()
779 {
780  int idx, j;
781  int list_size = 0;
782  int count = 0;
783 
784  startSection(Section::Missions);
785 
786  list_size = csg->missions.size();
787 
788  for (idx = 0; idx < list_size; idx++) {
789  cfwrite_int(csg->missions[idx].index, cfp);
790 
791  // flags
792  cfwrite_int(csg->missions[idx].flags, cfp);
793 
794  // goals
795  count = (int)csg->missions[idx].goals.size();
796  cfwrite_int(count, cfp);
797 
798  for (j = 0; j < count; j++) {
799  cfwrite_string_len(csg->missions[idx].goals[j].name, cfp);
800  cfwrite_char(csg->missions[idx].goals[j].status, cfp);
801  }
802 
803  // events
804  count = (int)csg->missions[idx].events.size();
805  cfwrite_int(count, cfp);
806 
807  for (j = 0; j < count; j++) {
808  cfwrite_string_len(csg->missions[idx].events[j].name, cfp);
809  cfwrite_char(csg->missions[idx].events[j].status, cfp);
810  }
811 
812  // variables
813  count = (int)csg->missions[idx].variables.size();
814  cfwrite_int(count, cfp);
815 
816  for (j = 0; j < count; j++) {
817  cfwrite_int(csg->missions[idx].variables[j].type, cfp);
818  cfwrite_string_len(csg->missions[idx].variables[j].text, cfp);
819  cfwrite_string_len(csg->missions[idx].variables[j].variable_name, cfp);
820  }
821 
822  // scoring stats
823  cfwrite_int(csg->missions[idx].stats.score, cfp);
824  cfwrite_int(csg->missions[idx].stats.rank, cfp);
825  cfwrite_int(csg->missions[idx].stats.assists, cfp);
826  cfwrite_int(csg->missions[idx].stats.kill_count, cfp);
827  cfwrite_int(csg->missions[idx].stats.kill_count_ok, cfp);
828  cfwrite_int(csg->missions[idx].stats.bonehead_kills, cfp);
829 
830  cfwrite_uint(csg->missions[idx].stats.p_shots_fired, cfp);
831  cfwrite_uint(csg->missions[idx].stats.p_shots_hit, cfp);
832  cfwrite_uint(csg->missions[idx].stats.p_bonehead_hits, cfp);
833 
834  cfwrite_uint(csg->missions[idx].stats.s_shots_fired, cfp);
835  cfwrite_uint(csg->missions[idx].stats.s_shots_hit, cfp);
836  cfwrite_uint(csg->missions[idx].stats.s_bonehead_hits, cfp);
837 
838  // ship kills (scoring)
839  count = (int)csg->missions[idx].stats.ship_kills.size();
840 
841  for (j = 0; j < count; j++) {
842  cfwrite_int(csg->missions[idx].stats.ship_kills[j].val, cfp);
843  }
844 
845  // medals earned (scoring)
846  count = (int)csg->missions[idx].stats.medals_earned.size();
847 
848  for (j = 0; j < count; j++) {
849  cfwrite_int(csg->missions[idx].stats.medals_earned[j].val, cfp);
850  }
851  }
852 
853  endSection();
854 }
855 
856 void pilotfile_convert::csg_export_techroom()
857 {
858  int list_size = 0;
859  int idx;
860  ubyte visible;
861 
862  startSection(Section::Techroom);
863 
864  // visible ships
865  list_size = (int)csg->ships_techroom.size();
866 
867  for (idx = 0; idx < list_size; idx++) {
868  visible = csg->ships_techroom[idx] ? 1 : 0;
869  cfwrite_ubyte(visible, cfp);
870  }
871 
872  // visible weapons
873  list_size = (int)csg->weapons_techroom.size();
874 
875  for (idx = 0; idx < list_size; idx++) {
876  visible = csg->weapons_techroom[idx] ? 1 : 0;
877  cfwrite_ubyte(visible, cfp);
878  }
879 
880  // visible intel entries
881  list_size = (int)csg->intel_techroom.size();
882 
883  for (idx = 0; idx < list_size; idx++) {
884  visible = csg->intel_techroom[idx] ? 1 : 0;
885  cfwrite_ubyte(visible, cfp);
886  }
887 
888  endSection();
889 }
890 
891 void pilotfile_convert::csg_export_loadout()
892 {
893  int idx, j;
894  int list_size = 0;
895 
896  startSection(Section::Loadout);
897 
898  // base info
899  cfwrite_string_len(csg->loadout.filename.c_str(), cfp);
900  cfwrite_string_len(csg->loadout.last_modified.c_str(), cfp);
901 
902  // ship pool
903  list_size = csg->loadout.ship_pool.size();
904 
905  for (idx = 0; idx < list_size; idx++) {
906  cfwrite_int(csg->loadout.ship_pool[idx], cfp);
907  }
908 
909  // weapon pool
910  list_size = csg->loadout.weapon_pool.size();
911 
912  for (idx = 0; idx < list_size; idx++) {
913  cfwrite_int(csg->loadout.weapon_pool[idx], cfp);
914  }
915 
916  // play ship loadout
917  cfwrite_ushort(12, cfp);
918 
919  for (idx = 0; idx < 12; idx++) {
920  // ship
921  cfwrite_int(csg->loadout.slot[idx].ship_index, cfp);
922 
923  // primary weapons
924  cfwrite_int(3, cfp);
925 
926  for (j = 0; j < 3; j++) {
927  cfwrite_int(csg->loadout.slot[idx].wep[j], cfp);
928  cfwrite_int(csg->loadout.slot[idx].wep_count[j], cfp);
929  }
930 
931  // secondary weapons
932  cfwrite_int(4, cfp);
933 
934  for (j = 0; j < 4; j++) {
935  cfwrite_int(csg->loadout.slot[idx].wep[j+3], cfp);
936  cfwrite_int(csg->loadout.slot[idx].wep_count[j+3], cfp);
937  }
938  }
939 
940  endSection();
941 }
942 
943 void pilotfile_convert::csg_export_stats()
944 {
945  int idx;
946  int list_size = 0;
947 
948  startSection(Section::Scoring);
949 
950  // scoring stats
951  cfwrite_int(csg->stats.score, cfp);
952  cfwrite_int(csg->stats.rank, cfp);
953  cfwrite_int(csg->stats.assists, cfp);
954  cfwrite_int(csg->stats.kill_count, cfp);
955  cfwrite_int(csg->stats.kill_count_ok, cfp);
956  cfwrite_int(csg->stats.bonehead_kills, cfp);
957 
958  cfwrite_uint(csg->stats.p_shots_fired, cfp);
959  cfwrite_uint(csg->stats.p_shots_hit, cfp);
961 
962  cfwrite_uint(csg->stats.s_shots_fired, cfp);
963  cfwrite_uint(csg->stats.s_shots_hit, cfp);
965 
966  cfwrite_uint(csg->stats.flight_time, cfp);
967  cfwrite_uint(csg->stats.missions_flown, cfp);
968  cfwrite_int((int)csg->stats.last_flown, cfp);
969  cfwrite_int((int)csg->stats.last_backup, cfp);
970 
971  // ship kills (scoring)
972  list_size = csg->stats.ship_kills.size();
973  for (idx = 0; idx < list_size; idx++) {
974  cfwrite_int(csg->stats.ship_kills[idx].val, cfp);
975  }
976 
977  // medals earned (scoring)
978  list_size = csg->stats.medals_earned.size();
979  for (idx = 0; idx < list_size; idx++) {
980  cfwrite_int(csg->stats.medals_earned[idx].val, cfp);
981  }
982 
983  endSection();
984 }
985 
986 void pilotfile_convert::csg_export_redalert()
987 {
988  int idx, j, list_size = 0;
989  int count;
990  red_alert_ship_status *ras;
991 
992  startSection(Section::RedAlert);
993 
994  list_size = (int)csg->wingman_status.size();
995 
996  cfwrite_int(list_size, cfp);
997 
998  if (list_size) {
999  cfwrite_string_len(csg->precursor_mission.c_str(), cfp);
1000 
1001  for (idx = 0; idx < list_size; idx++) {
1002  ras = &csg->wingman_status[idx];
1003 
1004  cfwrite_string_len(ras->name.c_str(), cfp);
1005 
1006  cfwrite_float(ras->hull, cfp);
1007 
1008  // ship class, should be index into ship_list[] on load
1009  cfwrite_int(ras->ship_class, cfp);
1010 
1011  // subsystem hits
1012  count = (int)ras->subsys_current_hits.size();
1013  cfwrite_int(count, cfp);
1014 
1015  for (j = 0; j < count; j++) {
1016  cfwrite_float(ras->subsys_current_hits[j], cfp);
1017  }
1018 
1019  // subsystem aggregate hits
1020  count = (int)ras->subsys_aggregate_current_hits.size();
1021  cfwrite_int(count, cfp);
1022 
1023  for (j = 0; j < count; j++) {
1024  cfwrite_float(ras->subsys_aggregate_current_hits[j], cfp);
1025  }
1026 
1027  // primary weapon loadout and status
1028  count = (int)ras->primary_weapons.size();
1029  cfwrite_int(count, cfp);
1030 
1031  for (j = 0; j < count; j++) {
1032  cfwrite_int(ras->primary_weapons[j].index, cfp);
1033  cfwrite_int(ras->primary_weapons[j].count, cfp);
1034  }
1035 
1036  // secondary weapon loadout and status
1037  count = (int)ras->secondary_weapons.size();
1038  cfwrite_int(count, cfp);
1039 
1040  for (j = 0; j < count; j++) {
1041  cfwrite_int(ras->secondary_weapons[j].index, cfp);
1042  cfwrite_int(ras->secondary_weapons[j].count, cfp);
1043  }
1044  }
1045  }
1046 
1047  endSection();
1048 }
1049 
1050 void pilotfile_convert::csg_export_hud()
1051 {
1052  int idx;
1053 
1054  startSection(Section::HUD);
1055 
1056  // flags
1057  cfwrite_int(plr->hud_show_flags, cfp);
1058  cfwrite_int(plr->hud_show_flags2, cfp);
1059 
1060  cfwrite_int(plr->hud_popup_flags, cfp);
1061  cfwrite_int(plr->hud_popup_flags2, cfp);
1062 
1063  // settings
1064  cfwrite_ubyte(plr->hud_num_lines, cfp);
1065 
1066  cfwrite_int(plr->hud_rp_flags, cfp);
1067  cfwrite_int(plr->hud_rp_dist, cfp);
1068 
1069  // basic colors
1070  cfwrite_int(0, cfp); // color
1071  cfwrite_int(8, cfp); // alpha
1072 
1073  // gauge-specific colors
1074  cfwrite_int(39, cfp);
1075 
1076  for (idx = 0; idx < 39; idx++) {
1077  cfwrite_ubyte(plr->hud_colors[idx][0], cfp);
1078  cfwrite_ubyte(plr->hud_colors[idx][1], cfp);
1079  cfwrite_ubyte(plr->hud_colors[idx][2], cfp);
1080  cfwrite_ubyte(plr->hud_colors[idx][3], cfp);
1081  }
1082 
1083  endSection();
1084 }
1085 
1086 void pilotfile_convert::csg_export_variables()
1087 {
1088  int list_size = 0;
1089  int idx;
1090 
1091  startSection(Section::Variables);
1092 
1093  list_size = (int)csg->variables.size();
1094 
1095  cfwrite_int(list_size, cfp);
1096 
1097  for (idx = 0; idx < list_size; idx++) {
1098  cfwrite_int(csg->variables[idx].type, cfp);
1099  cfwrite_string_len(csg->variables[idx].text, cfp);
1100  cfwrite_string_len(csg->variables[idx].variable_name, cfp);
1101  }
1102 
1103  endSection();
1104 }
1105 
1106 void pilotfile_convert::csg_export_cutscenes() {
1108 
1109  startSection(Section::Cutscenes);
1110 
1111  // convert the old int bitfield to the new vector
1112  // the 32 is the size-in-bits of the old int on all platforms
1113  // supported by FSO prior to 3.7.0
1114  size_t size = Cutscenes.size();
1115  size_t viewableScenes = 0;
1116  for (size_t j=0; j<size && j<32; ++j) {
1117  if ( csg->cutscenes & (1<<j) ) {
1118  Cutscenes.at(j).viewable = true;
1119  viewableScenes++;
1120  }
1121  }
1122 
1123  // output cutscene data in new format
1124  cfwrite_uint(viewableScenes, cfp);
1125 
1126  for(cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) {
1127  if(cut->viewable)
1128  cfwrite_string_len(cut->filename, cfp);
1129  }
1130 
1131  endSection();
1132 }
1133 
1134 void pilotfile_convert::csg_export()
1135 {
1136  Assert( cfp != NULL );
1137 
1138  // header and version
1139  cfwrite_int(CSG_FILE_ID, cfp);
1140  cfwrite_ubyte(CSG_VERSION, cfp);
1141 
1142  // flags and info sections go first
1143  csg_export_flags();
1144  csg_export_info();
1145 
1146  // everything else is next, not order specific
1147  csg_export_missions();
1148  csg_export_techroom();
1149  csg_export_loadout();
1150  csg_export_stats();
1151  csg_export_redalert();
1152  csg_export_hud();
1153  csg_export_variables();
1154  csg_export_cutscenes();
1155 
1156  // and... we're done! :)
1157 }
1158 
1159 bool pilotfile_convert::csg_convert(const char *fname, bool inferno)
1160 {
1161  Assert( fname != NULL );
1162  Assert( plr != NULL);
1163  Assert( csg == NULL );
1164 
1166  bool rval = true;
1167 
1168  csg = new(std::nothrow) csg_data;
1169 
1170  if (csg == NULL) {
1171  return false;
1172  }
1173 
1174  filename.reserve(200);
1175 
1176  cf_create_default_path_string(filename, CF_TYPE_SINGLE_PLAYERS, (inferno) ? "inferno" : NULL);
1177 
1178  if (inferno) {
1179  filename.append(DIR_SEPARATOR_STR);
1180  }
1181 
1182  filename.append(fname);
1183  filename.append(".cs2");
1184 
1185  mprintf((" CS2 => Converting '%s'...\n", filename.c_str()));
1186 
1187  cfp = cfopen(filename.c_str(), "rb", CFILE_NORMAL);
1188 
1189  if ( !cfp ) {
1190  mprintf((" CS2 => Unable to open '%s' for import!\n", fname));
1191  delete csg;
1192  csg = NULL;
1193 
1194  return false;
1195  }
1196 
1197  try {
1198  csg_import(inferno);
1199  } catch (const std::exception& err) {
1200  mprintf((" CS2 => Import ERROR: %s\n", err.what()));
1201  rval = false;
1202  }
1203 
1204  cfclose(cfp);
1205  cfp = NULL;
1206 
1207  if ( !rval ) {
1208  delete csg;
1209  csg = NULL;
1210 
1211  return false;
1212  }
1213 
1214  filename.assign(fname);
1215  filename.append(".csg");
1216 
1217  cfp = cfopen(filename.c_str(), "wb", CFILE_NORMAL, CF_TYPE_PLAYERS);
1218 
1219  if ( !cfp ) {
1220  mprintf((" CSG => Unable to open '%s' for export!\n", fname));
1221  return false;
1222  }
1223 
1224  try {
1225  csg_export();
1226  } catch (const char *err) {
1227  mprintf((" CSG => Export ERROR: %s\n", err));
1228  rval = false;
1229  }
1230 
1231  cfclose(cfp);
1232  cfp = NULL;
1233 
1234  delete csg;
1235  csg = NULL;
1236 
1237  if (rval) {
1238  mprintf((" CSG => Conversion complete!\n"));
1239  }
1240 
1241  return rval;
1242 }
unsigned int s_bonehead_hits
Definition: csg_convert.cpp:39
SCP_vector< mevent > events
unsigned int s_shots_fired
Definition: csg_convert.cpp:33
int cfwrite_ushort(ushort s, CFILE *file)
Definition: cfile.cpp:1328
int ship_info_lookup(const char *token)
Definition: ship.cpp:12772
#define CFILE_NORMAL
Definition: cfile.h:89
int i
Definition: multi_pxo.cpp:466
SCP_vector< medal_stuff > Medals
Definition: medals.cpp:33
#define CF_TYPE_SINGLE_PLAYERS
Definition: cfile.h:70
unsigned int missions_flown
Definition: csg_convert.cpp:94
bool csg_convert(const char *fname, bool inferno)
SCP_vector< index_list_t > medals_earned
SCP_string name
SCP_vector< cutscene_info > Cutscenes
Definition: cutscenes.cpp:39
char squad_filename[35]
char text[TOKEN_LENGTH]
Definition: sexp.h:1044
unsigned int s_shots_hit
Definition: csg_convert.cpp:36
#define CF_TYPE_PLAYERS
Definition: cfile.h:67
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
int cfwrite_ubyte(ubyte b, CFILE *file)
Definition: cfile.cpp:1334
int index
Definition: pstypes.h:213
unsigned int flight_time
Definition: csg_convert.cpp:95
int cfwrite_uint(uint i, CFILE *file)
Definition: cfile.cpp:1316
SCP_string precursor_mission
int weapon_info_lookup(const char *name=NULL)
Definition: weapons.cpp:467
loadout_conv_t loadout
Assert(pm!=NULL)
SCP_vector< bool > weapons_allowed
unsigned int p_shots_hit
Definition: csg_convert.cpp:87
unsigned int p_shots_fired
Definition: csg_convert.cpp:84
#define mprintf(args)
Definition: pstypes.h:238
SCP_vector< sexp_variable > variables
int m_dogfight_kills[12]
Definition: csg_convert.cpp:67
long _fs_time_t
Definition: pstypes.h:55
void cfread_string(char *buf, int n, CFILE *file)
Definition: cfile.cpp:1278
SCP_vector< index_list_t > intel_list
SCP_vector< sexp_variable > variables
unsigned int mp_shots_hit
unsigned int flight_time
Definition: csg_convert.cpp:43
char name[NAME_LENGTH]
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize)
unsigned int p_shots_hit
GLsizeiptr size
Definition: Glext.h:5496
GLuint in
Definition: Glext.h:9087
unsigned char hud_colors[39][4]
unsigned int ms_shots_fired
unsigned int mp_bonehead_hits
Definition: csg_convert.cpp:62
unsigned int s_bonehead_hits
scoring_special_t stats
int cfwrite_char(char b, CFILE *file)
Definition: cfile.cpp:1361
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
unsigned int mp_shots_hit
Definition: csg_convert.cpp:60
SCP_vector< cmission_conv_t > missions
SCP_vector< index_list_t > weapon_list
char name[NAME_LENGTH]
Definition: techmenu.h:21
#define cfopen(...)
Definition: cfile.h:134
_fs_time_t last_flown
Definition: csg_convert.cpp:96
int cfwrite_float(float f, CFILE *file)
Definition: cfile.cpp:1304
#define DIR_SEPARATOR_STR
Definition: pstypes.h:44
char * filename
SCP_string main_hall
SCP_vector< index_list_t > ship_kills
_fs_time_t last_backup
Definition: csg_convert.cpp:97
int Intel_info_size
Definition: techmenu.cpp:247
SCP_vector< red_alert_ship_status > wingman_status
unsigned int p_bonehead_hits
Definition: csg_convert.cpp:38
unsigned int s_shots_fired
Definition: csg_convert.cpp:85
int cfwrite_string_len(const char *buf, CFILE *file)
Write a fixed length string (not including its null terminator), with the length stored in file...
Definition: cfile.cpp:1378
unsigned int p_shots_fired
unsigned int p_shots_fired
Definition: csg_convert.cpp:32
SCP_vector< int > weapon_pool
unsigned int missions_flown
Definition: csg_convert.cpp:42
int idx
Definition: multiui.cpp:761
SCP_vector< int > ship_pool
SCP_vector< index_list_t > medals_list
char name[NAME_LENGTH]
int cfwrite_int(int i, CFILE *file)
Definition: cfile.cpp:1310
_fs_time_t last_flown
Definition: csg_convert.cpp:44
unsigned int p_bonehead_hits
Definition: csg_convert.cpp:90
int type
Definition: sexp.h:1043
unsigned char ubyte
Definition: pstypes.h:62
unsigned int s_shots_fired
int last_ship_flown_index
struct scoring_conv_INF_t scoring_conv_INF_t
unsigned int s_shots_hit
unsigned int p_bonehead_hits
ubyte cfread_ubyte(CFILE *file, int ver, ubyte deflt)
Definition: cfile.cpp:1220
unsigned int ms_bonehead_hits
#define INTEL_INT(x)
Definition: pstypes.h:388
GLuint const GLchar * name
Definition: Glext.h:5608
GLuint GLfloat * val
Definition: Glext.h:6741
unsigned int s_bonehead_hits
Definition: csg_convert.cpp:91
intel_data Intel_info[MAX_INTEL_ENTRIES]
Definition: techmenu.cpp:246
char status
SCP_vector< bool > ships_techroom
char cfread_char(CFILE *file, int ver, char deflt)
Definition: cfile.cpp:1265
char last_ship_flown[35]
SCP_vector< bool > intel_techroom
unsigned int ms_bonehead_hits
Definition: csg_convert.cpp:63
unsigned int missions_flown
Definition: pstypes.h:212
int count
Definition: pstypes.h:214
ushort cfread_ushort(CFILE *file, int ver, ushort deflt)
Definition: cfile.cpp:1206
int m_kills[130]
Definition: csg_convert.cpp:53
SCP_vector< bool > weapons_techroom
unsigned int flight_time
int cfread_int(CFILE *file, int ver, int deflt)
Definition: cfile.cpp:1164
float cfread_float(CFILE *file, int ver, float deflt)
Definition: cfile.cpp:1150
GLint GLsizei count
Definition: Gl.h:1491
char status
scoring_special_t stats
char variable_name[TOKEN_LENGTH]
Definition: sexp.h:1045
char squad_name[35]
SCP_vector< bool > ships_allowed
int wep_count[MAX_SHIP_WEAPONS_CONV]
struct scoring_conv_t scoring_conv_t
SCP_string last_modified
unsigned int mp_shots_fired
Definition: csg_convert.cpp:58
unsigned int ms_shots_hit
_fs_time_t last_backup
Definition: csg_convert.cpp:45
unsigned int ms_shots_fired
Definition: csg_convert.cpp:59
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
unsigned int ms_shots_hit
Definition: csg_convert.cpp:61
SCP_vector< index_list_t > ship_list
int m_okKills[130]
Definition: csg_convert.cpp:54
wss_unit_conv_t slot[MAX_WSS_SLOTS_CONV]
int Num_medals
Definition: medals.cpp:30
unsigned char hud_num_lines
unsigned int mp_shots_fired
int kills[130]
Definition: csg_convert.cpp:28
#define stricmp(s1, s2)
Definition: config.h:271
unsigned int mp_bonehead_hits
unsigned int s_shots_hit
Definition: csg_convert.cpp:88
SCP_vector< mgoal > goals
unsigned int p_shots_hit
Definition: csg_convert.cpp:35
uint cfread_uint(CFILE *file, int ver, uint deflt)
Definition: cfile.cpp:1178
void cfread_string_len(char *buf, int n, CFILE *file)
Read a fixed length string that is not null-terminated, with the length stored in file...
Definition: cfile.cpp:1291
int wep[MAX_SHIP_WEAPONS_CONV]