]> git.mxchange.org Git - flightgear.git/blob - src/Main/options.cxx
Initial revision
[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 #if defined(FX) && defined(XMESA)
29 bool global_fullscreen = true;
30 #endif
31
32 #include <Include/compiler.h>
33
34 #include <math.h>            // rint()
35 #include <stdio.h>
36 #include <stdlib.h>          // atof(), atoi()
37 #include <string.h>
38
39 #include STL_STRING
40
41 #include <Include/fg_constants.h>
42 #include <Include/general.hxx>
43 #include <Cockpit/cockpit.hxx>
44 #include <Debug/logstream.hxx>
45 #include <FDM/flight.hxx>
46 #include <Misc/fgstream.hxx>
47 #include <Time/fg_time.hxx>
48
49 #include "options.hxx"
50 #include "fg_serial.hxx"
51
52 FG_USING_STD(string);
53 FG_USING_NAMESPACE(std);
54
55 // from GLUTmain.cxx
56 extern void fgReshape( int width, int height );
57
58 inline double
59 atof( const string& str )
60 {
61
62 #ifdef __MWERKS__ 
63     // -dw- if ::atof is called, then we get an infinite loop
64     return std::atof( str.c_str() );
65 #else
66     return ::atof( str.c_str() );
67 #endif
68 }
69
70 inline int
71 atoi( const string& str )
72 {
73 #ifdef __MWERKS__ 
74     // -dw- if ::atoi is called, then we get an infinite loop
75     return std::atoi( str.c_str() );
76 #else
77     return ::atoi( str.c_str() );
78 #endif
79 }
80
81 // Defined the shared options class here
82 fgOPTIONS current_options;
83
84
85 // Constructor
86 fgOPTIONS::fgOPTIONS() :
87     // starting longitude in degrees (west = -)
88     // starting latitude in degrees (south = -)
89
90     // Default initial position is Globe, AZ (P13)
91     lon(-110.6642444),
92     lat(  33.3528917),
93
94     // North of the city of Globe
95     // lon(-110.7),
96     // lat(  33.4),
97
98     // North of the city of Globe
99     // lon(-110.742578),
100     // lat(  33.507122),
101
102     // Near where I used to live in Globe, AZ
103     // lon(-110.766000),
104     // lat(  33.377778),
105
106     // 10125 Jewell St. NE
107     // lon(-93.15),
108     // lat( 45.15),
109
110     // Near KHSP (Hot Springs, VA)
111     // lon(-79.8338964 + 0.01),
112     // lat( 37.9514564 + 0.008),
113
114     // (SEZ) SEDONA airport
115     // lon(-111.7884614 + 0.01),
116     // lat(  34.8486289 - 0.015),
117
118     // Jim Brennon's Kingmont Observatory
119     // lon(-121.1131667),
120     // lat(  38.8293917),
121
122     // Huaras, Peru (S09d 31.871'  W077d 31.498')
123     // lon(-77.5249667),
124     // lat( -9.5311833),
125  
126     // Eclipse Watching w73.5 n10 (approx) 18:00 UT
127     // lon(-73.5),
128     // lat( 10.0),
129
130     // Timms Hill (WI)
131     // lon(-90.1953055556),
132     // lat( 45.4511388889),
133
134     // starting altitude in meters (this will be reset to ground level
135     // if it is lower than the terrain
136     altitude(-9999.0),
137
138     // Initial Orientation
139     heading(270.0),      // heading (yaw) angle in degress (Psi)
140     roll(0.0),           // roll angle in degrees (Phi)
141     pitch(0.424),        // pitch angle in degrees (Theta)
142
143     // Miscellaneous
144     game_mode(0),
145     splash_screen(1),
146     intro_music(1),
147     mouse_pointer(0),
148     pause(0),
149
150     // Features
151     hud_status(1),
152     panel_status(0),
153     sound(1),
154
155     // Flight Model options
156     flight_model(FGInterface::FG_LARCSIM),
157
158     // Rendering options
159     fog(FG_FOG_NICEST),  // nicest
160     fov(55.0),
161     fullscreen(0),
162     shading(1),
163     skyblend(1),
164     textures(1),
165     wireframe(0),
166     xsize(640),
167     ysize(480),
168
169     // Scenery options
170     tile_diameter(5),
171
172     // HUD options
173     units(FG_UNITS_FEET),
174     tris_or_culled(0),
175         
176     // Time options
177     time_offset(0),
178     start_gst(0),
179     start_lst(0)
180
181 {
182     // set initial values/defaults
183     char* envp = ::getenv( "FG_ROOT" );
184
185     if ( envp != NULL ) {
186         // fg_root could be anywhere, so default to environmental
187         // variable $FG_ROOT if it is set.
188         fg_root = envp;
189     } else {
190         // Otherwise, default to a random compiled in location if
191         // $FG_ROOT is not set.  This can still be overridden from the
192         // command line or a config file.
193
194 #if defined( WIN32 )
195         fg_root = "\\FlightGear";
196 #elif defined( MACOS )
197         fg_root = "";
198 #else
199         fg_root = PKGLIBDIR;
200 #endif
201     }
202
203     airport_id = "";  // default airport id
204
205     // initialize port config string list
206     port_options_list.erase ( port_options_list.begin(), 
207                               port_options_list.end() );
208 }
209
210 void 
211 fgOPTIONS::toggle_panel() {
212     
213     FGTime *t = FGTime::cur_time_params;
214     
215     int toggle_pause = t->getPause();
216     
217     if( !toggle_pause )
218         t->togglePauseMode();
219     
220     if( panel_status ) {
221         panel_status = false;
222     } else {
223         panel_status = true;
224     }
225     if ( panel_status ) {
226         if( FGPanel::OurPanel == 0)
227             new FGPanel;
228         fov *= 0.4232;
229     } else {
230         fov *= (1.0 / 0.4232);
231     }
232     fgReshape( xsize, ysize);
233     
234     if( !toggle_pause )
235         t->togglePauseMode();
236 }
237
238 double
239 fgOPTIONS::parse_time(const string& time_in) {
240     char *time_str, num[256];
241     double hours, minutes, seconds;
242     double result = 0.0;
243     int sign = 1;
244     int i;
245
246     time_str = (char *)time_in.c_str();
247
248     // printf("parse_time(): %s\n", time_str);
249
250     // check for sign
251     if ( strlen(time_str) ) {
252         if ( time_str[0] == '+' ) {
253             sign = 1;
254             time_str++;
255         } else if ( time_str[0] == '-' ) {
256             sign = -1;
257             time_str++;
258         }
259     }
260     // printf("sign = %d\n", sign);
261
262     // get hours
263     if ( strlen(time_str) ) {
264         i = 0;
265         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
266             num[i] = time_str[0];
267             time_str++;
268             i++;
269         }
270         if ( time_str[0] == ':' ) {
271             time_str++;
272         }
273         num[i] = '\0';
274         hours = atof(num);
275         // printf("hours = %.2lf\n", hours);
276
277         result += hours;
278     }
279
280     // get minutes
281     if ( strlen(time_str) ) {
282         i = 0;
283         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
284             num[i] = time_str[0];
285             time_str++;
286             i++;
287         }
288         if ( time_str[0] == ':' ) {
289             time_str++;
290         }
291         num[i] = '\0';
292         minutes = atof(num);
293         // printf("minutes = %.2lf\n", minutes);
294
295         result += minutes / 60.0;
296     }
297
298     // get seconds
299     if ( strlen(time_str) ) {
300         i = 0;
301         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
302             num[i] = time_str[0];
303             time_str++;
304             i++;
305         }
306         num[i] = '\0';
307         seconds = atof(num);
308         // printf("seconds = %.2lf\n", seconds);
309
310         result += seconds / 3600.0;
311     }
312
313     return(sign * result);
314 }
315
316
317 long int fgOPTIONS::parse_date( const string& date)
318 {
319     struct tm gmt;
320     char * date_str, num[256];
321     int i;
322     // initialize to zero
323     gmt.tm_sec = 0;
324     gmt.tm_min = 0;
325     gmt.tm_hour = 0;
326     gmt.tm_mday = 0;
327     gmt.tm_mon = 0;
328     gmt.tm_year = 0;
329     gmt.tm_isdst = 0; // ignore daylight savingtime for the moment
330     date_str = (char *)date.c_str();
331     // get year
332     if ( strlen(date_str) ) {
333         i = 0;
334         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
335             num[i] = date_str[0];
336             date_str++;
337             i++;
338         }
339         if ( date_str[0] == ':' ) {
340             date_str++;
341         }
342         num[i] = '\0';
343         gmt.tm_year = atoi(num) - 1900;
344     }
345     // get month
346     if ( strlen(date_str) ) {
347         i = 0;
348         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
349             num[i] = date_str[0];
350             date_str++;
351             i++;
352         }
353         if ( date_str[0] == ':' ) {
354             date_str++;
355         }
356         num[i] = '\0';
357         gmt.tm_mon = atoi(num) -1;
358     }
359     // get day
360     if ( strlen(date_str) ) {
361         i = 0;
362         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
363             num[i] = date_str[0];
364             date_str++;
365             i++;
366         }
367         if ( date_str[0] == ':' ) {
368             date_str++;
369         }
370         num[i] = '\0';
371         gmt.tm_mday = atoi(num);
372     }
373     // get hour
374     if ( strlen(date_str) ) {
375         i = 0;
376         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
377             num[i] = date_str[0];
378             date_str++;
379             i++;
380         }
381         if ( date_str[0] == ':' ) {
382             date_str++;
383         }
384         num[i] = '\0';
385         gmt.tm_hour = atoi(num);
386     }
387     // get minute
388     if ( strlen(date_str) ) {
389         i = 0;
390         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
391             num[i] = date_str[0];
392             date_str++;
393             i++;
394         }
395         if ( date_str[0] == ':' ) {
396             date_str++;
397         }
398         num[i] = '\0';
399         gmt.tm_min = atoi(num);
400     }
401     // get second
402     if ( strlen(date_str) ) {
403         i = 0;
404         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
405             num[i] = date_str[0];
406             date_str++;
407             i++;
408         }
409         if ( date_str[0] == ':' ) {
410             date_str++;
411         }
412         num[i] = '\0';
413         gmt.tm_sec = atoi(num);
414     }
415     time_t theTime = FGTime::cur_time_params->get_gmt(gmt.tm_year,
416                                                       gmt.tm_mon,
417                                                       gmt.tm_mday,
418                                                       gmt.tm_hour,
419                                                       gmt.tm_min,
420                                                       gmt.tm_sec);
421     //printf ("Date is %s\n", ctime(&theTime));
422     //printf ("in seconds that is %d\n", theTime);
423     //exit(1);
424     return (theTime);
425 }
426
427
428 // parse degree in the form of [+/-]hhh:mm:ss
429 double
430 fgOPTIONS::parse_degree( const string& degree_str) {
431     double result = parse_time( degree_str );
432
433     // printf("Degree = %.4f\n", result);
434
435     return(result);
436 }
437
438
439 // parse time offset command line option
440 int
441 fgOPTIONS::parse_time_offset( const string& time_str) {
442     int result;
443
444     // printf("time offset = %s\n", time_str);
445
446 #ifdef HAVE_RINT
447     result = (int)rint(parse_time(time_str) * 3600.0);
448 #else
449     result = (int)(parse_time(time_str) * 3600.0);
450 #endif
451
452     // printf("parse_time_offset(): %d\n", result);
453
454     return( result );
455 }
456
457
458 // Parse --tile-diameter=n type option 
459
460 int
461 fgOPTIONS::parse_tile_radius( const string& arg ) {
462     int radius = atoi( arg );
463
464     if ( radius < FG_RADIUS_MIN ) { radius = FG_RADIUS_MIN; }
465     if ( radius > FG_RADIUS_MAX ) { radius = FG_RADIUS_MAX; }
466
467     // printf("parse_tile_radius(): radius = %d\n", radius);
468
469     return(radius);
470 }
471
472
473 // Parse --fdm=abcdefg type option 
474 int
475 fgOPTIONS::parse_fdm( const string& fm ) {
476     // printf("fdm = %s\n", fm);
477
478     if ( fm == "slew" ) {
479         return FGInterface::FG_SLEW;
480     } else if ( fm == "jsb" ) {
481         return FGInterface::FG_JSBSIM;
482     } else if ( (fm == "larcsim") || (fm == "LaRCsim") ) {
483         return FGInterface::FG_LARCSIM;
484     } else if ( fm == "external" ) {
485         return FGInterface::FG_EXTERNAL;
486     } else {
487         FG_LOG( FG_GENERAL, FG_ALERT, "Unknown fdm = " << fm );
488         exit(-1);
489     }
490
491     // we'll never get here, but it makes the compiler happy.
492     return -1;
493 }
494
495
496 // Parse --fov=x.xx type option 
497 double
498 fgOPTIONS::parse_fov( const string& arg ) {
499     double fov = atof(arg);
500
501     if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
502     if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
503
504     // printf("parse_fov(): result = %.4f\n", fov);
505
506     return(fov);
507 }
508
509
510 // Parse serial port option --serial=/dev/ttyS1,nmea,4800,out
511 //
512 // Format is "--serial=device,format,baud,direction" where
513 // 
514 //  device = OS device name to be open()'ed
515 //  format = {nmea, garmin,fgfs,rul}
516 //  baud = {300, 1200, 2400, ..., 230400}
517 //  direction = {in, out, bi}
518
519 bool 
520 fgOPTIONS::parse_serial( const string& serial_str ) {
521     string::size_type pos;
522
523     // cout << "Serial string = " << serial_str << endl;
524
525     // a flailing attempt to see if the port config string has a
526     // chance at being valid
527     pos = serial_str.find(",");
528     if ( pos == string::npos ) {
529         FG_LOG( FG_GENERAL, FG_ALERT, 
530                 "Malformed serial port configure string" );
531         return false;
532     }
533     
534     port_options_list.push_back( serial_str );
535
536     return true;
537 }
538
539
540 // Parse a single option
541 int fgOPTIONS::parse_option( const string& arg ) {
542     // General Options
543     if ( (arg == "--help") || (arg == "-h") ) {
544         // help/usage request
545         return(FG_OPTIONS_HELP);
546     } else if ( arg == "--disable-game-mode") {
547         game_mode = false;
548     } else if ( arg == "--enable-game-mode" ) {
549         game_mode = true;
550     } else if ( arg == "--disable-splash-screen" ) {
551         splash_screen = false;
552     } else if ( arg == "--enable-splash-screen" ) {
553         splash_screen = true;
554     } else if ( arg == "--disable-intro-music" ) {
555         intro_music = false;
556     } else if ( arg == "--enable-intro-music" ) {
557         intro_music = true;
558     } else if ( arg == "--disable-mouse-pointer" ) {
559         mouse_pointer = 1;
560     } else if ( arg == "--enable-mouse-pointer" ) {
561         mouse_pointer = 2;
562     } else if ( arg == "--disable-pause" ) {
563         pause = false;  
564     } else if ( arg == "--enable-pause" ) {
565         pause = true;   
566     } else if ( arg == "--disable-hud" ) {
567         hud_status = false;     
568     } else if ( arg == "--enable-hud" ) {
569         hud_status = true;      
570     } else if ( arg == "--disable-panel" ) {
571         panel_status = false;
572     } else if ( arg == "--enable-panel" ) {
573         panel_status = true;
574         fov *= 0.4232;
575     } else if ( arg == "--disable-sound" ) {
576         sound = false;
577     } else if ( arg == "--enable-sound" ) {
578         sound = true;
579     } else if ( arg.find( "--airport-id=") != string::npos ) {
580         airport_id = arg.substr( 13 );
581     } else if ( arg.find( "--lon=" ) != string::npos ) {
582         lon = parse_degree( arg.substr(6) );
583     } else if ( arg.find( "--lat=" ) != string::npos ) {
584         lat = parse_degree( arg.substr(6) );
585     } else if ( arg.find( "--altitude=" ) != string::npos ) {
586         if ( units == FG_UNITS_FEET ) {
587             altitude = atof( arg.substr(11) ) * FEET_TO_METER;
588         } else {
589             altitude = atof( arg.substr(11) );
590         }
591     } else if ( arg.find( "--heading=" ) != string::npos ) {
592         heading = atof( arg.substr(10) );
593     } else if ( arg.find( "--roll=" ) != string::npos ) {
594         roll = atof( arg.substr(7) );
595     } else if ( arg.find( "--pitch=" ) != string::npos ) {
596         pitch = atof( arg.substr(8) );
597     } else if ( arg.find( "--fg-root=" ) != string::npos ) {
598         fg_root = arg.substr( 10 );
599     } else if ( arg.find( "--fdm=" ) != string::npos ) {
600         flight_model = parse_fdm( arg.substr(6) );
601     } else if ( arg == "--fog-disable" ) {
602         fog = FG_FOG_DISABLED;  
603     } else if ( arg == "--fog-fastest" ) {
604         fog = FG_FOG_FASTEST;   
605     } else if ( arg == "--fog-nicest" ) {
606         fog = FG_FOG_NICEST;    
607     } else if ( arg.find( "--fov=" ) != string::npos ) {
608         fov = parse_fov( arg.substr(6) );
609     } else if ( arg == "--disable-fullscreen" ) {
610         fullscreen = false;     
611     } else if ( arg== "--enable-fullscreen") {
612         fullscreen = true;      
613     } else if ( arg == "--shading-flat") {
614         shading = 0;    
615     } else if ( arg == "--shading-smooth") {
616         shading = 1;    
617     } else if ( arg == "--disable-skyblend") {
618         skyblend = false;       
619     } else if ( arg== "--enable-skyblend" ) {
620         skyblend = true;        
621     } else if ( arg == "--disable-textures" ) {
622         textures = false;       
623     } else if ( arg == "--enable-textures" ) {
624         textures = true;
625     } else if ( arg == "--disable-wireframe" ) {
626         wireframe = false;      
627     } else if ( arg == "--enable-wireframe" ) {
628         wireframe = true;
629     } else if ( arg.find( "--geometry=" ) != string::npos ) {
630         string geometry = arg.substr( 11 );
631         if ( geometry == "640x480" ) {
632             xsize = 640;
633             ysize = 480;
634         } else if ( geometry == "800x600" ) {
635             xsize = 800;
636             ysize = 600;
637         } else if ( geometry == "1024x768" ) {
638             xsize = 1024;
639             ysize = 768;
640         } else {
641             FG_LOG( FG_GENERAL, FG_ALERT, "Unknown geometry: " << geometry );
642             exit(-1);
643         }
644     } else if ( arg == "--units-feet" ) {
645         units = FG_UNITS_FEET;  
646     } else if ( arg == "--units-meters" ) {
647         units = FG_UNITS_METERS;        
648     } else if ( arg.find( "--tile-radius=" ) != string::npos ) {
649         tile_radius = parse_tile_radius( arg.substr(14) );
650         tile_diameter = tile_radius * 2 + 1;
651     } else if ( arg.find( "--time-offset=" ) != string::npos ) {
652         time_offset = parse_time_offset( (arg.substr(14)) );
653     } else if (arg.find( "--start-date-gmt=") != string::npos ) {
654         start_gst = parse_date( (arg.substr(17)) );
655     } else if (arg.find( "--start-data-lst=") != string::npos ) {
656         start_lst = parse_date( (arg.substr(17)) );
657     } else if ( arg == "--hud-tris" ) {
658         tris_or_culled = 0;     
659     } else if ( arg == "--hud-culled" ) {
660         tris_or_culled = 1;
661     } else if ( arg.find( "--serial=" ) != string::npos ) {
662         parse_serial( arg.substr(9) );
663     } else {
664         FG_LOG( FG_GENERAL, FG_ALERT, "Unknown option '" << arg << "'" );
665         return FG_OPTIONS_ERROR;
666     }
667     
668     return FG_OPTIONS_OK;
669 }
670
671
672 // Parse the command line options
673 int fgOPTIONS::parse_command_line( int argc, char **argv ) {
674     int i = 1;
675     int result;
676
677     FG_LOG(FG_GENERAL, FG_INFO, "Processing command line arguments");
678
679     while ( i < argc ) {
680         FG_LOG( FG_GENERAL, FG_DEBUG, "argv[" << i << "] = " << argv[i] );
681
682         result = parse_option(argv[i]);
683         if ( (result == FG_OPTIONS_HELP) || (result == FG_OPTIONS_ERROR) ) {
684             return(result);
685         }
686
687         i++;
688     }
689     
690     return(FG_OPTIONS_OK);
691 }
692
693
694 // Parse config file options
695 int fgOPTIONS::parse_config_file( const string& path ) {
696     fg_gzifstream in( path );
697     if ( !in )
698         return(FG_OPTIONS_ERROR);
699
700     FG_LOG( FG_GENERAL, FG_INFO, "Processing config file: " << path );
701
702     in >> skipcomment;
703     while ( !in.eof() ) {
704         string line;
705
706 #ifdef GETLINE_NEEDS_TERMINATOR
707         getline( in, line, '\n' );
708 #else
709         getline( in, line );
710 #endif
711
712         if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
713             FG_LOG( FG_GENERAL, FG_ALERT, 
714                     "Config file parse error: " << path << " '" 
715                     << line << "'" );
716             exit(-1);
717         }
718         in >> skipcomment;
719     }
720
721     return FG_OPTIONS_OK;
722 }
723
724
725 // Print usage message
726 void fgOPTIONS::usage ( void ) {
727     printf("Usage: fg [ options ... ]\n");
728     printf("\n");
729
730     printf("General Options:\n");
731     printf("\t--help -h:  print usage\n");
732     printf("\t--fg-root=path:  specify the root path for all the data files\n");
733     printf("\t--disable-game-mode:  disable full-screen game mode\n");
734     printf("\t--enable-game-mode:  enable full-screen game mode\n");
735     printf("\t--disable-splash-screen:  disable splash screen\n");
736     printf("\t--enable-splash-screen:  enable splash screen\n");
737     printf("\t--disable-intro-music:  disable introduction music\n");
738     printf("\t--enable-intro-music:  enable introduction music\n");
739     printf("\t--disable-mouse-pointer:  disable extra mouse pointer\n");
740     printf("\t--enable-mouse-pointer:  enable extra mouse pointer (i.e. for\n");
741     printf("\t\tfull screen voodoo/voodoo-II based cards.)\n");
742     printf("\t--disable-pause:  start out in an active state\n");
743     printf("\t--enable-pause:  start out in a paused state\n");
744     printf("\n");
745
746     printf("Features:\n");
747     printf("\t--disable-hud:  disable heads up display\n");
748     printf("\t--enable-hud:  enable heads up display\n");
749     printf("\t--disable-panel:  disable instrument panel\n");
750     printf("\t--enable-panel:  enable instrumetn panel\n");
751     printf("\t--disable-sound:  disable sound effects\n");
752     printf("\t--enable-sound:  enable sound effects\n");
753     printf("\n");
754  
755     printf("Flight Model:\n");
756     printf("\t--fdm=abcd:  one of slew, jsb, larcsim, or external\n");
757     printf("\n");
758
759     printf("Initial Position and Orientation:\n");
760     printf("\t--airport-id=ABCD:  specify starting postion by airport id\n");
761     printf("\t--lon=degrees:  starting longitude in degrees (west = -)\n");
762     printf("\t--lat=degrees:  starting latitude in degrees (south = -)\n");
763     printf("\t--altitude=feet:  starting altitude in feet\n");
764     printf("\t\t(unless --units-meters specified\n");
765     printf("\t--heading=degrees:  heading (yaw) angle in degress (Psi)\n");
766     printf("\t--roll=degrees:  roll angle in degrees (Phi)\n");
767     printf("\t--pitch=degrees:  pitch angle in degrees (Theta)\n");
768     printf("\n");
769
770     printf("Rendering Options:\n");
771     printf("\t--fog-disable:  disable fog/haze\n");
772     printf("\t--fog-fastest:  enable fastest fog/haze\n");
773     printf("\t--fog-nicest:  enable nicest fog/haze\n");
774     printf("\t--fov=xx.x:  specify initial field of view angle in degrees\n");
775     printf("\t--disable-fullscreen:  disable fullscreen mode\n");
776     printf("\t--enable-fullscreen:  enable fullscreen mode\n");
777     printf("\t--shading-flat:  enable flat shading\n");
778     printf("\t--shading-smooth:  enable smooth shading\n");
779     printf("\t--disable-skyblend:  disable sky blending\n");
780     printf("\t--enable-skyblend:  enable sky blending\n");
781     printf("\t--disable-textures:  disable textures\n");
782     printf("\t--enable-textures:  enable textures\n");
783     printf("\t--disable-wireframe:  disable wireframe drawing mode\n");
784     printf("\t--enable-wireframe:  enable wireframe drawing mode\n");
785     printf("\t--geometry=WWWxHHH:  window geometry: 640x480, 800x600, etc.\n");
786     printf("\n");
787
788     printf("Scenery Options:\n");
789     printf("\t--tile-radius=n:  specify tile radius, must be 1 - 4\n");
790     printf("\n");
791
792     printf("Hud Options:\n");
793     printf("\t--units-feet:  Hud displays units in feet\n");
794     printf("\t--units-meters:  Hud displays units in meters\n");
795     printf("\t--hud-tris:  Hud displays number of triangles rendered\n");
796     printf("\t--hud-culled:  Hud displays percentage of triangles culled\n");
797     printf("\n");
798         
799     printf("Time Options:\n");
800     printf("\t--time-offset=[+-]hh:mm:ss:  offset local time by this amount\n");
801     printf("\t--start-date-gmt=yyyy:mm:dd:hh:mm:ss: specify a starting date/time. Time is Greenwich Mean Time\n");
802     printf("\t--start-date-lst=yyyy:mm:dd:hh:mm:ss: specify a starting date/time. Uses local sidereal time\n");
803 }
804
805
806 // Destructor
807 fgOPTIONS::~fgOPTIONS( void ) {
808 }
809
810