]> git.mxchange.org Git - flightgear.git/blob - src/Main/options.cxx
Viewer update from Jim Wilson:
[flightgear.git] / src / Main / options.cxx
1 // options.cxx -- class to handle command line options
2 //
3 // Written by Curtis Olson, started April 1998.
4 //
5 // Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <simgear/compiler.h>
29 #include <simgear/misc/exception.hxx>
30
31 #include <math.h>               // rint()
32 #include <stdio.h>
33 #include <stdlib.h>             // atof(), atoi()
34 #include <string.h>             // strcmp()
35
36 #include STL_STRING
37
38 #include <simgear/misc/sgstream.hxx>
39 #include <simgear/misc/sg_path.hxx>
40 #include <simgear/route/route.hxx>
41 #include <simgear/route/waypoint.hxx>
42
43 // #include <Include/general.hxx>
44 // #include <Airports/simple.hxx>
45 // #include <Cockpit/cockpit.hxx>
46 // #include <FDM/flight.hxx>
47 // #include <FDM/UIUCModel/uiuc_aircraftdir.h>
48 #ifdef FG_NETWORK_OLK
49 #  include <NetworkOLK/network.h>
50 #endif
51
52 #include <GUI/gui.h>
53
54 #include "globals.hxx"
55 #include "fg_init.hxx"
56 #include "fg_props.hxx"
57 #include "options.hxx"
58 #include "viewmgr.hxx"
59
60 SG_USING_STD(string);
61 SG_USING_NAMESPACE(std);
62
63
64 #define NEW_DEFAULT_MODEL_HZ 120
65
66 enum
67 {
68     FG_OPTIONS_OK = 0,
69     FG_OPTIONS_HELP = 1,
70     FG_OPTIONS_ERROR = 2
71 };
72
73 static double
74 atof( const string& str )
75 {
76
77 #ifdef __MWERKS__ 
78     // -dw- if ::atof is called, then we get an infinite loop
79     return std::atof( str.c_str() );
80 #else
81     return ::atof( str.c_str() );
82 #endif
83 }
84
85 static int
86 atoi( const string& str )
87 {
88 #ifdef __MWERKS__ 
89     // -dw- if ::atoi is called, then we get an infinite loop
90     return std::atoi( str.c_str() );
91 #else
92     return ::atoi( str.c_str() );
93 #endif
94 }
95
96
97 /**
98  * Set a few fail-safe default property values.
99  *
100  * These should all be set in $FG_ROOT/preferences.xml, but just
101  * in case, we provide some initial sane values here. This method 
102  * should be invoked *before* reading any init files.
103  */
104 void
105 fgSetDefaults ()
106 {
107     // set a possibly independent location for scenery data
108     char *envp = ::getenv( "FG_SCENERY" );
109
110     if ( envp != NULL ) {
111         // fg_root could be anywhere, so default to environmental
112         // variable $FG_ROOT if it is set.
113         globals->set_fg_scenery(envp);
114     } else {
115         // Otherwise, default to Scenery being in $FG_ROOT/Scenery
116         globals->set_fg_scenery("");
117     }
118                                 // Position (Globe, AZ)
119     fgSetDouble("/position/longitude-deg", -110.6642444);
120     fgSetDouble("/position/latitude-deg", 33.3528917);
121     fgSetDouble("/position/altitude-ft", -9999.0);
122
123                                 // Orientation
124     fgSetDouble("/orientation/heading-deg", 270);
125     fgSetDouble("/orientation/roll-deg", 0);
126     fgSetDouble("/orientation/pitch-deg", 0.424);
127
128                                 // Velocities
129     fgSetString("/sim/startup/speed-set", "knots");
130     fgSetDouble("/velocities/uBody-fps", 0.0);
131     fgSetDouble("/velocities/vBody-fps", 0.0);
132     fgSetDouble("/velocities/wBody-fps", 0.0);
133     fgSetDouble("/velocities/speed-north-fps", 0.0);
134     fgSetDouble("/velocities/speed-east-fps", 0.0);
135     fgSetDouble("/velocities/speed-down-fps", 0.0);
136     fgSetDouble("/velocities/airspeed-kt", 0.0);
137     fgSetDouble("/velocities/mach", 0.0);
138
139                                 // Miscellaneous
140     fgSetBool("/sim/startup/game-mode", false);
141     fgSetBool("/sim/startup/splash-screen", true);
142     fgSetBool("/sim/startup/intro-music", true);
143     // we want mouse-pointer to have an undefined value if nothing is
144     // specified so we can do the right thing for voodoo-1/2 cards.
145     // fgSetString("/sim/startup/mouse-pointer", "disabled");
146     fgSetString("/sim/control-mode", "joystick");
147     fgSetBool("/sim/auto-coordination", false);
148 #if !defined(WIN32)
149     fgSetString("/sim/startup/browser-app", "netscape");
150 #else
151     fgSetString("/sim/startup/browser-app", "webrun.bat");
152 #endif
153                                 // Features
154     fgSetBool("/sim/hud/visibility", false);
155     fgSetBool("/sim/panel/visibility", true);
156     fgSetBool("/sim/sound/audible", true);
157     fgSetBool("/sim/hud/antialiased", false);
158
159                                 // Flight Model options
160     fgSetString("/sim/flight-model", "jsb");
161     fgSetString("/sim/aero", "c172");
162     fgSetInt("/sim/model-hz", NEW_DEFAULT_MODEL_HZ);
163     fgSetInt("/sim/speed-up", 1);
164     fgSetBool("/sim/startup/trim", false);
165     fgSetBool("/sim/startup/onground", true);
166
167                                 // Rendering options
168     fgSetString("/sim/rendering/fog", "nicest");
169     fgSetBool("/environment/clouds/status", true);
170     fgSetDouble("/environment/clouds/altitude-ft", 5000);
171     fgSetBool("/sim/startup/fullscreen", false);
172     fgSetBool("/sim/rendering/shading", true);
173     fgSetBool("/sim/rendering/skyblend", true);
174     fgSetBool("/sim/rendering/textures", true);
175     fgSetBool("/sim/rendering/wireframe", false);
176     fgSetInt("/sim/startup/xsize", 800);
177     fgSetInt("/sim/startup/ysize", 600);
178     fgSetInt("/sim/rendering/bits-per-pixel", 16);
179     fgSetString("/sim/view-mode", "pilot");
180     fgSetDouble("/sim/view/offset-deg", 0);
181     fgSetDouble("/environment/visibility-m", 20000);
182
183                                 // HUD options
184     fgSetString("/sim/startup/units", "feet");
185     fgSetString("/sim/hud/frame-stat-type", "tris");
186         
187                                 // Time options
188     fgSetInt("/sim/startup/time-offset", 0);
189     fgSetString("/sim/startup/time-offset-type", "system-offset");
190     fgSetLong("/sim/time/cur-time-override", 0);
191
192     fgSetBool("/sim/networking/network-olk", false);
193     fgSetString("/sim/networking/call-sign", "Johnny");
194
195                                 // Freeze options
196     fgSetBool("/sim/freeze/master", false);
197     fgSetBool("/sim/freeze/position", false);
198     fgSetBool("/sim/freeze/clock", false);
199     fgSetBool("/sim/freeze/fuel", false);
200 }
201
202
203 // parse a time string ([+/-]%f[:%f[:%f]]) into hours
204 static double
205 parse_time(const string& time_in) {
206     char *time_str, num[256];
207     double hours, minutes, seconds;
208     double result = 0.0;
209     int sign = 1;
210     int i;
211
212     time_str = (char *)time_in.c_str();
213
214     // printf("parse_time(): %s\n", time_str);
215
216     // check for sign
217     if ( strlen(time_str) ) {
218         if ( time_str[0] == '+' ) {
219             sign = 1;
220             time_str++;
221         } else if ( time_str[0] == '-' ) {
222             sign = -1;
223             time_str++;
224         }
225     }
226     // printf("sign = %d\n", sign);
227
228     // get hours
229     if ( strlen(time_str) ) {
230         i = 0;
231         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
232             num[i] = time_str[0];
233             time_str++;
234             i++;
235         }
236         if ( time_str[0] == ':' ) {
237             time_str++;
238         }
239         num[i] = '\0';
240         hours = atof(num);
241         // printf("hours = %.2lf\n", hours);
242
243         result += hours;
244     }
245
246     // get minutes
247     if ( strlen(time_str) ) {
248         i = 0;
249         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
250             num[i] = time_str[0];
251             time_str++;
252             i++;
253         }
254         if ( time_str[0] == ':' ) {
255             time_str++;
256         }
257         num[i] = '\0';
258         minutes = atof(num);
259         // printf("minutes = %.2lf\n", minutes);
260
261         result += minutes / 60.0;
262     }
263
264     // get seconds
265     if ( strlen(time_str) ) {
266         i = 0;
267         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
268             num[i] = time_str[0];
269             time_str++;
270             i++;
271         }
272         num[i] = '\0';
273         seconds = atof(num);
274         // printf("seconds = %.2lf\n", seconds);
275
276         result += seconds / 3600.0;
277     }
278
279     return(sign * result);
280 }
281
282
283 // parse a date string (yyyy:mm:dd:hh:mm:ss) into a time_t (seconds)
284 static long int 
285 parse_date( const string& date)
286 {
287     struct tm gmt;
288     char * date_str, num[256];
289     int i;
290     // initialize to zero
291     gmt.tm_sec = 0;
292     gmt.tm_min = 0;
293     gmt.tm_hour = 0;
294     gmt.tm_mday = 0;
295     gmt.tm_mon = 0;
296     gmt.tm_year = 0;
297     gmt.tm_isdst = 0; // ignore daylight savings time for the moment
298     date_str = (char *)date.c_str();
299     // get year
300     if ( strlen(date_str) ) {
301         i = 0;
302         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
303             num[i] = date_str[0];
304             date_str++;
305             i++;
306         }
307         if ( date_str[0] == ':' ) {
308             date_str++;
309         }
310         num[i] = '\0';
311         gmt.tm_year = atoi(num) - 1900;
312     }
313     // get month
314     if ( strlen(date_str) ) {
315         i = 0;
316         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
317             num[i] = date_str[0];
318             date_str++;
319             i++;
320         }
321         if ( date_str[0] == ':' ) {
322             date_str++;
323         }
324         num[i] = '\0';
325         gmt.tm_mon = atoi(num) -1;
326     }
327     // get day
328     if ( strlen(date_str) ) {
329         i = 0;
330         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
331             num[i] = date_str[0];
332             date_str++;
333             i++;
334         }
335         if ( date_str[0] == ':' ) {
336             date_str++;
337         }
338         num[i] = '\0';
339         gmt.tm_mday = atoi(num);
340     }
341     // get hour
342     if ( strlen(date_str) ) {
343         i = 0;
344         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
345             num[i] = date_str[0];
346             date_str++;
347             i++;
348         }
349         if ( date_str[0] == ':' ) {
350             date_str++;
351         }
352         num[i] = '\0';
353         gmt.tm_hour = atoi(num);
354     }
355     // get minute
356     if ( strlen(date_str) ) {
357         i = 0;
358         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
359             num[i] = date_str[0];
360             date_str++;
361             i++;
362         }
363         if ( date_str[0] == ':' ) {
364             date_str++;
365         }
366         num[i] = '\0';
367         gmt.tm_min = atoi(num);
368     }
369     // get second
370     if ( strlen(date_str) ) {
371         i = 0;
372         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
373             num[i] = date_str[0];
374             date_str++;
375             i++;
376         }
377         if ( date_str[0] == ':' ) {
378             date_str++;
379         }
380         num[i] = '\0';
381         gmt.tm_sec = atoi(num);
382     }
383     time_t theTime = sgTimeGetGMT( gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
384                                    gmt.tm_hour, gmt.tm_min, gmt.tm_sec );
385     //printf ("Date is %s\n", ctime(&theTime));
386     //printf ("in seconds that is %d\n", theTime);
387     //exit(1);
388     return (theTime);
389 }
390
391
392 // parse angle in the form of [+/-]ddd:mm:ss into degrees
393 static double
394 parse_degree( const string& degree_str) {
395     double result = parse_time( degree_str );
396
397     // printf("Degree = %.4f\n", result);
398
399     return(result);
400 }
401
402
403 // parse time offset string into seconds
404 static int
405 parse_time_offset( const string& time_str) {
406     int result;
407
408     // printf("time offset = %s\n", time_str);
409
410 #ifdef HAVE_RINT
411     result = (int)rint(parse_time(time_str) * 3600.0);
412 #else
413     result = (int)(parse_time(time_str) * 3600.0);
414 #endif
415
416     // printf("parse_time_offset(): %d\n", result);
417
418     return( result );
419 }
420
421
422 // Parse --fov=x.xx type option 
423 static double
424 parse_fov( const string& arg ) {
425     double fov = atof(arg);
426
427     if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
428     if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
429
430     fgSetDouble("/sim/field-of-view", fov);
431
432     // printf("parse_fov(): result = %.4f\n", fov);
433
434     return fov;
435 }
436
437
438 // Parse I/O channel option
439 //
440 // Format is "--protocol=medium,direction,hz,medium_options,..."
441 //
442 //   protocol = { native, nmea, garmin, fgfs, rul, pve, etc. }
443 //   medium = { serial, socket, file, etc. }
444 //   direction = { in, out, bi }
445 //   hz = number of times to process channel per second (floating
446 //        point values are ok.
447 //
448 // Serial example "--nmea=serial,dir,hz,device,baud" where
449 // 
450 //  device = OS device name of serial line to be open()'ed
451 //  baud = {300, 1200, 2400, ..., 230400}
452 //
453 // Socket exacmple "--native=socket,dir,hz,machine,port,style" where
454 // 
455 //  machine = machine name or ip address if client (leave empty if server)
456 //  port = port, leave empty to let system choose
457 //  style = tcp or udp
458 //
459 // File example "--garmin=file,dir,hz,filename" where
460 // 
461 //  filename = file system file name
462
463 static bool 
464 add_channel( const string& type, const string& channel_str ) {
465     // cout << "Channel string = " << channel_str << endl;
466
467     globals->get_channel_options_list()->push_back( type + "," + channel_str );
468
469     return true;
470 }
471
472
473 // Parse --wp=ID[@alt]
474 static bool 
475 parse_wp( const string& arg ) {
476     string id, alt_str;
477     double alt = 0.0;
478
479     unsigned int pos = arg.find( "@" );
480     if ( pos != string::npos ) {
481         id = arg.substr( 0, pos );
482         alt_str = arg.substr( pos + 1 );
483         // cout << "id str = " << id << "  alt str = " << alt_str << endl;
484         alt = atof( alt_str.c_str() );
485         if ( !strcmp("/sim/startup/units", "feet") ) {
486             alt *= SG_FEET_TO_METER;
487         }
488     } else {
489         id = arg;
490     }
491
492     FGAirport a;
493     if ( fgFindAirportID( id, &a ) ) {
494         SGWayPoint wp( a.longitude, a.latitude, alt, SGWayPoint::WGS84, id );
495         globals->get_route()->add_waypoint( wp );
496
497         return true;
498     } else {
499         return false;
500     }
501 }
502
503
504 // Parse --flight-plan=[file]
505 static bool 
506 parse_flightplan(const string& arg)
507 {
508     sg_gzifstream in(arg.c_str());
509     if ( !in.is_open() ) {
510         return false;
511     }
512     while ( true ) {
513         string line;
514
515 #if defined( macintosh )
516         getline( in, line, '\r' );
517 #else
518         getline( in, line, '\n' );
519 #endif
520
521         // catch extraneous (DOS) line ending character
522         if ( line[line.length() - 1] < 32 ) {
523             line = line.substr( 0, line.length()-1 );
524         }
525
526         if ( in.eof() ) {
527             break;
528         }
529         parse_wp(line);
530     }
531
532     return true;
533 }
534
535
536 // Parse a single option
537 static int 
538 parse_option (const string& arg) 
539 {
540     // General Options
541     if ( (arg == "--help") || (arg == "-h") ) {
542         // help/usage request
543         return(FG_OPTIONS_HELP);
544     } else if ( arg == "--disable-game-mode") {
545         fgSetBool("/sim/startup/game-mode", false);
546     } else if ( arg == "--enable-game-mode" ) {
547         fgSetBool("/sim/startup/game-mode", true);
548     } else if ( arg == "--disable-splash-screen" ) {
549         fgSetBool("/sim/startup/splash-screen", false); 
550     } else if ( arg == "--enable-splash-screen" ) {
551         fgSetBool("/sim/startup/splash-screen", true);
552     } else if ( arg == "--disable-intro-music" ) {
553         fgSetBool("/sim/startup/intro-music", false);
554     } else if ( arg == "--enable-intro-music" ) {
555         fgSetBool("/sim/startup/intro-music", true);
556     } else if ( arg == "--disable-mouse-pointer" ) {
557         fgSetString("/sim/startup/mouse-pointer", "disabled");
558     } else if ( arg == "--enable-mouse-pointer" ) {
559         fgSetString("/sim/startup/mouse-pointer", "enabled");
560     } else if ( arg == "--disable-freeze" ) {
561         fgSetBool("/sim/freeze/master", false);
562     } else if ( arg == "--enable-freeze" ) {
563         fgSetBool("/sim/freeze/master", true);
564     } else if ( arg == "--disable-fuel-freeze" ) {
565         fgSetBool("/sim/freeze/fuel", false);
566     } else if ( arg == "--enable-fuel-freeze" ) {
567         fgSetBool("/sim/freeze/fuel", true);
568     } else if ( arg == "--disable-clock-freeze" ) {
569         fgSetBool("/sim/freeze/clock", false);
570     } else if ( arg == "--enable-clock-freeze" ) {
571         fgSetBool("/sim/freeze/clock", true);
572     } else if ( arg == "--disable-anti-alias-hud" ) {
573         fgSetBool("/sim/hud/antialiased", false);
574     } else if ( arg == "--enable-anti-alias-hud" ) {
575         fgSetBool("/sim/hud/antialiased", true);
576     } else if ( arg.find( "--control=") == 0 ) {
577         fgSetString("/sim/control-mode", arg.substr(10).c_str());
578     } else if ( arg == "--disable-auto-coordination" ) {
579         fgSetBool("/sim/auto-coordination", false);
580     } else if ( arg == "--enable-auto-coordination" ) {
581         fgSetBool("/sim/auto-coordination", true);
582     } else if ( arg.find( "--browser-app=") == 0 ) {
583         fgSetString("/sim/startup/browser-app", arg.substr(14).c_str());
584     } else if ( arg == "--disable-hud" ) {
585         fgSetBool("/sim/hud/visibility", false);
586     } else if ( arg == "--enable-hud" ) {
587         fgSetBool("/sim/hud/visibility", true);
588     } else if ( arg == "--disable-panel" ) {
589         fgSetBool("/sim/panel/visibility", false);
590     } else if ( arg == "--enable-panel" ) {
591         fgSetBool("/sim/panel/visibility", true);
592     } else if ( arg == "--disable-sound" ) {
593         fgSetBool("/sim/sound/audible", false);
594     } else if ( arg == "--enable-sound" ) {
595         fgSetBool("/sim/sound/audible", true);
596     } else if ( arg.find( "--airport-id=") == 0 ) {
597                                 // NB: changed property name!!!
598         fgSetString("/sim/startup/airport-id", arg.substr(13).c_str());
599     } else if ( arg.find( "--offset-distance=") == 0 ) {
600         fgSetDouble("/sim/startup/offset-distance", atof(arg.substr(18)));
601     } else if ( arg.find( "--offset-azimuth=") == 0 ) {
602         fgSetDouble("/sim/startup/offset-azimuth", atof(arg.substr(17))); 
603     } else if ( arg.find( "--lon=" ) == 0 ) {
604         fgSetDouble("/position/longitude-deg",
605                               parse_degree(arg.substr(6)));
606         fgSetString("/sim/startup/airport-id", "");
607     } else if ( arg.find( "--lat=" ) == 0 ) {
608         fgSetDouble("/position/latitude-deg",
609                               parse_degree(arg.substr(6)));
610         fgSetString("/sim/startup/airport-id", "");
611     } else if ( arg.find( "--altitude=" ) == 0 ) {
612         fgSetBool("/sim/startup/onground", false);
613         if ( !strcmp("/sim/startup/units", "feet") )
614             fgSetDouble("/position/altitude-ft", atof(arg.substr(11)));
615         else
616             fgSetDouble("/position/altitude-ft",
617                         atof(arg.substr(11)) * SG_METER_TO_FEET);
618     } else if ( arg.find( "--uBody=" ) == 0 ) {
619         fgSetString("/sim/startup/speed-set", "UVW");
620         if ( !strcmp("/sim/startup/units", "feet") )
621           fgSetDouble("/velocities/uBody-fps", atof(arg.substr(8)));
622         else
623           fgSetDouble("/velocities/uBody-fps",
624                                atof(arg.substr(8)) * SG_METER_TO_FEET);
625     } else if ( arg.find( "--vBody=" ) == 0 ) {
626         fgSetString("/sim/startup/speed-set", "UVW");
627         if ( !strcmp("/sim/startup/units", "feet") )
628           fgSetDouble("/velocities/vBody-fps", atof(arg.substr(8)));
629         else
630           fgSetDouble("/velocities/vBody-fps",
631                                atof(arg.substr(8)) * SG_METER_TO_FEET);
632     } else if ( arg.find( "--wBody=" ) == 0 ) {
633         fgSetString("/sim/startup/speed-set", "UVW");
634         if ( !strcmp("/sim/startup/units", "feet") )
635           fgSetDouble("/velocities/wBody-fps", atof(arg.substr(8)));
636         else
637           fgSetDouble("/velocities/wBody-fps",
638                                atof(arg.substr(8)) * SG_METER_TO_FEET);
639     } else if ( arg.find( "--vNorth=" ) == 0 ) {
640         fgSetString("/sim/startup/speed-set", "NED");
641         if ( !strcmp("/sim/startup/units", "feet") )
642           fgSetDouble("/velocities/speed-north-fps", atof(arg.substr(9)));
643         else
644           fgSetDouble("/velocities/speed-north-fps",
645                                atof(arg.substr(9)) * SG_METER_TO_FEET);
646     } else if ( arg.find( "--vEast=" ) == 0 ) {
647         fgSetString("/sim/startup/speed-set", "NED");
648         if ( !strcmp("/sim/startup/units", "feet") )
649           fgSetDouble("/velocities/speed-east-fps", atof(arg.substr(8)));
650         else
651           fgSetDouble("/velocities/speed-east-fps",
652                       atof(arg.substr(8)) * SG_METER_TO_FEET);
653     } else if ( arg.find( "--vDown=" ) == 0 ) {
654         fgSetString("/sim/startup/speed-set", "NED");
655         if ( !strcmp("/sim/startup/units", "feet") )
656           fgSetDouble("/velocities/speed-down-fps", atof(arg.substr(8)));
657         else
658           fgSetDouble("/velocities/speed-down-fps",
659                                atof(arg.substr(8)) * SG_METER_TO_FEET);
660     } else if ( arg.find( "--vc=" ) == 0) {
661         fgSetString("/sim/startup/speed-set", "knots");
662         fgSetDouble("/velocities/airspeed-kt", atof(arg.substr(5)));
663     } else if ( arg.find( "--mach=" ) == 0) {
664         fgSetString("/sim/startup/speed-set", "mach");
665         fgSetDouble("/velocities/mach", atof(arg.substr(7)));
666     } else if ( arg.find( "--heading=" ) == 0 ) {
667         fgSetDouble("/orientation/heading-deg", atof(arg.substr(10)));
668     } else if ( arg.find( "--roll=" ) == 0 ) {
669         fgSetDouble("/orientation/roll-deg", atof(arg.substr(7)));
670     } else if ( arg.find( "--pitch=" ) == 0 ) {
671         fgSetDouble("/orientation/pitch-deg", atof(arg.substr(8)));
672     } else if ( arg.find( "--glideslope=" ) == 0 ) {
673         fgSetDouble("/velocities/glideslope", atof(arg.substr(13))
674                                           *SG_DEGREES_TO_RADIANS);
675     }  else if ( arg.find( "--roc=" ) == 0 ) {
676         fgSetDouble("/velocities/vertical-speed-fps", atof(arg.substr(6))/60);
677     } else if ( arg.find( "--fg-root=" ) == 0 ) {
678         globals->set_fg_root(arg.substr( 10 ));
679     } else if ( arg.find( "--fg-scenery=" ) == 0 ) {
680         globals->set_fg_scenery(arg.substr( 13 ));
681     } else if ( arg.find( "--fdm=" ) == 0 ) {
682         fgSetString("/sim/flight-model", arg.substr(6).c_str());
683     } else if ( arg.find( "--aero=" ) == 0 ) {
684         fgSetString("/sim/aero", arg.substr(7).c_str());
685     } else if ( arg.find( "--aircraft-dir=" ) == 0 ) {
686         fgSetString("/sim/aircraft-dir", arg.substr(15).c_str());
687     } else if ( arg.find( "--model-hz=" ) == 0 ) {
688         fgSetInt("/sim/model-hz", atoi(arg.substr(11)));
689     } else if ( arg.find( "--speed=" ) == 0 ) {
690         fgSetInt("/sim/speed-up", atoi(arg.substr(8)));
691     } else if ( arg.find( "--trim") == 0) {
692         fgSetBool("/sim/startup/trim", true);
693     } else if ( arg.find( "--notrim") == 0) {
694         fgSetBool("/sim/startup/trim", false);
695     } else if ( arg.find( "--on-ground") == 0) {
696         fgSetBool("/sim/startup/onground", true);
697     } else if ( arg.find( "--in-air") == 0) {
698         fgSetBool("/sim/startup/onground", false);
699     } else if ( arg == "--fog-disable" ) {
700         fgSetString("/sim/rendering/fog", "disabled");
701     } else if ( arg == "--fog-fastest" ) {
702         fgSetString("/sim/rendering/fog", "fastest");
703     } else if ( arg == "--fog-nicest" ) {
704         fgSetString("/sim/fog", "nicest");
705     } else if ( arg == "--disable-clouds" ) {
706         fgSetBool("/environment/clouds/status", false);
707     } else if ( arg == "--enable-clouds" ) {
708         fgSetBool("/environment/clouds/status", true);
709     } else if ( arg.find( "--clouds-asl=" ) == 0 ) {
710                                 // FIXME: check units
711         if ( !strcmp("/sim/startup/units", "feet") )
712           fgSetDouble("/environment/clouds/altitude-ft",
713                                 atof(arg.substr(13)));
714         else
715           fgSetDouble("/environment/clouds/altitude-ft",
716                                 atof(arg.substr(13)) * SG_METER_TO_FEET);
717     } else if ( arg.find( "--fov=" ) == 0 ) {
718         parse_fov( arg.substr(6) );
719     } else if ( arg == "--disable-fullscreen" ) {
720         fgSetBool("/sim/startup/fullscreen", false);
721     } else if ( arg== "--enable-fullscreen") {
722         fgSetBool("/sim/startup/fullscreen", true);
723     } else if ( arg == "--shading-flat") {
724         fgSetBool("/sim/rendering/shading", false);
725     } else if ( arg == "--shading-smooth") {
726         fgSetBool("/sim/rendering/shading", true);
727     } else if ( arg == "--disable-skyblend") {
728         fgSetBool("/sim/rendering/skyblend", false);
729     } else if ( arg== "--enable-skyblend" ) {
730         fgSetBool("/sim/rendering/skyblend", true);
731     } else if ( arg == "--disable-textures" ) {
732         fgSetBool("/sim/rendering/textures", false);
733     } else if ( arg == "--enable-textures" ) {
734         fgSetBool("/sim/rendering/textures", true);
735     } else if ( arg == "--disable-wireframe" ) {
736         fgSetBool("/sim/rendering/wireframe", false);
737     } else if ( arg == "--enable-wireframe" ) {
738         fgSetBool("/sim/rendering/wireframe", true);
739     } else if ( arg.find( "--geometry=" ) == 0 ) {
740         bool geometry_ok = true;
741         int xsize = 0, ysize = 0;
742         string geometry = arg.substr( 11 );
743         string::size_type i = geometry.find('x');
744
745         if (i != string::npos) {
746             xsize = atoi(geometry.substr(0, i));
747             ysize = atoi(geometry.substr(i+1));
748         } else {
749             geometry_ok = false;
750         }
751
752         if ( xsize <= 0 || ysize <= 0 ) {
753             xsize = 640;
754             ysize = 480;
755             geometry_ok = false;
756         }
757
758         if ( !geometry_ok ) {
759             SG_LOG( SG_GENERAL, SG_ALERT, "Unknown geometry: " << geometry );
760             SG_LOG( SG_GENERAL, SG_ALERT,
761                     "Setting geometry to " << xsize << 'x' << ysize << '\n');
762         } else {
763           SG_LOG( SG_GENERAL, SG_INFO,
764                   "Setting geometry to " << xsize << 'x' << ysize << '\n');
765           fgSetInt("/sim/startup/xsize", xsize);
766           fgSetInt("/sim/startup/ysize", ysize);
767         }
768     } else if ( arg.find( "--bpp=" ) == 0 ) {
769         string bits_per_pix = arg.substr( 6 );
770         if ( bits_per_pix == "16" ) {
771             fgSetInt("/sim/rendering/bits-per-pixel", 16);
772         } else if ( bits_per_pix == "24" ) {
773             fgSetInt("/sim/rendering/bits-per-pixel", 24);
774         } else if ( bits_per_pix == "32" ) {
775             fgSetInt("/sim/rendering/bits-per-pixel", 32);
776         } else {
777           SG_LOG(SG_GENERAL, SG_ALERT, "Unsupported bpp " << bits_per_pix);
778         }
779     } else if ( arg == "--units-feet" ) {
780         fgSetString("/sim/startup/units", "feet");
781     } else if ( arg == "--units-meters" ) {
782         fgSetString("/sim/startup/units", "meters");
783     } else if ( arg.find( "--time-offset" ) == 0 ) {
784         fgSetInt("/sim/startup/time-offset",
785                  parse_time_offset( (arg.substr(14)) ));
786         fgSetString("/sim/startup/time-offset-type", "system-offset");
787     } else if ( arg.find( "--time-match-real") == 0 ) {
788         fgSetString("/sim/startup/time-offset-type", "system-offset");
789     } else if ( arg.find( "--time-match-local") == 0 ) {
790         fgSetString("/sim/startup/time-offset-type", "latitude-offset");
791     } else if ( arg.find( "--start-date-sys=") == 0 ) {
792         fgSetInt("/sim/startup/time-offset", parse_date((arg.substr(17))));
793         fgSetString("/sim/startup/time-offset-type", "system");
794     } else if ( arg.find( "--start-date-lat=") == 0 ) {
795         fgSetInt("/sim/startup/time-offset", parse_date((arg.substr(17))));
796         fgSetString("/sim/startup/time-offset-type", "latitude");
797     } else if ( arg.find( "--start-date-gmt=") == 0 ) {
798         fgSetInt("/sim/startup/time-offset", parse_date((arg.substr(17))));
799         fgSetString("/sim/startup/time-offset-type", "gmt");
800     } else if ( arg == "--hud-tris" ) {
801         fgSetString("/sim/hud/frame-stat-type", "tris");
802     } else if ( arg == "--hud-culled" ) {
803         fgSetString("/sim/hud/frame-stat-type", "culled");
804     } else if ( arg.find( "--atc610x" ) == 0 ) {
805         add_channel( "atc610x", "dummy" );
806     } else if ( arg.find( "--atlas=" ) == 0 ) {
807         add_channel( "atlas", arg.substr(8) );
808     } else if ( arg.find( "--httpd=" ) == 0 ) {
809         add_channel( "httpd", arg.substr(8) );
810 #ifdef FG_JPEG_SERVER
811     } else if ( arg.find( "--jpg-httpd=" ) == 0 ) {
812         add_channel( "jpg-httpd", arg.substr(12) );
813 #endif
814     } else if ( arg.find( "--native=" ) == 0 ) {
815         add_channel( "native", arg.substr(9) );
816     } else if ( arg.find( "--native-ctrls=" ) == 0 ) {
817         add_channel( "native_ctrls", arg.substr(15) );
818     } else if ( arg.find( "--native-fdm=" ) == 0 ) {
819         add_channel( "native_fdm", arg.substr(13) );
820     } else if ( arg.find( "--opengc=" ) == 0 ) {
821         // char stop;
822         // cout << "Adding channel for OpenGC Display" << endl; cin >> stop;
823         add_channel( "opengc", arg.substr(9) );
824     } else if ( arg.find( "--garmin=" ) == 0 ) {
825         add_channel( "garmin", arg.substr(9) );
826     } else if ( arg.find( "--nmea=" ) == 0 ) {
827         add_channel( "nmea", arg.substr(7) );
828     } else if ( arg.find( "--props=" ) == 0 ) {
829         add_channel( "props", arg.substr(8) );
830     } else if ( arg.find( "--pve=" ) == 0 ) {
831         add_channel( "pve", arg.substr(6) );
832     } else if ( arg.find( "--ray=" ) == 0 ) {
833         add_channel( "ray", arg.substr(6) );
834     } else if ( arg.find( "--rul=" ) == 0 ) {
835         add_channel( "rul", arg.substr(6) );
836     } else if ( arg.find( "--joyclient=" ) == 0 ) {
837         add_channel( "joyclient", arg.substr(12) );
838 #ifdef FG_NETWORK_OLK
839     } else if ( arg == "--disable-network-olk" ) {
840         fgSetBool("/sim/networking/olk", false);
841     } else if ( arg== "--enable-network-olk") {
842         fgSetBool("/sim/networking/olk", true);
843     } else if ( arg == "--net-hud" ) {
844         fgSetBool("/sim/hud/net-display", true);
845         net_hud_display = 1;    // FIXME
846     } else if ( arg.find( "--net-id=") == 0 ) {
847         fgSetString("sim/networking/call-sign", arg.substr(9).c_str());
848 #endif
849     } else if ( arg.find( "--prop:" ) == 0 ) {
850         string assign = arg.substr(7);
851         unsigned int pos = assign.find('=');
852         if ( pos == arg.npos || pos == 0 ) {
853             SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
854             return FG_OPTIONS_ERROR;
855         }
856         string name = assign.substr(0, pos);
857         string value = assign.substr(pos + 1);
858         fgSetString(name.c_str(), value.c_str());
859         // SG_LOG(SG_GENERAL, SG_INFO, "Setting default value of property "
860         //        << name << " to \"" << value << '"');
861     } else if ( arg.find("--trace-read=") == 0) {
862         string name = arg.substr(13);
863         SG_LOG(SG_GENERAL, SG_INFO, "Tracing reads for property " << name);
864         fgGetNode(name.c_str(), true)
865           ->setAttribute(SGPropertyNode::TRACE_READ, true);
866     } else if ( arg.find("--trace-write=") == 0) {
867         string name = arg.substr(14);
868         SG_LOG(SG_GENERAL, SG_INFO, "Tracing writes for property " << name);
869         fgGetNode(name.c_str(), true)
870           ->setAttribute(SGPropertyNode::TRACE_WRITE, true);
871     } else if ( arg.find( "--view-offset=" ) == 0 ) {
872         // $$$ begin - added VS Renganathan, 14 Oct 2K
873         // for multi-window outside window imagery
874         string woffset = arg.substr( 14 );
875         double default_view_offset = 0.0;
876         if ( woffset == "LEFT" ) {
877                default_view_offset = SGD_PI * 0.25;
878         } else if ( woffset == "RIGHT" ) {
879             default_view_offset = SGD_PI * 1.75;
880         } else if ( woffset == "CENTER" ) {
881             default_view_offset = 0.00;
882         } else {
883             default_view_offset = atof( woffset.c_str() ) * SGD_DEGREES_TO_RADIANS;
884         }
885         FGViewer *pilot_view =
886             (FGViewer *)globals->get_viewmgr()->get_view( 0 );
887         pilot_view->setHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES );
888         pilot_view->setGoalHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES );
889         fgSetDouble("/sim/view/offset-deg", default_view_offset  * SGD_RADIANS_TO_DEGREES );
890     // $$$ end - added VS Renganathan, 14 Oct 2K
891     } else if ( arg.find( "--visibility=" ) == 0 ) {
892         fgSetDouble("/environment/visibility-m", atof(arg.substr(13)));
893     } else if ( arg.find( "--visibility-miles=" ) == 0 ) {
894         double visibility = atof(arg.substr(19)) * 5280.0 * SG_FEET_TO_METER;
895         fgSetDouble("/environment/visibility-m", visibility);
896     } else if ( arg.find( "--wind=" ) == 0 ) {
897         string val = arg.substr(7);
898         unsigned int pos = val.find('@');
899         if ( pos == string::npos ) {
900           SG_LOG( SG_GENERAL, SG_ALERT, "bad wind value " << val );
901           return FG_OPTIONS_ERROR;
902         }
903         double dir = atof(val.substr(0,pos).c_str());
904         double speed = atof(val.substr(pos+1).c_str());
905         SG_LOG(SG_GENERAL, SG_INFO, "WIND: " << dir << '@' << 
906                speed << " knots" << endl);
907         fgSetDouble("/environment/wind-from-heading-deg", dir);
908         fgSetDouble("/environment/wind-speed-kt", speed);
909
910 #if !defined (FG_NEW_ENVIRONMENT)
911         // convert to fps
912         speed *= SG_NM_TO_METER * SG_METER_TO_FEET * (1.0/3600);
913         while (dir > 360)
914           dir -= 360;
915         while (dir <= 0)
916           dir += 360;
917         dir *= SGD_DEGREES_TO_RADIANS;
918         fgSetDouble("/environment/wind-from-north-fps",
919                     speed * cos(dir));
920         fgSetDouble("/environment/wind-from-east-fps",
921                     speed * sin(dir));
922 #endif // FG_NEW_ENVIRONMENT
923     } else if ( arg.find( "--wp=" ) == 0 ) {
924         parse_wp( arg.substr( 5 ) );
925     } else if ( arg.find( "--flight-plan=") == 0) {
926         parse_flightplan ( arg.substr (14) );
927     } else if ( arg.find( "--config=" ) == 0 ) {
928         string file = arg.substr(9);
929         try {
930           readProperties(file, globals->get_props());
931         } catch (const sg_exception &e) {
932           string message = "Error loading config file: ";
933           message += e.getFormattedMessage();
934           SG_LOG(SG_INPUT, SG_ALERT, message);
935           exit(2);
936         }
937     } else if ( arg.find( "--aircraft=" ) == 0 ) {
938         // read in the top level aircraft definition file
939         SGPath apath( globals->get_fg_root() );
940         apath.append( "Aircraft" );
941         apath.append( arg.substr(11) );
942         apath.concat( "-set.xml" );
943         SG_LOG(SG_INPUT, SG_INFO, "Reading aircraft: " << arg.substr(11)
944             << " from " << apath.str());
945         try {
946             readProperties( apath.str(), globals->get_props() );
947         } catch (const sg_exception &e) {
948             string message = "Error loading aircraft file: ";
949             message += e.getFormattedMessage();
950             SG_LOG(SG_INPUT, SG_ALERT, message);
951             exit(2);
952         }
953     } else {
954         SG_LOG( SG_GENERAL, SG_ALERT, "Unknown option '" << arg << "'" );
955         return FG_OPTIONS_ERROR;
956     }
957     
958     return FG_OPTIONS_OK;
959 }
960
961
962 // Scan the command line options for an fg_root definition and set
963 // just that.
964 string
965 fgScanForRoot (int argc, char **argv) 
966 {
967     int i = 1;
968
969     SG_LOG(SG_GENERAL, SG_INFO, "Scanning for root: command line");
970
971     while ( i < argc ) {
972         SG_LOG( SG_GENERAL, SG_DEBUG, "argv[" << i << "] = " << argv[i] );
973
974         string arg = argv[i];
975         if ( arg.find( "--fg-root=" ) == 0 ) {
976             return arg.substr( 10 );
977         }
978
979         i++;
980     }
981
982     return "";
983 }
984
985
986 // Scan the config file for an fg_root definition and set just that.
987 string
988 fgScanForRoot (const string& path)
989 {
990     sg_gzifstream in( path );
991     if ( !in.is_open() )
992       return "";
993
994     SG_LOG( SG_GENERAL, SG_INFO, "Scanning for root: " << path );
995
996     in >> skipcomment;
997 #ifndef __MWERKS__
998     while ( ! in.eof() ) {
999 #else
1000     char c = '\0';
1001     while ( in.get(c) && c != '\0' ) {
1002         in.putback(c);
1003 #endif
1004         string line;
1005
1006 #if defined( macintosh )
1007         getline( in, line, '\r' );
1008 #else
1009         getline( in, line, '\n' );
1010 #endif
1011
1012         // catch extraneous (DOS) line ending character
1013         if ( line[line.length() - 1] < 32 ) {
1014             line = line.substr( 0, line.length()-1 );
1015         }
1016
1017         if ( line.find( "--fg-root=" ) == 0 ) {
1018             return line.substr( 10 );
1019         }
1020
1021         in >> skipcomment;
1022     }
1023
1024     return "";
1025 }
1026
1027
1028 // Parse the command line options
1029 void
1030 fgParseArgs (int argc, char **argv)
1031 {
1032     bool in_options = true;
1033
1034     SG_LOG(SG_GENERAL, SG_INFO, "Processing command line arguments");
1035
1036     for (int i = 1; i < argc; i++) {
1037         string arg = argv[i];
1038
1039         if (in_options && (arg.find('-') == 0)) {
1040           if (arg == "--") {
1041             in_options = false;
1042           } else {
1043             int result = parse_option(arg);
1044             if ( (result == FG_OPTIONS_HELP) ||
1045                  (result == FG_OPTIONS_ERROR) ) {
1046               fgUsage();
1047               exit(-1);
1048             }
1049           }
1050         } else {
1051           in_options = false;
1052           SG_LOG(SG_GENERAL, SG_INFO,
1053                  "Reading command-line property file " << arg);
1054           readProperties(arg, globals->get_props());
1055         }
1056     }
1057
1058     SG_LOG(SG_GENERAL, SG_INFO, "Finished command line arguments");
1059 }
1060
1061
1062 // Parse config file options
1063 void
1064 fgParseOptions (const string& path) {
1065     sg_gzifstream in( path );
1066     if ( !in.is_open() ) {
1067         return;
1068     }
1069
1070     SG_LOG( SG_GENERAL, SG_INFO, "Processing config file: " << path );
1071
1072     in >> skipcomment;
1073 #ifndef __MWERKS__
1074     while ( ! in.eof() ) {
1075 #else
1076     char c = '\0';
1077     while ( in.get(c) && c != '\0' ) {
1078         in.putback(c);
1079 #endif
1080         string line;
1081
1082 #if defined( macintosh )
1083         getline( in, line, '\r' );
1084 #else
1085         getline( in, line, '\n' );
1086 #endif
1087
1088         // catch extraneous (DOS) line ending character
1089         if ( line[line.length() - 1] < 32 ) {
1090             line = line.substr( 0, line.length()-1 );
1091         }
1092
1093         if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
1094             SG_LOG( SG_GENERAL, SG_ALERT, 
1095                     "Config file parse error: " << path << " '" 
1096                     << line << "'" );
1097             fgUsage();
1098             exit(-1);
1099         }
1100         in >> skipcomment;
1101     }
1102 }
1103
1104
1105 // Print usage message
1106 void 
1107 fgUsage ()
1108 {
1109     cout << "Usage: fgfs [ option ... ]" << endl
1110          << endl
1111
1112          << "General Options:" << endl
1113          << "    --help, -h                    Print usage" << endl
1114          << "    --fg-root=path                Specify the root data path" << endl
1115          << "    --fg-scenery=path             Specify the base scenery path;" << endl
1116          << "                                  Defaults to $FG_ROOT/Scenery" << endl
1117          << "    --disable-game-mode           Disable full-screen game mode" << endl
1118          << "    --enable-game-mode            Enable full-screen game mode" << endl
1119          << "    --disable-splash-screen       Disable splash screen" << endl
1120          << "    --enable-splash-screen        Enable splash screen" << endl
1121          << "    --disable-intro-music         Disable introduction music" << endl
1122          << "    --enable-intro-music          Enable introduction music" << endl
1123          << "    --disable-mouse-pointer       Disable extra mouse pointer" << endl
1124          << "    --enable-mouse-pointer        Enable extra mouse pointer (i.e. for full-" << endl
1125          << "                                  screen Voodoo based cards)" << endl
1126          << "    --disable-freeze              Start in a running state" << endl
1127          << "    --enable-freeze               Start in a frozen state" << endl
1128          << "    --disable-fuel-freeze         Fuel is consumed normally" << endl
1129          << "    --enable-fuel-freeze          Fuel tank quantity forced to remain constant" << endl
1130          << "    --disable-clock-freeze        Clock advances normally" << endl
1131          << "    --enable-clock-freeze         Do not advance clock" << endl
1132          << "    --control=mode                Primary control mode (joystick, keyboard," << endl
1133          << "                                  mouse)" << endl
1134          << "    --enable-auto-coordination    Enable auto coordination" << endl
1135          << "    --disable-auto-coordination   Disable auto coordination" << endl
1136          << "    --browser-app=path            Specify path to your web browser" << endl
1137          << "    --prop:name=value             Set property <name> to <value>" << endl
1138          << "    --config=path                 Load additional properties from path" << endl
1139          << "    --units-feet                  Use feet for distances" << endl
1140          << "    --units-meters                Use meters for distances" << endl
1141          << endl
1142
1143          << "Features:" << endl
1144          << "    --disable-hud                 Disable Heads Up Display (HUD)" << endl
1145          << "    --enable-hud                  Enable Heads Up Display (HUD)" << endl
1146          << "    --disable-panel               Disable instrument panel" << endl
1147          << "    --enable-panel                Enable instrument panel" << endl
1148          << "    --disable-sound               Disable sound effects" << endl
1149          << "    --enable-sound                Enable sound effects" << endl
1150          << "    --disable-anti-alias-hud      Disable anti-aliased HUD" << endl
1151          << "    --enable-anti-alias-hud       Enable anti-aliased HUD" << endl
1152          << endl
1153
1154          << "Aircraft:" <<endl
1155          << "    --aircraft=name               Select an aircraft profile as defined by a" << endl
1156          << "                                  top level <name>-set.xml" << endl
1157          << endl
1158
1159          << "Flight Model:" << endl
1160          << "    --fdm=name                    Select the core flight dynamics model" << endl
1161          << "                                  Can be one of jsb, larcsim, yasim, magic," << endl
1162          << "                                  balloon, ada, external, or null" << endl
1163          << "    --aero=name                   Select aircraft aerodynamics model to load" << endl
1164          << "    --model-hz=n                  Run the FDM this rate (iterations per" << endl
1165          << "                                  second)" << endl
1166          << "    --speed=n                     Run the FDM 'n' times faster than real time" << endl
1167          << "    --notrim                      Do NOT attempt to trim the model (only with" << endl
1168          << "                                  fdm=jsbsim)" << endl
1169          << "    --on-ground                   Start at ground level (default)" << endl
1170          << "    --in-air                      Start in air (implied when using --altitude)" << endl
1171          << "    --wind=DIR@SPEED              Specify wind coming from DIR (degrees) at" << endl
1172          << "                                  SPEED (knots)" << endl
1173          << endl
1174
1175          << "Aircraft model directory (UIUC FDM ONLY):" << endl
1176          << "    --aircraft-dir=path           Aircraft directory relative to the path of" << endl
1177          << "                                  the executable" << endl
1178          << endl
1179
1180          << "Initial Position and Orientation:" << endl
1181          << "    --airport-id=ID               Specify starting position by airport ID" << endl
1182          << "    --offset-distance=nm          Specify distance to threshold" << endl 
1183          << "    --offset-azimuth=degrees      Specify heading to threshold" << endl    
1184          << "    --lon=degrees                 Starting longitude (west = -)" << endl
1185          << "    --lat=degrees                 Starting latitude (south = -)" << endl
1186          << "    --altitude=value              Starting altitude (in feet unless" << endl
1187          << "                                  --units-meters specified)" << endl
1188          << "    --heading=degrees             Specify heading (yaw) angle (Psi)" << endl
1189          << "    --roll=degrees                Specify roll angle (Phi)" << endl
1190          << "    --pitch=degrees               Specify pitch angle (Theta)" << endl
1191          << "    --uBody=units_per_sec         Specify velocity along the body X axis" << endl
1192          << "                                  (in feet unless --units-meters specified)" << endl
1193          << "    --vBody=units_per_sec         Specify velocity along the body Y axis" << endl
1194          << "                                  (in feet unless --units-meters specified)" << endl
1195          << "    --wBody=units_per_sec         Specify velocity along the body Z axis" << endl
1196          << "                                  (in feet unless --units-meters specified)" << endl
1197          << "    --vc=knots                    Specify initial airspeed" << endl
1198          << "    --mach=num                    Specify initial mach number" << endl
1199          << "    --glideslope=degreees         Specify flight path angle (can be positive)" << endl
1200          << "    --roc=fpm                     Specify initial climb rate (can be negative)" << endl
1201          << endl
1202
1203          << "Rendering Options:" << endl
1204          << "    --bpp=depth                   Specify the bits per pixel" << endl
1205          << "    --fog-disable                 Disable fog/haze" << endl
1206          << "    --fog-fastest                 Enable fastest fog/haze" << endl
1207          << "    --fog-nicest                  Enable nicest fog/haze" << endl
1208          << "    --enable-clouds               Enable cloud layers" << endl
1209          << "    --disable-clouds              Disable cloud layers" << endl
1210          << "    --clouds-asl=altitude         Specify altitude of cloud layer above sea" << endl
1211          << "                                  level" << endl
1212          << "    --fov=degrees                 Specify field of view angle" << endl
1213          << "    --disable-fullscreen          Disable fullscreen mode" << endl
1214          << "    --enable-fullscreen           Enable fullscreen mode" << endl
1215          << "    --shading-flat                Enable flat shading" << endl
1216          << "    --shading-smooth              Enable smooth shading" << endl
1217          << "    --disable-skyblend            Disable sky blending" << endl
1218          << "    --enable-skyblend             Enable sky blending" << endl
1219          << "    --disable-textures            Disable textures" << endl
1220          << "    --enable-textures             Enable textures" << endl
1221          << "    --disable-wireframe           Disable wireframe drawing mode" << endl
1222          << "    --enable-wireframe            Enable wireframe drawing mode" << endl
1223          << "    --geometry=WxH                Specify window geometry (640x480, etc)" << endl
1224          << "    --view-offset=value           Specify the default forward view direction" << endl
1225          << "                                  as an offset from straight ahead.  Allowable" << endl
1226          << "                                  values are LEFT, RIGHT, CENTER, or a specific" << endl
1227          << "                                  number in degrees" << endl
1228          << "    --visibility=meters           Specify initial visibility" << endl
1229          << "    --visibility-miles=miles      Specify initial visibility in miles" << endl
1230          << endl
1231
1232          << "Hud Options:" << endl
1233          << "    --hud-tris                    Hud displays number of triangles rendered" << endl
1234          << "    --hud-culled                  Hud displays percentage of triangles culled" << endl
1235          << endl
1236         
1237          << "Time Options:" << endl
1238          << "    --time-offset=[+-]hh:mm:ss    Add this time offset" << endl
1239          << "    --time-match-real             Synchronize time with real-world time" << endl
1240          << "    --time-match-local            Synchronize time with local real-world time" << endl
1241          << "    --start-date-sys=yyyy:mm:dd:hh:mm:ss" << endl
1242          << "                                  Specify a starting date/time with respect to" << endl
1243          << "                                  system time" << endl
1244          << "    --start-date-gmt=yyyy:mm:dd:hh:mm:ss" << endl
1245          << "                                  Specify a starting date/time with respect to" << endl
1246          << "                                  Greenwich Mean Time" << endl
1247          << "    --start-date-lat=yyyy:mm:dd:hh:mm:ss" << endl
1248          << "                                  Specify a starting date/time with respect to" << endl
1249          << "                                  Local Aircraft Time" << endl
1250          << endl
1251
1252          << "Network Options:" << endl
1253          << "    --httpd=port                  Enable http server on the specified port" << endl
1254 #ifdef FG_JPEG_SERVER
1255          << "    --jpg-httpd=port              Enable screen shot http server on the" << endl
1256          << "                                  specified port" << endl
1257 #endif
1258 #ifdef FG_NETWORK_OLK
1259          << "    --disable-network-olk         Disable Multipilot mode (default)" << endl
1260          << "    --enable-network-olk          Enable Multipilot mode" << endl
1261          << "    --net-hud                     Hud displays network info" << endl
1262          << "    --net-id=name                 Specify your own callsign" << endl
1263 #endif
1264          << endl
1265
1266          << "Route/Way Point Options:" << endl
1267          << "    --wp=ID[@alt]                 Specify a waypoint for the GC autopilot;" << endl
1268          << "                                  multiple instances can be used to create a" << endl
1269          << "                                  route" << endl
1270          << "    --flight-plan=file            Read all waypoints from a file" << endl
1271          << endl
1272
1273          << "IO Options:" << endl
1274          << "    --gamin=params                Open connection using the Garmin GPS protocol" << endl
1275          << "    --joyclient=params            Open connection to an Agwagon joystick" << endl
1276          << "    --native-ctrls=params         Open connection using the FG Native Controls" << endl
1277          << "                                  protocol" << endl
1278          << "    --native-fdm=params           Open connection using the FG Native FDM" << endl
1279          << "                                  protocol" << endl
1280          << "    --native=params               Open connection using the FG Native protocol" << endl
1281          << "    --nmea=params                 Open connection using the NMEA protocol" << endl
1282          << "    --opengc=params               Open connection using the OpenGC protocol" << endl
1283          << "    --props=params                Open connection using the interactive" << endl
1284          << "                                  property manager" << endl
1285          << "    --pve=params                  Open connection using the PVE protocol" << endl
1286          << "    --ray=params                  Open connection using the RayWoodworth" << endl
1287          << "                                  motion chair protocol" << endl
1288          << "    --rul=params                  Open connection using the RUL protocol" << endl
1289          << endl
1290          << "    --atc610x                     Enable atc610x interface." << endl
1291          << endl
1292
1293          << "Debugging Options:" << endl
1294          << "    --trace-read=property         Trace the reads for a property; multiple" << endl
1295          << "                                  instances allowed." << endl
1296          << "    --trace-write=property        Trace the writes for a property; multiple" << endl
1297          << "                                  instances allowed." << endl
1298          << endl;
1299 }
1300
1301
1302