]> git.mxchange.org Git - flightgear.git/blob - src/Main/options.cxx
389ccc72aca8f7285fb334cf09b0128d6b84c198
[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 (deliberately out of range)
119     fgSetDouble("/position/longitude-deg", 9999.0);
120     fgSetDouble("/position/latitude-deg", 9999.0);
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/current-view/heading-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/current-view/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(fgGetString("/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(fgGetString("/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(fgGetString("/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(fgGetString("/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(fgGetString("/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(fgGetString("/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(fgGetString("/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(fgGetString("/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(fgGetString("/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( "--telnet=" ) == 0 ) {
831         add_channel( "telnet", arg.substr(9) );
832     } else if ( arg.find( "--pve=" ) == 0 ) {
833         add_channel( "pve", arg.substr(6) );
834     } else if ( arg.find( "--ray=" ) == 0 ) {
835         add_channel( "ray", arg.substr(6) );
836     } else if ( arg.find( "--rul=" ) == 0 ) {
837         add_channel( "rul", arg.substr(6) );
838     } else if ( arg.find( "--joyclient=" ) == 0 ) {
839         add_channel( "joyclient", arg.substr(12) );
840 #ifdef FG_NETWORK_OLK
841     } else if ( arg == "--disable-network-olk" ) {
842         fgSetBool("/sim/networking/olk", false);
843     } else if ( arg== "--enable-network-olk") {
844         fgSetBool("/sim/networking/olk", true);
845     } else if ( arg == "--net-hud" ) {
846         fgSetBool("/sim/hud/net-display", true);
847         net_hud_display = 1;    // FIXME
848     } else if ( arg.find( "--net-id=") == 0 ) {
849         fgSetString("sim/networking/call-sign", arg.substr(9).c_str());
850 #endif
851     } else if ( arg.find( "--prop:" ) == 0 ) {
852         string assign = arg.substr(7);
853         unsigned int pos = assign.find('=');
854         if ( pos == arg.npos || pos == 0 ) {
855             SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
856             return FG_OPTIONS_ERROR;
857         }
858         string name = assign.substr(0, pos);
859         string value = assign.substr(pos + 1);
860         fgSetString(name.c_str(), value.c_str());
861         // SG_LOG(SG_GENERAL, SG_INFO, "Setting default value of property "
862         //        << name << " to \"" << value << '"');
863     } else if ( arg.find("--trace-read=") == 0) {
864         string name = arg.substr(13);
865         SG_LOG(SG_GENERAL, SG_INFO, "Tracing reads for property " << name);
866         fgGetNode(name.c_str(), true)
867           ->setAttribute(SGPropertyNode::TRACE_READ, true);
868     } else if ( arg.find("--trace-write=") == 0) {
869         string name = arg.substr(14);
870         SG_LOG(SG_GENERAL, SG_INFO, "Tracing writes for property " << name);
871         fgGetNode(name.c_str(), true)
872           ->setAttribute(SGPropertyNode::TRACE_WRITE, true);
873     } else if ( arg.find( "--view-offset=" ) == 0 ) {
874         // $$$ begin - added VS Renganathan, 14 Oct 2K
875         // for multi-window outside window imagery
876         string woffset = arg.substr( 14 );
877         double default_view_offset = 0.0;
878         if ( woffset == "LEFT" ) {
879                default_view_offset = SGD_PI * 0.25;
880         } else if ( woffset == "RIGHT" ) {
881             default_view_offset = SGD_PI * 1.75;
882         } else if ( woffset == "CENTER" ) {
883             default_view_offset = 0.00;
884         } else {
885             default_view_offset = atof( woffset.c_str() ) * SGD_DEGREES_TO_RADIANS;
886         }
887         FGViewer *pilot_view =
888             (FGViewer *)globals->get_viewmgr()->get_view( 0 );
889         pilot_view->setHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES );
890         pilot_view->setGoalHeadingOffset_deg( default_view_offset * SGD_RADIANS_TO_DEGREES );
891         fgSetDouble( "/sim/current-view/heading-offset-deg",
892                      default_view_offset  * SGD_RADIANS_TO_DEGREES );
893     // $$$ end - added VS Renganathan, 14 Oct 2K
894     } else if ( arg.find( "--visibility=" ) == 0 ) {
895         fgSetDouble("/environment/visibility-m", atof(arg.substr(13)));
896     } else if ( arg.find( "--visibility-miles=" ) == 0 ) {
897         double visibility = atof(arg.substr(19)) * 5280.0 * SG_FEET_TO_METER;
898         fgSetDouble("/environment/visibility-m", visibility);
899     } else if ( arg.find( "--wind=" ) == 0 ) {
900         string val = arg.substr(7);
901         unsigned int pos = val.find('@');
902         if ( pos == string::npos ) {
903           SG_LOG( SG_GENERAL, SG_ALERT, "bad wind value " << val );
904           return FG_OPTIONS_ERROR;
905         }
906         double dir = atof(val.substr(0,pos).c_str());
907         double speed = atof(val.substr(pos+1).c_str());
908         SG_LOG(SG_GENERAL, SG_INFO, "WIND: " << dir << '@' << 
909                speed << " knots" << endl);
910         fgSetDouble("/environment/wind-from-heading-deg", dir);
911         fgSetDouble("/environment/wind-speed-kt", speed);
912
913 #ifdef FG_WEATHERCM
914         // convert to fps
915         speed *= SG_NM_TO_METER * SG_METER_TO_FEET * (1.0/3600);
916         while (dir > 360)
917           dir -= 360;
918         while (dir <= 0)
919           dir += 360;
920         dir *= SGD_DEGREES_TO_RADIANS;
921         fgSetDouble("/environment/wind-from-north-fps",
922                     speed * cos(dir));
923         fgSetDouble("/environment/wind-from-east-fps",
924                     speed * sin(dir));
925 #endif // FG_WEATHERCM
926     } else if ( arg.find( "--wp=" ) == 0 ) {
927         parse_wp( arg.substr( 5 ) );
928     } else if ( arg.find( "--flight-plan=") == 0) {
929         parse_flightplan ( arg.substr (14) );
930     } else if ( arg.find( "--config=" ) == 0 ) {
931         string file = arg.substr(9);
932         try {
933           readProperties(file, globals->get_props());
934         } catch (const sg_exception &e) {
935           string message = "Error loading config file: ";
936           message += e.getFormattedMessage();
937           SG_LOG(SG_INPUT, SG_ALERT, message);
938           exit(2);
939         }
940     } else if ( arg.find( "--aircraft=" ) == 0 ) {
941         // read in the top level aircraft definition file
942         SGPath apath( globals->get_fg_root() );
943         apath.append( "Aircraft" );
944         apath.append( arg.substr(11) );
945         apath.concat( "-set.xml" );
946         SG_LOG(SG_INPUT, SG_INFO, "Reading aircraft: " << arg.substr(11)
947             << " from " << apath.str());
948         readProperties( apath.str(), globals->get_props() );
949     } else {
950         SG_LOG( SG_GENERAL, SG_ALERT, "Unknown option '" << arg << "'" );
951         return FG_OPTIONS_ERROR;
952     }
953     
954     return FG_OPTIONS_OK;
955 }
956
957
958 // Scan the command line options for an fg_root definition and set
959 // just that.
960 string
961 fgScanForRoot (int argc, char **argv) 
962 {
963     int i = 1;
964
965     SG_LOG(SG_GENERAL, SG_INFO, "Scanning for root: command line");
966
967     while ( i < argc ) {
968         SG_LOG( SG_GENERAL, SG_DEBUG, "argv[" << i << "] = " << argv[i] );
969
970         string arg = argv[i];
971         if ( arg.find( "--fg-root=" ) == 0 ) {
972             return arg.substr( 10 );
973         }
974
975         i++;
976     }
977
978     return "";
979 }
980
981
982 // Scan the config file for an fg_root definition and set just that.
983 string
984 fgScanForRoot (const string& path)
985 {
986     sg_gzifstream in( path );
987     if ( !in.is_open() )
988       return "";
989
990     SG_LOG( SG_GENERAL, SG_INFO, "Scanning for root: " << path );
991
992     in >> skipcomment;
993 #ifndef __MWERKS__
994     while ( ! in.eof() ) {
995 #else
996     char c = '\0';
997     while ( in.get(c) && c != '\0' ) {
998         in.putback(c);
999 #endif
1000         string line;
1001
1002 #if defined( macintosh )
1003         getline( in, line, '\r' );
1004 #else
1005         getline( in, line, '\n' );
1006 #endif
1007
1008         // catch extraneous (DOS) line ending character
1009         if ( line[line.length() - 1] < 32 ) {
1010             line = line.substr( 0, line.length()-1 );
1011         }
1012
1013         if ( line.find( "--fg-root=" ) == 0 ) {
1014             return line.substr( 10 );
1015         }
1016
1017         in >> skipcomment;
1018     }
1019
1020     return "";
1021 }
1022
1023
1024 // Parse the command line options
1025 void
1026 fgParseArgs (int argc, char **argv)
1027 {
1028     bool in_options = true;
1029
1030     SG_LOG(SG_GENERAL, SG_INFO, "Processing command line arguments");
1031
1032     for (int i = 1; i < argc; i++) {
1033         string arg = argv[i];
1034
1035         if (in_options && (arg.find('-') == 0)) {
1036           if (arg == "--") {
1037             in_options = false;
1038           } else {
1039             int result = parse_option(arg);
1040             if ( (result == FG_OPTIONS_HELP) ||
1041                  (result == FG_OPTIONS_ERROR) ) {
1042               fgUsage();
1043               exit(-1);
1044             }
1045           }
1046         } else {
1047           in_options = false;
1048           SG_LOG(SG_GENERAL, SG_INFO,
1049                  "Reading command-line property file " << arg);
1050           readProperties(arg, globals->get_props());
1051         }
1052     }
1053
1054     SG_LOG(SG_GENERAL, SG_INFO, "Finished command line arguments");
1055 }
1056
1057
1058 // Parse config file options
1059 void
1060 fgParseOptions (const string& path) {
1061     sg_gzifstream in( path );
1062     if ( !in.is_open() ) {
1063         return;
1064     }
1065
1066     SG_LOG( SG_GENERAL, SG_INFO, "Processing config file: " << path );
1067
1068     in >> skipcomment;
1069 #ifndef __MWERKS__
1070     while ( ! in.eof() ) {
1071 #else
1072     char c = '\0';
1073     while ( in.get(c) && c != '\0' ) {
1074         in.putback(c);
1075 #endif
1076         string line;
1077
1078 #if defined( macintosh )
1079         getline( in, line, '\r' );
1080 #else
1081         getline( in, line, '\n' );
1082 #endif
1083
1084         // catch extraneous (DOS) line ending character
1085         if ( line[line.length() - 1] < 32 ) {
1086             line = line.substr( 0, line.length()-1 );
1087         }
1088
1089         if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
1090             SG_LOG( SG_GENERAL, SG_ALERT, 
1091                     "Config file parse error: " << path << " '" 
1092                     << line << "'" );
1093             fgUsage();
1094             exit(-1);
1095         }
1096         in >> skipcomment;
1097     }
1098 }
1099
1100
1101 // Print usage message
1102 void 
1103 fgUsage ()
1104 {
1105     cout <<
1106 "Usage: fgfs [ option ... ]\n\
1107 \n\
1108 General Options:\n\
1109     --help, -h                    Print usage\n\
1110     --fg-root=path                Specify the root data path\n\
1111     --fg-scenery=path             Specify the base scenery path\n\
1112                                   Defaults to $FG_ROOT/Scenery\n\
1113     --disable-game-mode           Disable full-screen game mode\n\
1114     --enable-game-mode            Enable full-screen game mode\n\
1115     --disable-splash-screen       Disable splash screen\n\
1116     --enable-splash-screen        Enable splash screen\n\
1117     --disable-intro-music         Disable introduction music\n\
1118     --enable-intro-music          Enable introduction music\n\
1119     --disable-mouse-pointer       Disable extra mouse pointer\n\
1120     --enable-mouse-pointer        Enable extra mouse pointer (i.e. for full-\n\
1121                                   screen Voodoo based cards)\n\
1122     --disable-freeze              Start in a running state\n\
1123     --enable-freeze               Start in a frozen state\n\
1124     --disable-fuel-freeze         Fuel is consumed normally\n\
1125     --enable-fuel-freeze          Fuel tank quantity forced to remain constant\n\
1126     --disable-clock-freeze        Clock advances normally\n\
1127     --enable-clock-freeze         Do not advance clock\n\
1128     --control=mode                Primary control mode (joystick, keyboard,\n\
1129                                   mouse)\n\
1130     --enable-auto-coordination    Enable auto coordination\n\
1131     --disable-auto-coordination   Disable auto coordination\n\
1132     --browser-app=path            Specify path to your web browser\n\
1133     --prop:name=value             Set property <name> to <value>\n\
1134     --config=path                 Load additional properties from path\n\
1135     --units-feet                  Use feet for distances\n\
1136     --units-meters                Use meters for distances\n\
1137 \n\
1138 Features:\n\
1139     --disable-hud                 Disable Heads Up Display (HUD)\n\
1140     --enable-hud                  Enable Heads Up Display (HUD)\n\
1141     --disable-panel               Disable instrument panel\n\
1142     --enable-panel                Enable instrument panel\n\
1143     --disable-sound               Disable sound effects\n\
1144     --enable-sound                Enable sound effects\n\
1145     --disable-anti-alias-hud      Disable anti-aliased HUD\n\
1146     --enable-anti-alias-hud       Enable anti-aliased HUD\n\
1147 \n\
1148 Aircraft:\n\
1149     --aircraft=name               Select an aircraft profile as defined by a\n\
1150                                   top level <name>-set.xml\n\
1151 \n\
1152 Flight Model:\n\
1153     --fdm=name                    Select the core flight dynamics model\n\
1154                                   Can be one of jsb, larcsim, yasim, magic,\n\
1155                                   balloon, ada, external, or null\n\
1156     --aero=name                   Select aircraft aerodynamics model to load\n\
1157     --model-hz=n                  Run the FDM this rate (iterations per\n\
1158                                   second)\n\
1159     --speed=n                     Run the FDM 'n' times faster than real time\n\
1160     --notrim                      Do NOT attempt to trim the model (only with\n\
1161                                   fdm=jsbsim)\n\
1162     --on-ground                   Start at ground level (default)\n\
1163     --in-air                      Start in air (implied when using --altitude)\n\
1164     --wind=DIR@SPEED              Specify wind coming from DIR (degrees) at\n\
1165                                   SPEED (knots)\n\
1166 \n\
1167 Aircraft model directory (UIUC FDM ONLY):\n\
1168     --aircraft-dir=path           Aircraft directory relative to the path of\n\
1169                                   the executable\n\
1170 \n\
1171 Initial Position and Orientation:\n\
1172     --airport-id=ID               Specify starting position by airport ID\n\
1173     --offset-distance=nm          Specify distance to threshold\n\
1174     --offset-azimuth=degrees      Specify heading to threshold\n\
1175     --lon=degrees                 Starting longitude (west = -)\n\
1176     --lat=degrees                 Starting latitude (south = -)\n\
1177     --altitude=value              Starting altitude (in feet unless\n\
1178                                   --units-meters specified)\n\
1179     --heading=degrees             Specify heading (yaw) angle (Psi)\n\
1180     --roll=degrees                Specify roll angle (Phi)\n\
1181     --pitch=degrees               Specify pitch angle (Theta)\n\
1182     --uBody=units_per_sec         Specify velocity along the body X axis\n\
1183                                   (in feet unless --units-meters specified)\n\
1184     --vBody=units_per_sec         Specify velocity along the body Y axis\n\
1185                                   (in feet unless --units-meters specified)\n\
1186     --wBody=units_per_sec         Specify velocity along the body Z axis\n\
1187                                   (in feet unless --units-meters specified)\n\
1188     --vc=knots                    Specify initial airspeed\n\
1189     --mach=num                    Specify initial mach number\n\
1190     --glideslope=degreees         Specify flight path angle (can be positive)\n\
1191     --roc=fpm                     Specify initial climb rate (can be negative)\n\
1192 \n\
1193 Rendering Options:\n\
1194     --bpp=depth                   Specify the bits per pixel\n\
1195     --fog-disable                 Disable fog/haze\n\
1196     --fog-fastest                 Enable fastest fog/haze\n\
1197     --fog-nicest                  Enable nicest fog/haze\n\
1198     --enable-clouds               Enable cloud layers\n\
1199     --disable-clouds              Disable cloud layers\n\
1200     --clouds-asl=altitude         Specify altitude of cloud layer above sea\n\
1201                                   level\n\
1202     --fov=degrees                 Specify field of view angle\n\
1203     --disable-fullscreen          Disable fullscreen mode\n\
1204     --enable-fullscreen           Enable fullscreen mode\n\
1205     --shading-flat                Enable flat shading\n\
1206     --shading-smooth              Enable smooth shading\n\
1207     --disable-skyblend            Disable sky blending\n\
1208     --enable-skyblend             Enable sky blending\n\
1209     --disable-textures            Disable textures\n\
1210     --enable-textures             Enable textures\n\
1211     --disable-wireframe           Disable wireframe drawing mode\n\
1212     --enable-wireframe            Enable wireframe drawing mode\n\
1213     --geometry=WxH                Specify window geometry (640x480, etc)\n\
1214     --view-offset=value           Specify the default forward view direction\n\
1215                                   as an offset from straight ahead.  Allowable\n\
1216                                   values are LEFT, RIGHT, CENTER, or a specific\n\
1217                                   number in degrees\n\
1218     --visibility=meters           Specify initial visibility\n\
1219     --visibility-miles=miles      Specify initial visibility in miles\n\
1220 \n\
1221 Hud Options:\n\
1222     --hud-tris                    Hud displays number of triangles rendered\n\
1223     --hud-culled                  Hud displays percentage of triangles culled\n\
1224 \n\
1225 Time Options:\n\
1226     --time-offset=[+-]hh:mm:ss    Add this time offset\n\
1227     --time-match-real             Synchronize time with real-world time\n\
1228     --time-match-local            Synchronize time with local real-world time\n\
1229     --start-date-sys=yyyy:mm:dd:hh:mm:ss\n\
1230                                   Specify a starting date/time with respect to\n\
1231                                   system time\n\
1232     --start-date-gmt=yyyy:mm:dd:hh:mm:ss\n\
1233                                   Specify a starting date/time with respect to\n\
1234                                   Greenwich Mean Time\n\
1235     --start-date-lat=yyyy:mm:dd:hh:mm:ss\n\
1236                                   Specify a starting date/time with respect to\n\
1237                                   Local Aircraft Time\n\
1238 \n\
1239 Network Options:\n\
1240     --httpd=port                  Enable http server on the specified port\n\
1241     --telnet=port                 Enable telnet server on the specified port\n\
1242 \n"
1243
1244 #ifdef FG_JPEG_SERVER
1245 "\
1246     --jpg-httpd=port              Enable screen shot http server on the\n\
1247                                   specified port\n"
1248 #endif
1249 #ifdef FG_NETWORK_OLK
1250 "\
1251     --disable-network-olk         Disable Multipilot mode (default)\n\
1252     --enable-network-olk          Enable Multipilot mode\n\
1253     --net-hud                     Hud displays network info\n\
1254     --net-id=name                 Specify your own callsign\n"
1255 #endif
1256 "\
1257 Route/Way Point Options:\n\
1258     --wp=ID[@alt]                 Specify a waypoint for the GC autopilot;\n\
1259                                   multiple instances can be used to create a\n\
1260                                   route\n\
1261     --flight-plan=file            Read all waypoints from a file\n\
1262 \n\
1263 IO Options:\n\
1264     --gamin=params                Open connection using the Garmin GPS protocol\n\
1265     --joyclient=params            Open connection to an Agwagon joystick\n\
1266     --native-ctrls=params         Open connection using the FG Native Controls\n\
1267                                   protocol\n\
1268     --native-fdm=params           Open connection using the FG Native FDM\n\
1269                                   protocol\n\
1270     --native=params               Open connection using the FG Native protocol\n\
1271     --nmea=params                 Open connection using the NMEA protocol\n\
1272     --opengc=params               Open connection using the OpenGC protocol\n\
1273     --props=params                Open connection using the interactive\n\
1274                                   property manager\n\
1275     --pve=params                  Open connection using the PVE protocol\n\
1276     --ray=params                  Open connection using the RayWoodworth\n\
1277                                   motion chair protocol\n\
1278     --rul=params                  Open connection using the RUL protocol\n\
1279 \n\
1280     --atc610x                     Enable atc610x interface.\n\
1281 \n\
1282 Debugging Options:\n\
1283     --trace-read=property         Trace the reads for a property; multiple\n\
1284                                   instances allowed.\n\
1285     --trace-write=property        Trace the writes for a property; multiple\n\
1286                                   instances allowed.\n";
1287 }