1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6
7 #include "../include/cfgfmt.h"
8 #include "../include/string.h"
9 #include "../include/strexp.h"
10 #include "../include/fio.h"
11 #include "../include/disk.h"
12
13 #include "obj.h"
14 #include "mission.h"
15 #include "sartime.h"
16 #include "sarfio.h"
17 #include "config.h"
18
19 static int SARParmSaveToFileAnyIterate(
20 const char *filename, FILE *fp, const void *p
21 );
22 static int SARParmSaveToFileAny(
23 const char *filename, FILE *fp,
24 void **parm, int total_parms,
25 void *client_data,
26 int (*progress_func)(void *, long, long)
27 );
28 int SARParmSaveToFile(
29 const char *filename, int file_format,
30 void **parm, int total_parms,
31 void *client_data,
32 int (*progress_func)(void *, long, long)
33 );
34
35
36 #ifndef SAR_COMMENT_CHAR
37 # define SAR_COMMENT_CHAR '#'
38 #endif
39
40 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
41 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
42 #define ATOF(s) (((s) != NULL) ? atof(s) : 0.0f)
43 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
44
45 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
46 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
47 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
48
49 #define ISCOMMENT(c) ((c) == SAR_COMMENT_CHAR)
50 #define ISCR(c) (((c) == '\n') || ((c) == '\r'))
51
52 #define DEGTORAD(d) ((d) * PI / 180)
53 #define RADTODEG(r) ((r) * 180 / PI)
54
55
56 /*
57 * Saves the given parameter to file.
58 *
59 * Returns the number of parameters saved.
60 */
SARParmSaveToFileAnyIterate(const char * filename,FILE * fp,const void * p)61 static int SARParmSaveToFileAnyIterate(
62 const char *filename, FILE *fp, const void *p
63 )
64 {
65 int parms_saved = 0;
66 int type = *(int *)p;
67
68 /* Version. */
69 if(type == SAR_PARM_VERSION)
70 {
71 #define PARM_TYPE const sar_parm_version_struct
72 PARM_TYPE *pv = (PARM_TYPE *)p;
73 fprintf(
74 fp,
75 "version %i %i %i%s%s\n",
76 pv->major, pv->minor, pv->release,
77 (pv->copyright != NULL) ? " " : "",
78 (pv->copyright != NULL) ? pv->copyright : ""
79 );
80 parms_saved++;
81 #undef PARM_TYPE
82 }
83 /* Name. */
84 else if(type == SAR_PARM_NAME)
85 {
86 #define PARM_TYPE const sar_parm_name_struct
87 PARM_TYPE *pv = (PARM_TYPE *)p;
88 if(pv->name != NULL)
89 {
90 fprintf(
91 fp,
92 "name %s\n",
93 pv->name
94 );
95 parms_saved++;
96 }
97 #undef PARM_TYPE
98 }
99 /* Description. */
100 else if(type == SAR_PARM_DESCRIPTION)
101 {
102 #define PARM_TYPE const sar_parm_description_struct
103 PARM_TYPE *pv = (PARM_TYPE *)p;
104 if(pv->description != NULL)
105 {
106 fprintf(
107 fp,
108 "description %s\n",
109 pv->description
110 );
111 parms_saved++;
112 }
113 #undef PARM_TYPE
114 }
115 /* Player model file. */
116 else if(type == SAR_PARM_PLAYER_MODEL_FILE)
117 {
118 #define PARM_TYPE const sar_parm_player_model_file_struct
119 PARM_TYPE *pv = (PARM_TYPE *)p;
120 if(pv->file != NULL)
121 {
122 fprintf(
123 fp,
124 "player_model_file %s\n",
125 pv->file
126 );
127 parms_saved++;
128 }
129 #undef PARM_TYPE
130 }
131 /* Weather. */
132 else if(type == SAR_PARM_WEATHER)
133 {
134 #define PARM_TYPE const sar_parm_weather_struct
135 PARM_TYPE *pv = (PARM_TYPE *)p;
136 if(pv->weather_preset_name != NULL)
137 {
138 fprintf(
139 fp,
140 "weather %s\n",
141 pv->weather_preset_name
142 );
143 parms_saved++;
144 }
145 #undef PARM_TYPE
146 }
147 /* Time of day. */
148 else if(type == SAR_PARM_TIME_OF_DAY)
149 {
150 #define PARM_TYPE const sar_parm_time_of_day_struct
151 PARM_TYPE *pv = (PARM_TYPE *)p;
152 fprintf(
153 fp,
154 "time_of_day %f\n",
155 pv->tod
156 );
157 parms_saved++;
158 #undef PARM_TYPE
159 }
160 /* Registered location. */
161 else if(type == SAR_PARM_REGISTER_LOCATION)
162 {
163 #define PARM_TYPE const sar_parm_register_location_struct
164 PARM_TYPE *pv = (PARM_TYPE *)p;
165 fprintf(
166 fp,
167 "register_location %f %f %f %f %f %f%s%s\n",
168 pv->pos.x, pv->pos.y, SFMMetersToFeet(pv->pos.z),
169 RADTODEG(pv->dir.heading),
170 RADTODEG(pv->dir.pitch),
171 RADTODEG(pv->dir.bank),
172 (pv->name != NULL) ? " " : "",
173 (pv->name != NULL) ? pv->name : ""
174 );
175 parms_saved++;
176 #undef PARM_TYPE
177 }
178 /* Scene GPS. */
179 else if(type == SAR_PARM_SCENE_GPS)
180 {
181 #define PARM_TYPE const sar_parm_scene_gps_struct
182 PARM_TYPE *pv = (PARM_TYPE *)p;
183 fprintf(
184 fp,
185 "scene_gps %f %f %f\n",
186 pv->dms_x_offset, pv->dms_y_offset,
187 pv->planet_radius
188 );
189 parms_saved++;
190 #undef PARM_TYPE
191 }
192 /* Scene map. */
193 else if(type == SAR_PARM_SCENE_MAP)
194 {
195 #define PARM_TYPE const sar_parm_scene_map_struct
196 PARM_TYPE *pv = (PARM_TYPE *)p;
197 fprintf(
198 fp,
199 "scene_map %f %f%s%s\n",
200 pv->width, pv->height,
201 (pv->file != NULL) ? " " : "",
202 (pv->file != NULL) ? pv->file : ""
203 );
204 parms_saved++;
205 #undef PARM_TYPE
206 }
207 /* Scene elevation. */
208 else if(type == SAR_PARM_SCENE_ELEVATION)
209 {
210 #define PARM_TYPE const sar_parm_scene_elevation_struct
211 PARM_TYPE *pv = (PARM_TYPE *)p;
212 fprintf(
213 fp,
214 "scene_elevation %f\n",
215 SFMMetersToFeet(pv->elevation)
216 );
217 parms_saved++;
218 #undef PARM_TYPE
219 }
220 /* Scene CANT. */
221 else if(type == SAR_PARM_SCENE_CANT)
222 {
223 #define PARM_TYPE const sar_parm_scene_cant_struct
224 PARM_TYPE *pv = (PARM_TYPE *)p;
225 fprintf(
226 fp,
227 "scene_cant %f\n",
228 RADTODEG(pv->cant)
229 );
230 parms_saved++;
231 #undef PARM_TYPE
232 }
233 /* Scene ground flags. */
234 else if(type == SAR_PARM_SCENE_GROUND_FLAGS)
235 {
236 #define PARM_TYPE const sar_parm_scene_ground_flags_struct
237 PARM_TYPE *pv = (PARM_TYPE *)p;
238 fprintf(fp, "scene_ground_flags");
239 if(pv->flags & SAR_SCENE_BASE_FLAG_IS_WATER)
240 fprintf(fp, " is_water");
241 fputc('\n', fp);
242 parms_saved++;
243 #undef PARM_TYPE
244 }
245 /* Scene ground tile. */
246 else if(type == SAR_PARM_SCENE_GROUND_TILE)
247 {
248 #define PARM_TYPE const sar_parm_scene_ground_tile_struct
249 PARM_TYPE *pv = (PARM_TYPE *)p;
250 fprintf(
251 fp,
252 "scene_ground_tile %i %i %f %.2f %.2f %.2f %.2f%s%s\n",
253 pv->tile_width, pv->tile_height, pv->close_range,
254 pv->color.r, pv->color.g, pv->color.b, pv->color.a,
255 (pv->texture_name != NULL) ? " " : "",
256 (pv->texture_name != NULL) ? pv->texture_name : ""
257 );
258 parms_saved++;
259 #undef PARM_TYPE
260 }
261 /* Texture base directory. */
262 else if(type == SAR_PARM_TEXTURE_BASE_DIRECTORY)
263 {
264 #define PARM_TYPE const sar_parm_texture_base_directory_struct
265 PARM_TYPE *pv = (PARM_TYPE *)p;
266 fprintf(
267 fp,
268 "texture_base_directory%s%s\n",
269 (pv->directory != NULL) ? " " : "",
270 (pv->directory != NULL) ? pv->directory : ""
271 );
272 parms_saved++;
273 #undef PARM_TYPE
274 }
275 /* Texture load. */
276 else if(type == SAR_PARM_TEXTURE_LOAD)
277 {
278 #define PARM_TYPE const sar_parm_texture_load_struct
279 PARM_TYPE *pv = (PARM_TYPE *)p;
280 fprintf(
281 fp,
282 "texture_load %s %s %f\n",
283 pv->name, pv->file, pv->priority
284 );
285 parms_saved++;
286 #undef PARM_TYPE
287 }
288 /* Mission scene file. */
289 else if(type == SAR_PARM_MISSION_SCENE_FILE)
290 {
291 #define PARM_TYPE const sar_parm_mission_scene_file_struct
292 PARM_TYPE *pv = (PARM_TYPE *)p;
293 fprintf(
294 fp,
295 "mission_scene_file%s%s\n",
296 (pv->file != NULL) ? " " : "",
297 (pv->file != NULL) ? pv->file : ""
298 );
299 parms_saved++;
300 #undef PARM_TYPE
301 }
302 /* Mission new objective. */
303 else if(type == SAR_PARM_MISSION_NEW_OBJECTIVE)
304 {
305 #define PARM_TYPE const sar_parm_mission_new_objective_struct
306 PARM_TYPE *pv = (PARM_TYPE *)p;
307 fprintf(fp, "mission_objective_new");
308 switch(pv->objective_type)
309 {
310 case SAR_MISSION_OBJECTIVE_ARRIVE_AT:
311 fprintf(fp, " arrive");
312 break;
313 case SAR_MISSION_OBJECTIVE_PICK_UP_ARRIVE_AT:
314 fprintf(fp, " pick_up_arrive");
315 break;
316 case SAR_MISSION_OBJECTIVE_PICK_UP:
317 fprintf(fp, " pick_up");
318 break;
319 }
320 fputc('\n', fp);
321 parms_saved++;
322 #undef PARM_TYPE
323 }
324 /* Mission time left. */
325 else if(type == SAR_PARM_MISSION_TIME_LEFT)
326 {
327 #define PARM_TYPE const sar_parm_mission_time_left_struct
328 PARM_TYPE *pv = (PARM_TYPE *)p;
329 fprintf(
330 fp,
331 "mission_objective_time_left %f\n",
332 pv->time_left
333 );
334 parms_saved++;
335 #undef PARM_TYPE
336 }
337 /* Mission begin at. */
338 else if(type == SAR_PARM_MISSION_BEGIN_AT)
339 {
340 #define PARM_TYPE const sar_parm_mission_begin_at_struct
341 PARM_TYPE *pv = (PARM_TYPE *)p;
342 fprintf(
343 fp,
344 "mission_begin_at%s%s\n",
345 (pv->name != NULL) ? " " : "",
346 (pv->name != NULL) ? pv->name : ""
347 );
348 parms_saved++;
349 #undef PARM_TYPE
350 }
351 /* Mission begin at position. */
352 else if(type == SAR_PARM_MISSION_BEGIN_AT_POS)
353 {
354 #define PARM_TYPE const sar_parm_mission_begin_at_pos_struct
355 PARM_TYPE *pv = (PARM_TYPE *)p;
356 fprintf(
357 fp,
358 "mission_begin_at_pos %f %f %f %f %f %f\n",
359 pv->pos.x, pv->pos.y, SFMMetersToFeet(pv->pos.z),
360 RADTODEG(pv->dir.heading),
361 RADTODEG(pv->dir.pitch),
362 RADTODEG(pv->dir.bank)
363 );
364 parms_saved++;
365 #undef PARM_TYPE
366 }
367 /* Mission arrive at. */
368 else if(type == SAR_PARM_MISSION_ARRIVE_AT)
369 {
370 #define PARM_TYPE const sar_parm_mission_arrive_at_struct
371 PARM_TYPE *pv = (PARM_TYPE *)p;
372 fprintf(
373 fp,
374 "mission_objective_arrive_at%s%s\n",
375 (pv->name != NULL) ? " " : "",
376 (pv->name != NULL) ? pv->name : ""
377 );
378 parms_saved++;
379 #undef PARM_TYPE
380 }
381 /* Mission message success. */
382 else if(type == SAR_PARM_MISSION_MESSAGE_SUCCESS)
383 {
384 #define PARM_TYPE const sar_parm_mission_message_success_struct
385 PARM_TYPE *pv = (PARM_TYPE *)p;
386 fprintf(
387 fp,
388 "mission_objective_message_success%s%s\n",
389 (pv->message != NULL) ? " " : "",
390 (pv->message != NULL) ? pv->message : ""
391 );
392 parms_saved++;
393 #undef PARM_TYPE
394 }
395 /* Mission message fail. */
396 else if(type == SAR_PARM_MISSION_MESSAGE_FAIL)
397 {
398 #define PARM_TYPE const sar_parm_mission_message_fail_struct
399 PARM_TYPE *pv = (PARM_TYPE *)p;
400 fprintf(
401 fp,
402 "mission_objective_message_fail%s%s\n",
403 (pv->message != NULL) ? " " : "",
404 (pv->message != NULL) ? pv->message : ""
405 );
406 parms_saved++;
407 #undef PARM_TYPE
408 }
409 /* Mission humans tally. */
410 else if(type == SAR_PARM_MISSION_HUMANS_TALLY)
411 {
412 #define PARM_TYPE const sar_parm_mission_humans_tally_struct
413 PARM_TYPE *pv = (PARM_TYPE *)p;
414 fprintf(
415 fp,
416 "mission_objective_humans_tally %i %i\n",
417 pv->humans_need_rescue, pv->total_humans
418 );
419 parms_saved++;
420 #undef PARM_TYPE
421 }
422 /* Mission add intercept. */
423 else if(type == SAR_PARM_MISSION_ADD_INTERCEPT)
424 {
425 #define PARM_TYPE const sar_parm_mission_add_intercept_struct
426 PARM_TYPE *pv = (PARM_TYPE *)p;
427 switch(pv->ref_code)
428 {
429 case 3: case 2: /* Arrive or begin at location. */
430 fprintf(
431 fp,
432 "mission_add_intercept %i %f %f\n",
433 pv->ref_code,
434 pv->radius, pv->urgency
435 );
436 parms_saved++;
437 break;
438 default: /* Standard intercept way point. */
439 fprintf(
440 fp,
441 "mission_add_intercept %i %f %f %f %f %f\n",
442 pv->ref_code,
443 pv->pos.x,
444 pv->pos.y,
445 pv->pos.z, /* In meters. */
446 pv->radius, pv->urgency
447 );
448 parms_saved++;
449 break;
450 }
451 #undef PARM_TYPE
452 }
453 /* Mission log header. */
454 else if(type == SAR_PARM_MISSION_LOG_HEADER)
455 {
456 #define PARM_TYPE const sar_parm_mission_log_header_struct
457 PARM_TYPE *pv = (PARM_TYPE *)p;
458 fprintf(fp, "BeginHeader\n");
459 fprintf(fp, " Version %i %i %i\n",
460 pv->version_major, pv->version_minor, pv->version_release
461 );
462 if(pv->title != NULL)
463 fprintf(fp, " Title %s\n", pv->title);
464 if(pv->scene_file != NULL)
465 fprintf(fp, " SceneFile %s\n", pv->scene_file);
466 if(pv->player_stats_file != NULL)
467 fprintf(fp, " PlayerStatsFile %s\n", pv->player_stats_file);
468 fprintf(fp, "EndHeader\n");
469 parms_saved++;
470 #undef PARM_TYPE
471 }
472 /* Mission log event. */
473 else if(type == SAR_PARM_MISSION_LOG_EVENT)
474 {
475 #define PARM_TYPE const sar_parm_mission_log_event_struct
476 PARM_TYPE *pv = (PARM_TYPE *)p;
477 fprintf(
478 fp,
479 "%i %f %f %f %f%c%s\n",
480 pv->event_type,
481 pv->tod,
482 pv->pos.x,
483 pv->pos.y,
484 pv->pos.z, /* In meters. */
485 (pv->message != NULL) ? ':' : '\0',
486 (pv->message != NULL) ? pv->message : ""
487 );
488 parms_saved++;
489 #undef PARM_TYPE
490 }
491 /* New object. */
492 else if(type == SAR_PARM_NEW_OBJECT)
493 {
494 #define PARM_TYPE const sar_parm_new_object_struct
495 PARM_TYPE *pv = (PARM_TYPE *)p;
496 fprintf(
497 fp,
498 "new_object %i\n",
499 pv->object_type
500 );
501 parms_saved++;
502 #undef PARM_TYPE
503 }
504 /* New helipad. */
505 else if(type == SAR_PARM_NEW_HELIPAD)
506 {
507 #define PARM_TYPE const sar_parm_new_helipad_struct
508 PARM_TYPE *pv = (PARM_TYPE *)p;
509 if(pv->ref_obj_name != NULL)
510 fprintf(
511 fp,
512 "new_helipad %s %f %f %f %s %c %c %c %c %c %s %f %f %f %f %f %f\n",
513 pv->style,
514 pv->length, pv->width,
515 SFMMetersToFeet(pv->recession),
516 (pv->label != NULL) ? pv->label : "_",
517 (pv->flags & SAR_HELIPAD_FLAG_EDGE_LIGHTING) ? 'y' : 'n',
518 (pv->flags & SAR_HELIPAD_FLAG_FUEL) ? 'y' : 'n',
519 (pv->flags & SAR_HELIPAD_FLAG_REPAIR) ? 'y' : 'n',
520 (pv->flags & SAR_HELIPAD_FLAG_DROPOFF) ? 'y' : 'n',
521 (pv->flags & SAR_HELIPAD_FLAG_RESTART_POINT) ? 'y' : 'n',
522 pv->ref_obj_name,
523 pv->ref_offset.x, pv->ref_offset.y,
524 SFMMetersToFeet(pv->ref_offset.z),
525 RADTODEG(pv->ref_dir.heading),
526 RADTODEG(pv->ref_dir.pitch),
527 RADTODEG(pv->ref_dir.bank)
528 );
529 else
530 fprintf(
531 fp,
532 "new_helipad %s %f %f %f %s %c %c %c %c %c\n",
533 pv->style,
534 pv->length, pv->width,
535 SFMMetersToFeet(pv->recession),
536 (pv->label != NULL) ? pv->label : "_",
537 (pv->flags & SAR_HELIPAD_FLAG_EDGE_LIGHTING) ? 'y' : 'n',
538 (pv->flags & SAR_HELIPAD_FLAG_FUEL) ? 'y' : 'n',
539 (pv->flags & SAR_HELIPAD_FLAG_REPAIR) ? 'y' : 'n',
540 (pv->flags & SAR_HELIPAD_FLAG_DROPOFF) ? 'y' : 'n',
541 (pv->flags & SAR_HELIPAD_FLAG_RESTART_POINT) ? 'y' : 'n'
542 );
543 parms_saved++;
544 #undef PARM_TYPE
545 }
546 /* New runway. */
547 else if(type == SAR_PARM_NEW_RUNWAY)
548 {
549 #define PARM_TYPE const sar_parm_new_runway_struct
550 PARM_TYPE *pv = (PARM_TYPE *)p;
551 fprintf(
552 fp,
553 "new_runway %f %f %f %i %i %f %s %s %f %f",
554 pv->range, pv->length, pv->width, pv->surface_type,
555 pv->dashes, pv->edge_light_spacing,
556 (pv->north_label != NULL) ? pv->north_label : "_",
557 (pv->south_label != NULL) ? pv->south_label : "_",
558 pv->north_displaced_threshold,
559 pv->south_displaced_threshold
560 );
561 if(pv->flags & SAR_RUNWAY_FLAG_THRESHOLDS)
562 fprintf(fp, " thresholds");
563 if(pv->flags & SAR_RUNWAY_FLAG_BORDERS)
564 fprintf(fp, " borders");
565 if(pv->flags & SAR_RUNWAY_FLAG_TD_MARKERS)
566 fprintf(fp, " td_markers");
567 if(pv->flags & SAR_RUNWAY_FLAG_MIDWAY_MARKERS)
568 fprintf(fp, " midway_markers");
569 if(pv->flags & SAR_RUNWAY_FLAG_NORTH_GS)
570 fprintf(fp, " north_gs");
571 if(pv->flags & SAR_RUNWAY_FLAG_SOUTH_GS)
572 fprintf(fp, " south_gs");
573 fputc('\n', fp);
574 parms_saved++;
575 #undef PARM_TYPE
576 }
577 /* New human. */
578 else if(type == SAR_PARM_NEW_HUMAN)
579 {
580 #define PARM_TYPE const sar_parm_new_human_struct
581 PARM_TYPE *pv = (PARM_TYPE *)p;
582 fprintf(
583 fp,
584 "new_human %s",
585 pv->type_name
586 );
587 if(pv->flags & SAR_HUMAN_FLAG_NEED_RESCUE)
588 fprintf(fp, " need_rescue");
589 if(pv->flags & SAR_HUMAN_FLAG_SIT)
590 fprintf(fp, " sit");
591 if(pv->flags & SAR_HUMAN_FLAG_SIT_UP)
592 fprintf(fp, " sit_up");
593 if(pv->flags & SAR_HUMAN_FLAG_SIT_DOWN)
594 fprintf(fp, " sit_down");
595 if(pv->flags & SAR_HUMAN_FLAG_LYING)
596 fprintf(fp, " lying");
597 if(pv->flags & SAR_HUMAN_FLAG_ALERT)
598 fprintf(fp, " alert");
599 if(pv->flags & SAR_HUMAN_FLAG_AWARE)
600 fprintf(fp, " aware");
601 if(pv->flags & SAR_HUMAN_FLAG_IN_WATER)
602 fprintf(fp, " in_water");
603 fputc('\n', fp);
604 parms_saved++;
605 #undef PARM_TYPE
606 }
607 /* New fire. */
608 else if(type == SAR_PARM_NEW_FIRE)
609 {
610 #define PARM_TYPE const sar_parm_new_fire_struct
611 PARM_TYPE *pv = (PARM_TYPE *)p;
612 fprintf(
613 fp,
614 "new_fire %f %f\n",
615 pv->radius, SFMMetersToFeet(pv->height)
616 );
617 parms_saved++;
618 #undef PARM_TYPE
619 }
620 /* New smoke. */
621 else if(type == SAR_PARM_NEW_SMOKE)
622 {
623 #define PARM_TYPE const sar_parm_new_smoke_struct
624 PARM_TYPE *pv = (PARM_TYPE *)p;
625 fprintf(
626 fp,
627 "new_smoke %f %f %f %f %f %f %i %ld %i %i\n",
628 pv->offset.x,
629 pv->offset.y,
630 pv->offset.z, /* In meters. */
631 pv->radius_start,
632 pv->radius_max,
633 pv->radius_rate,
634 pv->hide_at_max,
635 pv->respawn_int,
636 pv->total_units,
637 pv->color_code
638 );
639 parms_saved++;
640 #undef PARM_TYPE
641 }
642 /* New premodeled object. */
643 else if(type == SAR_PARM_NEW_PREMODELED)
644 {
645 #define PARM_TYPE const sar_parm_new_premodeled_struct
646 int i;
647 PARM_TYPE *pv = (PARM_TYPE *)p;
648 fprintf(
649 fp,
650 "new_premodeled %s",
651 pv->model_type
652 );
653 for(i = 0; i < pv->argc; i++)
654 fprintf(fp, " %s", pv->argv[i]);
655 fputc('\n', fp);
656 parms_saved++;
657 #undef PARM_TYPE
658 }
659 /* Select object by name. */
660 else if(type == SAR_PARM_SELECT_OBJECT_BY_NAME)
661 {
662 #define PARM_TYPE const sar_parm_select_object_by_name_struct
663 PARM_TYPE *pv = (PARM_TYPE *)p;
664 if(pv->name != NULL)
665 {
666 fprintf(
667 fp,
668 "select_object_by_name %s\n",
669 pv->name
670 );
671 parms_saved++;
672 }
673 #undef PARM_TYPE
674 }
675 /* Model file. */
676 else if(type == SAR_PARM_MODEL_FILE)
677 {
678 #define PARM_TYPE const sar_parm_model_file_struct
679 PARM_TYPE *pv = (PARM_TYPE *)p;
680 if(pv->file != NULL)
681 {
682 fprintf(
683 fp,
684 "model_file %s\n",
685 pv->file
686 );
687 parms_saved++;
688 }
689 #undef PARM_TYPE
690 }
691 /* Range. */
692 else if(type == SAR_PARM_RANGE)
693 {
694 #define PARM_TYPE const sar_parm_range_struct
695 PARM_TYPE *pv = (PARM_TYPE *)p;
696 fprintf(
697 fp,
698 "range %f\n",
699 pv->range
700 );
701 parms_saved++;
702 #undef PARM_TYPE
703 }
704 /* Range far. */
705 else if(type == SAR_PARM_RANGE_FAR)
706 {
707 #define PARM_TYPE const sar_parm_range_far_struct
708 PARM_TYPE *pv = (PARM_TYPE *)p;
709 fprintf(
710 fp,
711 "range_far %f\n",
712 pv->range_far
713 );
714 parms_saved++;
715 #undef PARM_TYPE
716 }
717 /* Translate. */
718 else if(type == SAR_PARM_TRANSLATE)
719 {
720 #define PARM_TYPE const sar_parm_translate_struct
721 PARM_TYPE *pv = (PARM_TYPE *)p;
722 fprintf(
723 fp,
724 "translate %f %f %f\n",
725 pv->translate.x,
726 pv->translate.y,
727 SFMMetersToFeet(pv->translate.z)
728 );
729 parms_saved++;
730 #undef PARM_TYPE
731 }
732 /* Translate random. */
733 else if(type == SAR_PARM_TRANSLATE_RANDOM)
734 {
735 #define PARM_TYPE const sar_parm_translate_random_struct
736 PARM_TYPE *pv = (PARM_TYPE *)p;
737 fprintf(
738 fp,
739 "translate_random %f %f\n",
740 pv->radius_bound,
741 pv->z_bound
742 );
743 parms_saved++;
744 #undef PARM_TYPE
745 }
746 /* Rotate. */
747 else if(type == SAR_PARM_ROTATE)
748 {
749 #define PARM_TYPE const sar_parm_rotate_struct
750 PARM_TYPE *pv = (PARM_TYPE *)p;
751 fprintf(
752 fp,
753 "rotate %f %f %f\n",
754 RADTODEG(pv->rotate.heading),
755 RADTODEG(pv->rotate.pitch),
756 RADTODEG(pv->rotate.bank)
757 );
758 parms_saved++;
759 #undef PARM_TYPE
760 }
761 /* No depth test. */
762 else if(type == SAR_PARM_NO_DEPTH_TEST)
763 {
764 #define PARM_TYPE const sar_parm_no_depth_test_struct
765 /* PARM_TYPE *pv = (PARM_TYPE *)p; */
766 fprintf(
767 fp,
768 "no_depth_test\n"
769 );
770 parms_saved++;
771 #undef PARM_TYPE
772 }
773 /* Polygon offset. */
774 else if(type == SAR_PARM_POLYGON_OFFSET)
775 {
776 #define PARM_TYPE const sar_parm_polygon_offset_struct
777 PARM_TYPE *pv = (PARM_TYPE *)p;
778 fprintf(fp, "polygon_offset");
779 if(pv->flags & SAR_OBJ_FLAG_POLYGON_OFFSET_REVERSE)
780 fprintf(fp, " reverse");
781 if(pv->flags & SAR_OBJ_FLAG_POLYGON_OFFSET_WRITE_DEPTH)
782 fprintf(fp, " write_depth");
783 fputc('\n', fp);
784 parms_saved++;
785 #undef PARM_TYPE
786 }
787 /* Countact bounds spherical. */
788 else if(type == SAR_PARM_CONTACT_BOUNDS_SPHERICAL)
789 {
790 #define PARM_TYPE const sar_parm_contact_bounds_spherical_struct
791 PARM_TYPE *pv = (PARM_TYPE *)p;
792 fprintf(
793 fp,
794 "contact_spherical %f\n",
795 pv->radius
796 );
797 parms_saved++;
798 #undef PARM_TYPE
799 }
800 /* Countact bounds cylendrical. */
801 else if(type == SAR_PARM_CONTACT_BOUNDS_CYLENDRICAL)
802 {
803 #define PARM_TYPE const sar_parm_contact_bounds_cylendrical_struct
804 PARM_TYPE *pv = (PARM_TYPE *)p;
805 fprintf(
806 fp,
807 "contact_cylendrical %f %f %f\n",
808 pv->radius,
809 pv->height_min, pv->height_max /* In meters. */
810 );
811 parms_saved++;
812 #undef PARM_TYPE
813 }
814 /* Countact bounds rectangular. */
815 else if(type == SAR_PARM_CONTACT_BOUNDS_RECTANGULAR)
816 {
817 #define PARM_TYPE const sar_parm_contact_bounds_rectangular_struct
818 PARM_TYPE *pv = (PARM_TYPE *)p;
819 fprintf(
820 fp,
821 "contact_rectangular %f %f %f %f %f %f\n",
822 pv->x_min, pv->x_max,
823 pv->y_min, pv->y_max,
824 pv->z_min, pv->z_max /* In meters. */
825 );
826 parms_saved++;
827 #undef PARM_TYPE
828 }
829 /* Ground elevation. */
830 else if(type == SAR_PARM_GROUND_ELEVATION)
831 {
832 #define PARM_TYPE const sar_parm_ground_elevation_struct
833 PARM_TYPE *pv = (PARM_TYPE *)p;
834 fprintf(
835 fp,
836 "ground_elevation %f\n",
837 SFMMetersToFeet(pv->elevation)
838 );
839 parms_saved++;
840 #undef PARM_TYPE
841 }
842 /* Object name. */
843 else if(type == SAR_PARM_OBJECT_NAME)
844 {
845 #define PARM_TYPE const sar_parm_object_name_struct
846 PARM_TYPE *pv = (PARM_TYPE *)p;
847 fprintf(
848 fp,
849 "object_name%s%s\n",
850 (pv->name != NULL) ? " " : "",
851 (pv->name != NULL) ? pv->name : ""
852 );
853 parms_saved++;
854 #undef PARM_TYPE
855 }
856 /* Object map description. */
857 else if(type == SAR_PARM_OBJECT_MAP_DESCRIPTION)
858 {
859 #define PARM_TYPE const sar_parm_object_map_description_struct
860 PARM_TYPE *pv = (PARM_TYPE *)p;
861 fprintf(
862 fp,
863 "object_map_description%s%s\n",
864 (pv->description != NULL) ? " " : "",
865 (pv->description != NULL) ? pv->description : ""
866 );
867 parms_saved++;
868 #undef PARM_TYPE
869 }
870 /* Object fuel. */
871 else if(type == SAR_PARM_FUEL)
872 {
873 #define PARM_TYPE const sar_parm_fuel_struct
874 PARM_TYPE *pv = (PARM_TYPE *)p;
875 fprintf(
876 fp,
877 "fuel %f %f\n",
878 pv->fuel, pv->fuel_max
879 );
880 parms_saved++;
881 #undef PARM_TYPE
882 }
883 /* Object hit points. */
884 else if(type == SAR_PARM_HITPOINTS)
885 {
886 #define PARM_TYPE const sar_parm_hitpoints_struct
887 PARM_TYPE *pv = (PARM_TYPE *)p;
888 fprintf(
889 fp,
890 "hitpoints %f %f\n",
891 pv->hitpoints, pv->hitpoints_max
892 );
893 parms_saved++;
894 #undef PARM_TYPE
895 }
896 /* Object engine state. */
897 else if(type == SAR_PARM_ENGINE_STATE)
898 {
899 #define PARM_TYPE const sar_parm_engine_state_struct
900 PARM_TYPE *pv = (PARM_TYPE *)p;
901 fprintf(
902 fp,
903 "engine_state %i\n",
904 pv->state
905 );
906 parms_saved++;
907 #undef PARM_TYPE
908 }
909 /* Object passengers. */
910 else if(type == SAR_PARM_PASSENGERS)
911 {
912 #define PARM_TYPE const sar_parm_passengers_struct
913 PARM_TYPE *pv = (PARM_TYPE *)p;
914 fprintf(
915 fp,
916 "passengers %i %i\n",
917 pv->passengers, pv->passengers_max
918 );
919 parms_saved++;
920 #undef PARM_TYPE
921 }
922 /* Runway approach lighting north. */
923 else if(type == SAR_PARM_RUNWAY_APPROACH_LIGHTING_NORTH)
924 {
925 #define PARM_TYPE const sar_parm_runway_approach_lighting_north_struct
926 PARM_TYPE *pv = (PARM_TYPE *)p;
927 fprintf(
928 fp,
929 "runway_approach_lighting_north"
930 );
931 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_END)
932 fprintf(fp, " end");
933 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_TRACER)
934 fprintf(fp, " tracer");
935 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_ALIGN)
936 fprintf(fp, " align");
937 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_ILS_GLIDE)
938 fprintf(fp, " ils_glide");
939 fputc('\n', fp);
940 parms_saved++;
941 #undef PARM_TYPE
942 }
943 /* Runway approach lighting south. */
944 else if(type == SAR_PARM_RUNWAY_APPROACH_LIGHTING_SOUTH)
945 {
946 #define PARM_TYPE const sar_parm_runway_approach_lighting_south_struct
947 PARM_TYPE *pv = (PARM_TYPE *)p;
948 fprintf(
949 fp,
950 "runway_approach_lighting_south"
951 );
952 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_END)
953 fprintf(fp, " end");
954 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_TRACER)
955 fprintf(fp, " tracer");
956 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_ALIGN)
957 fprintf(fp, " align");
958 if(pv->flags & SAR_RUNWAY_APPROACH_LIGHTING_ILS_GLIDE)
959 fprintf(fp, " ils_glide");
960 fputc('\n', fp);
961 parms_saved++;
962 #undef PARM_TYPE
963 }
964 /* Human message enter. */
965 else if(type == SAR_PARM_HUMAN_MESSAGE_ENTER)
966 {
967 #define PARM_TYPE const sar_parm_human_message_enter_struct
968 PARM_TYPE *pv = (PARM_TYPE *)p;
969 fprintf(
970 fp,
971 "set_human_message_enter%s%s\n",
972 (pv->message != NULL) ? " " : "",
973 (pv->message != NULL) ? pv->message : ""
974 );
975 parms_saved++;
976 #undef PARM_TYPE
977 }
978 /* Human reference. */
979 else if(type == SAR_PARM_HUMAN_REFERENCE)
980 {
981 #define PARM_TYPE const sar_parm_human_reference_struct
982 PARM_TYPE *pv = (PARM_TYPE *)p;
983 if(pv->reference_name != NULL)
984 {
985 fprintf(fp, "human_reference %s", pv->reference_name);
986 if(pv->flags & SAR_HUMAN_FLAG_RUN_TOWARDS)
987 fprintf(fp, " run_towards");
988 if(pv->flags & SAR_HUMAN_FLAG_RUN_AWAY)
989 fprintf(fp, " run_away");
990 fputc('\n', fp);
991 }
992 parms_saved++;
993 #undef PARM_TYPE
994 }
995
996
997 return(parms_saved);
998 }
999
1000 /*
1001 * Saves parameters to file regardless of file format.
1002 */
SARParmSaveToFileAny(const char * filename,FILE * fp,void ** parm,int total_parms,void * client_data,int (* progress_func)(void *,long,long))1003 static int SARParmSaveToFileAny(
1004 const char *filename, FILE *fp,
1005 void **parm, int total_parms,
1006 void *client_data,
1007 int (*progress_func)(void *, long, long)
1008 )
1009 {
1010 int i;
1011 const void *p;
1012
1013 /* Iterate through all parameters. */
1014 for(i = 0; i < total_parms; i++)
1015 {
1016 p = parm[i];
1017 if(p == NULL)
1018 continue;
1019
1020 /* Call progress callback. */
1021 if(progress_func != NULL)
1022 {
1023 if(progress_func(client_data, i + 1, total_parms))
1024 break;
1025 }
1026
1027 /* Save this parameter. */
1028 SARParmSaveToFileAnyIterate(filename, fp, p);
1029 }
1030
1031 return(0);
1032 }
1033
1034 /*
1035 * Saves the list of parameters to file.
1036 *
1037 * The given file_format is a hint to the file's format.
1038 *
1039 * Returns non-zero on error.
1040 */
SARParmSaveToFile(const char * filename,int file_format,void ** parm,int total_parms,void * client_data,int (* progress_func)(void *,long,long))1041 int SARParmSaveToFile(
1042 const char *filename, int file_format,
1043 void **parm, int total_parms,
1044 void *client_data,
1045 int (*progress_func)(void *, long, long)
1046 )
1047 {
1048 int status = -1;
1049 FILE *fp;
1050
1051
1052 if(filename == NULL)
1053 return(status);
1054
1055 /* Open file for writing. */
1056 fp = FOpen(filename, "wb");
1057 if(fp == NULL)
1058 return(status);
1059
1060 /* Save by file format type. */
1061 if(1)
1062 {
1063 status = SARParmSaveToFileAny(
1064 filename, fp,
1065 parm, total_parms,
1066 client_data, progress_func
1067 );
1068 }
1069
1070 /* Close file. */
1071 FClose(fp);
1072
1073 return(status);
1074 }
1075