]> git.mxchange.org Git - flightgear.git/blob - src/Main/options.cxx
286776c7169062b06215f1ad69a985aef722766a
[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     net_id = "";
205
206     // initialize port config string list
207     port_options_list.erase ( port_options_list.begin(), 
208                               port_options_list.end() );
209 }
210
211 void 
212 fgOPTIONS::toggle_panel() {
213     
214     FGTime *t = FGTime::cur_time_params;
215     
216     int toggle_pause = t->getPause();
217     
218     if( !toggle_pause )
219         t->togglePauseMode();
220     
221     if( panel_status ) {
222         panel_status = false;
223     } else {
224         panel_status = true;
225     }
226     if ( panel_status ) {
227         if( FGPanel::OurPanel == 0)
228             new FGPanel;
229         fov *= 0.4232;
230     } else {
231         fov *= (1.0 / 0.4232);
232     }
233     fgReshape( xsize, ysize);
234     
235     if( !toggle_pause )
236         t->togglePauseMode();
237 }
238
239 double
240 fgOPTIONS::parse_time(const string& time_in) {
241     char *time_str, num[256];
242     double hours, minutes, seconds;
243     double result = 0.0;
244     int sign = 1;
245     int i;
246
247     time_str = (char *)time_in.c_str();
248
249     // printf("parse_time(): %s\n", time_str);
250
251     // check for sign
252     if ( strlen(time_str) ) {
253         if ( time_str[0] == '+' ) {
254             sign = 1;
255             time_str++;
256         } else if ( time_str[0] == '-' ) {
257             sign = -1;
258             time_str++;
259         }
260     }
261     // printf("sign = %d\n", sign);
262
263     // get hours
264     if ( strlen(time_str) ) {
265         i = 0;
266         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
267             num[i] = time_str[0];
268             time_str++;
269             i++;
270         }
271         if ( time_str[0] == ':' ) {
272             time_str++;
273         }
274         num[i] = '\0';
275         hours = atof(num);
276         // printf("hours = %.2lf\n", hours);
277
278         result += hours;
279     }
280
281     // get minutes
282     if ( strlen(time_str) ) {
283         i = 0;
284         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
285             num[i] = time_str[0];
286             time_str++;
287             i++;
288         }
289         if ( time_str[0] == ':' ) {
290             time_str++;
291         }
292         num[i] = '\0';
293         minutes = atof(num);
294         // printf("minutes = %.2lf\n", minutes);
295
296         result += minutes / 60.0;
297     }
298
299     // get seconds
300     if ( strlen(time_str) ) {
301         i = 0;
302         while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
303             num[i] = time_str[0];
304             time_str++;
305             i++;
306         }
307         num[i] = '\0';
308         seconds = atof(num);
309         // printf("seconds = %.2lf\n", seconds);
310
311         result += seconds / 3600.0;
312     }
313
314     return(sign * result);
315 }
316
317
318 long int fgOPTIONS::parse_date( const string& date)
319 {
320     struct tm gmt;
321     char * date_str, num[256];
322     int i;
323     // initialize to zero
324     gmt.tm_sec = 0;
325     gmt.tm_min = 0;
326     gmt.tm_hour = 0;
327     gmt.tm_mday = 0;
328     gmt.tm_mon = 0;
329     gmt.tm_year = 0;
330     gmt.tm_isdst = 0; // ignore daylight savingtime for the moment
331     date_str = (char *)date.c_str();
332     // get year
333     if ( strlen(date_str) ) {
334         i = 0;
335         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
336             num[i] = date_str[0];
337             date_str++;
338             i++;
339         }
340         if ( date_str[0] == ':' ) {
341             date_str++;
342         }
343         num[i] = '\0';
344         gmt.tm_year = atoi(num) - 1900;
345     }
346     // get month
347     if ( strlen(date_str) ) {
348         i = 0;
349         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
350             num[i] = date_str[0];
351             date_str++;
352             i++;
353         }
354         if ( date_str[0] == ':' ) {
355             date_str++;
356         }
357         num[i] = '\0';
358         gmt.tm_mon = atoi(num) -1;
359     }
360     // get day
361     if ( strlen(date_str) ) {
362         i = 0;
363         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
364             num[i] = date_str[0];
365             date_str++;
366             i++;
367         }
368         if ( date_str[0] == ':' ) {
369             date_str++;
370         }
371         num[i] = '\0';
372         gmt.tm_mday = atoi(num);
373     }
374     // get hour
375     if ( strlen(date_str) ) {
376         i = 0;
377         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
378             num[i] = date_str[0];
379             date_str++;
380             i++;
381         }
382         if ( date_str[0] == ':' ) {
383             date_str++;
384         }
385         num[i] = '\0';
386         gmt.tm_hour = atoi(num);
387     }
388     // get minute
389     if ( strlen(date_str) ) {
390         i = 0;
391         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
392             num[i] = date_str[0];
393             date_str++;
394             i++;
395         }
396         if ( date_str[0] == ':' ) {
397             date_str++;
398         }
399         num[i] = '\0';
400         gmt.tm_min = atoi(num);
401     }
402     // get second
403     if ( strlen(date_str) ) {
404         i = 0;
405         while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
406             num[i] = date_str[0];
407             date_str++;
408             i++;
409         }
410         if ( date_str[0] == ':' ) {
411             date_str++;
412         }
413         num[i] = '\0';
414         gmt.tm_sec = atoi(num);
415     }
416     time_t theTime = FGTime::cur_time_params->get_gmt(gmt.tm_year,
417                                                       gmt.tm_mon,
418                                                       gmt.tm_mday,
419                                                       gmt.tm_hour,
420                                                       gmt.tm_min,
421                                                       gmt.tm_sec);
422     //printf ("Date is %s\n", ctime(&theTime));
423     //printf ("in seconds that is %d\n", theTime);
424     //exit(1);
425     return (theTime);
426 }
427
428
429 // parse degree in the form of [+/-]hhh:mm:ss
430 double
431 fgOPTIONS::parse_degree( const string& degree_str) {
432     double result = parse_time( degree_str );
433
434     // printf("Degree = %.4f\n", result);
435
436     return(result);
437 }
438
439
440 // parse time offset command line option
441 int
442 fgOPTIONS::parse_time_offset( const string& time_str) {
443     int result;
444
445     // printf("time offset = %s\n", time_str);
446
447 #ifdef HAVE_RINT
448     result = (int)rint(parse_time(time_str) * 3600.0);
449 #else
450     result = (int)(parse_time(time_str) * 3600.0);
451 #endif
452
453     // printf("parse_time_offset(): %d\n", result);
454
455     return( result );
456 }
457
458
459 // Parse --tile-diameter=n type option 
460
461 int
462 fgOPTIONS::parse_tile_radius( const string& arg ) {
463     int radius = atoi( arg );
464
465     if ( radius < FG_RADIUS_MIN ) { radius = FG_RADIUS_MIN; }
466     if ( radius > FG_RADIUS_MAX ) { radius = FG_RADIUS_MAX; }
467
468     // printf("parse_tile_radius(): radius = %d\n", radius);
469
470     return(radius);
471 }
472
473
474 // Parse --fdm=abcdefg type option 
475 int
476 fgOPTIONS::parse_fdm( const string& fm ) {
477     // printf("fdm = %s\n", fm);
478
479     if ( fm == "slew" ) {
480         return FGInterface::FG_SLEW;
481     } else if ( fm == "jsb" ) {
482         return FGInterface::FG_JSBSIM;
483     } else if ( (fm == "larcsim") || (fm == "LaRCsim") ) {
484         return FGInterface::FG_LARCSIM;
485     } else if ( fm == "external" ) {
486         return FGInterface::FG_EXTERNAL;
487     } else {
488         FG_LOG( FG_GENERAL, FG_ALERT, "Unknown fdm = " << fm );
489         exit(-1);
490     }
491
492     // we'll never get here, but it makes the compiler happy.
493     return -1;
494 }
495
496
497 // Parse --fov=x.xx type option 
498 double
499 fgOPTIONS::parse_fov( const string& arg ) {
500     double fov = atof(arg);
501
502     if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
503     if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
504
505     // printf("parse_fov(): result = %.4f\n", fov);
506
507     return(fov);
508 }
509
510
511 // Parse serial port option --serial=/dev/ttyS1,nmea,4800,out
512 //
513 // Format is "--serial=device,format,baud,direction" where
514 // 
515 //  device = OS device name to be open()'ed
516 //  format = {nmea, garmin,fgfs,rul}
517 //  baud = {300, 1200, 2400, ..., 230400}
518 //  direction = {in, out, bi}
519
520 bool 
521 fgOPTIONS::parse_serial( const string& serial_str ) {
522     string::size_type pos;
523
524     // cout << "Serial string = " << serial_str << endl;
525
526     // a flailing attempt to see if the port config string has a
527     // chance at being valid
528     pos = serial_str.find(",");
529     if ( pos == string::npos ) {
530         FG_LOG( FG_GENERAL, FG_ALERT, 
531                 "Malformed serial port configure string" );
532         return false;
533     }
534     
535     port_options_list.push_back( serial_str );
536
537     return true;
538 }
539
540
541 // Parse a single option
542 int fgOPTIONS::parse_option( const string& arg ) {
543     // General Options
544     if ( (arg == "--help") || (arg == "-h") ) {
545         // help/usage request
546         return(FG_OPTIONS_HELP);
547     } else if ( arg == "--disable-game-mode") {
548         game_mode = false;
549     } else if ( arg == "--enable-game-mode" ) {
550         game_mode = true;
551     } else if ( arg == "--disable-splash-screen" ) {
552         splash_screen = false;
553     } else if ( arg == "--enable-splash-screen" ) {
554         splash_screen = true;
555     } else if ( arg == "--disable-intro-music" ) {
556         intro_music = false;
557     } else if ( arg == "--enable-intro-music" ) {
558         intro_music = true;
559     } else if ( arg == "--disable-mouse-pointer" ) {
560         mouse_pointer = 1;
561     } else if ( arg == "--enable-mouse-pointer" ) {
562         mouse_pointer = 2;
563     } else if ( arg == "--disable-pause" ) {
564         pause = false;  
565     } else if ( arg == "--enable-pause" ) {
566         pause = true;   
567     } else if ( arg == "--disable-hud" ) {
568         hud_status = false;     
569     } else if ( arg == "--enable-hud" ) {
570         hud_status = true;      
571     } else if ( arg == "--disable-panel" ) {
572         panel_status = false;
573     } else if ( arg == "--enable-panel" ) {
574         panel_status = true;
575         fov *= 0.4232;
576     } else if ( arg == "--disable-sound" ) {
577         sound = false;
578     } else if ( arg == "--enable-sound" ) {
579         sound = true;
580     } else if ( arg.find( "--airport-id=") != string::npos ) {
581         airport_id = arg.substr( 13 );
582     } else if ( arg.find( "--lon=" ) != string::npos ) {
583         lon = parse_degree( arg.substr(6) );
584     } else if ( arg.find( "--lat=" ) != string::npos ) {
585         lat = parse_degree( arg.substr(6) );
586     } else if ( arg.find( "--altitude=" ) != string::npos ) {
587         if ( units == FG_UNITS_FEET ) {
588             altitude = atof( arg.substr(11) ) * FEET_TO_METER;
589         } else {
590             altitude = atof( arg.substr(11) );
591         }
592     } else if ( arg.find( "--heading=" ) != string::npos ) {
593         heading = atof( arg.substr(10) );
594     } else if ( arg.find( "--roll=" ) != string::npos ) {
595         roll = atof( arg.substr(7) );
596     } else if ( arg.find( "--pitch=" ) != string::npos ) {
597         pitch = atof( arg.substr(8) );
598     } else if ( arg.find( "--fg-root=" ) != string::npos ) {
599         fg_root = arg.substr( 10 );
600     } else if ( arg.find( "--fdm=" ) != string::npos ) {
601         flight_model = parse_fdm( arg.substr(6) );
602     } else if ( arg == "--fog-disable" ) {
603         fog = FG_FOG_DISABLED;  
604     } else if ( arg == "--fog-fastest" ) {
605         fog = FG_FOG_FASTEST;   
606     } else if ( arg == "--fog-nicest" ) {
607         fog = FG_FOG_NICEST;    
608     } else if ( arg.find( "--fov=" ) != string::npos ) {
609         fov = parse_fov( arg.substr(6) );
610     } else if ( arg == "--disable-fullscreen" ) {
611         fullscreen = false;     
612     } else if ( arg== "--enable-fullscreen") {
613         fullscreen = true;      
614     } else if ( arg == "--shading-flat") {
615         shading = 0;    
616     } else if ( arg == "--shading-smooth") {
617         shading = 1;    
618     } else if ( arg == "--disable-skyblend") {
619         skyblend = false;       
620     } else if ( arg== "--enable-skyblend" ) {
621         skyblend = true;        
622     } else if ( arg == "--disable-textures" ) {
623         textures = false;       
624     } else if ( arg == "--enable-textures" ) {
625         textures = true;
626     } else if ( arg == "--disable-wireframe" ) {
627         wireframe = false;      
628     } else if ( arg == "--enable-wireframe" ) {
629         wireframe = true;
630     } else if ( arg.find( "--geometry=" ) != string::npos ) {
631         string geometry = arg.substr( 11 );
632         if ( geometry == "640x480" ) {
633             xsize = 640;
634             ysize = 480;
635         } else if ( geometry == "800x600" ) {
636             xsize = 800;
637             ysize = 600;
638         } else if ( geometry == "1024x768" ) {
639             xsize = 1024;
640             ysize = 768;
641         } else {
642             FG_LOG( FG_GENERAL, FG_ALERT, "Unknown geometry: " << geometry );
643             exit(-1);
644         }
645     } else if ( arg == "--units-feet" ) {
646         units = FG_UNITS_FEET;  
647     } else if ( arg == "--units-meters" ) {
648         units = FG_UNITS_METERS;        
649     } else if ( arg.find( "--tile-radius=" ) != string::npos ) {
650         tile_radius = parse_tile_radius( arg.substr(14) );
651         tile_diameter = tile_radius * 2 + 1;
652     } else if ( arg.find( "--time-offset=" ) != string::npos ) {
653         time_offset = parse_time_offset( (arg.substr(14)) );
654     } else if (arg.find( "--start-date-gmt=") != string::npos ) {
655         start_gst = parse_date( (arg.substr(17)) );
656     } else if (arg.find( "--start-data-lst=") != string::npos ) {
657         start_lst = parse_date( (arg.substr(17)) );
658     } else if ( arg == "--hud-tris" ) {
659         tris_or_culled = 0;     
660     } else if ( arg == "--hud-culled" ) {
661         tris_or_culled = 1;
662     } else if ( arg.find( "--serial=" ) != string::npos ) {
663         parse_serial( arg.substr(9) );
664     } else {
665         FG_LOG( FG_GENERAL, FG_ALERT, "Unknown option '" << arg << "'" );
666         return FG_OPTIONS_ERROR;
667     }
668     
669     return FG_OPTIONS_OK;
670 }
671
672
673 // Parse the command line options
674 int fgOPTIONS::parse_command_line( int argc, char **argv ) {
675     int i = 1;
676     int result;
677
678     FG_LOG(FG_GENERAL, FG_INFO, "Processing command line arguments");
679
680     while ( i < argc ) {
681         FG_LOG( FG_GENERAL, FG_DEBUG, "argv[" << i << "] = " << argv[i] );
682
683         result = parse_option(argv[i]);
684         if ( (result == FG_OPTIONS_HELP) || (result == FG_OPTIONS_ERROR) ) {
685             return(result);
686         }
687
688         i++;
689     }
690     
691     return(FG_OPTIONS_OK);
692 }
693
694
695 // Parse config file options
696 int fgOPTIONS::parse_config_file( const string& path ) {
697     fg_gzifstream in( path );
698     if ( !in )
699         return(FG_OPTIONS_ERROR);
700
701     FG_LOG( FG_GENERAL, FG_INFO, "Processing config file: " << path );
702
703     in >> skipcomment;
704     while ( !in.eof() ) {
705         string line;
706
707 #ifdef GETLINE_NEEDS_TERMINATOR
708         getline( in, line, '\n' );
709 #else
710         getline( in, line );
711 #endif
712
713         if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
714             FG_LOG( FG_GENERAL, FG_ALERT, 
715                     "Config file parse error: " << path << " '" 
716                     << line << "'" );
717             exit(-1);
718         }
719         in >> skipcomment;
720     }
721
722     return FG_OPTIONS_OK;
723 }
724
725
726 // Print usage message
727 void fgOPTIONS::usage ( void ) {
728     printf("Usage: fg [ options ... ]\n");
729     printf("\n");
730
731     printf("General Options:\n");
732     printf("\t--help -h:  print usage\n");
733     printf("\t--fg-root=path:  specify the root path for all the data files\n");
734     printf("\t--disable-game-mode:  disable full-screen game mode\n");
735     printf("\t--enable-game-mode:  enable full-screen game mode\n");
736     printf("\t--disable-splash-screen:  disable splash screen\n");
737     printf("\t--enable-splash-screen:  enable splash screen\n");
738     printf("\t--disable-intro-music:  disable introduction music\n");
739     printf("\t--enable-intro-music:  enable introduction music\n");
740     printf("\t--disable-mouse-pointer:  disable extra mouse pointer\n");
741     printf("\t--enable-mouse-pointer:  enable extra mouse pointer (i.e. for\n");
742     printf("\t\tfull screen voodoo/voodoo-II based cards.)\n");
743     printf("\t--disable-pause:  start out in an active state\n");
744     printf("\t--enable-pause:  start out in a paused state\n");
745     printf("\n");
746
747     printf("Features:\n");
748     printf("\t--disable-hud:  disable heads up display\n");
749     printf("\t--enable-hud:  enable heads up display\n");
750     printf("\t--disable-panel:  disable instrument panel\n");
751     printf("\t--enable-panel:  enable instrumetn panel\n");
752     printf("\t--disable-sound:  disable sound effects\n");
753     printf("\t--enable-sound:  enable sound effects\n");
754     printf("\n");
755  
756     printf("Flight Model:\n");
757     printf("\t--fdm=abcd:  one of slew, jsb, larcsim, or external\n");
758     printf("\n");
759
760     printf("Initial Position and Orientation:\n");
761     printf("\t--airport-id=ABCD:  specify starting postion by airport id\n");
762     printf("\t--lon=degrees:  starting longitude in degrees (west = -)\n");
763     printf("\t--lat=degrees:  starting latitude in degrees (south = -)\n");
764     printf("\t--altitude=feet:  starting altitude in feet\n");
765     printf("\t\t(unless --units-meters specified\n");
766     printf("\t--heading=degrees:  heading (yaw) angle in degress (Psi)\n");
767     printf("\t--roll=degrees:  roll angle in degrees (Phi)\n");
768     printf("\t--pitch=degrees:  pitch angle in degrees (Theta)\n");
769     printf("\n");
770
771     printf("Rendering Options:\n");
772     printf("\t--fog-disable:  disable fog/haze\n");
773     printf("\t--fog-fastest:  enable fastest fog/haze\n");
774     printf("\t--fog-nicest:  enable nicest fog/haze\n");
775     printf("\t--fov=xx.x:  specify initial field of view angle in degrees\n");
776     printf("\t--disable-fullscreen:  disable fullscreen mode\n");
777     printf("\t--enable-fullscreen:  enable fullscreen mode\n");
778     printf("\t--shading-flat:  enable flat shading\n");
779     printf("\t--shading-smooth:  enable smooth shading\n");
780     printf("\t--disable-skyblend:  disable sky blending\n");
781     printf("\t--enable-skyblend:  enable sky blending\n");
782     printf("\t--disable-textures:  disable textures\n");
783     printf("\t--enable-textures:  enable textures\n");
784     printf("\t--disable-wireframe:  disable wireframe drawing mode\n");
785     printf("\t--enable-wireframe:  enable wireframe drawing mode\n");
786     printf("\t--geometry=WWWxHHH:  window geometry: 640x480, 800x600, etc.\n");
787     printf("\n");
788
789     printf("Scenery Options:\n");
790     printf("\t--tile-radius=n:  specify tile radius, must be 1 - 4\n");
791     printf("\n");
792
793     printf("Hud Options:\n");
794     printf("\t--units-feet:  Hud displays units in feet\n");
795     printf("\t--units-meters:  Hud displays units in meters\n");
796     printf("\t--hud-tris:  Hud displays number of triangles rendered\n");
797     printf("\t--hud-culled:  Hud displays percentage of triangles culled\n");
798     printf("\n");
799         
800     printf("Time Options:\n");
801     printf("\t--time-offset=[+-]hh:mm:ss:  offset local time by this amount\n");
802     printf("\t--start-date-gmt=yyyy:mm:dd:hh:mm:ss: specify a starting date/time. Time is Greenwich Mean Time\n");
803     printf("\t--start-date-lst=yyyy:mm:dd:hh:mm:ss: specify a starting date/time. Uses local sidereal time\n");
804 }
805
806
807 // Destructor
808 fgOPTIONS::~fgOPTIONS( void ) {
809 }
810
811