Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Main.cpp

Go to the documentation of this file.
00001 /*
00002  * Main.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2003 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00033 // Disable MSVC warnings for truncated debug names
00034 #ifdef _MSC_VER
00035 #pragma warning( disable : 4786 )
00036 #endif
00037 
00038 
00039 #include <math.h>
00040 #include <GL/glut.h>
00041 #include <plib/ssg.h>
00042 #include <plib/ssgAux.h>
00043 
00044 #include "../Ssg/ssgLocal.h"
00045 
00046 #include "../Include/FlyLegacy.h"
00047 #include "../Include/Globals.h"
00048 #include "../Include/Situation.h"
00049 #include "../Include/KeyMap.h"
00050 #include "../Include/Ui.h"
00051 #include "../Include/Database.h"
00052 #include "../Include/Utility.h"
00053 #include "../Include/LogFile.h"
00054 #include "../Include/Pod.h"
00055 
00056 
00057 // General-purpose global settings
00058 SGlobals *globals = NULL;
00059 
00060 //
00061 // GLUT idle function
00062 //
00063 #ifdef _WIN32
00064 static BYTE savedkeys[256];
00065 
00066 typedef struct {
00067   BYTE          vk;
00068   EKeyboardKeys key;
00069 } SNonGlutKey;
00070 
00071 SNonGlutKey nonGlutKeys[] =
00072 {
00073   { VK_CAPITAL, KB_KEY_CAPSLOCK },
00074   { VK_NUMLOCK, KB_KEY_NUMLOCK },
00075   { VK_SCROLL,  KB_KEY_SCROLLLOCK },
00076   { VK_SUBTRACT,  KB_KEY_KEYPAD_MINUS },
00077   { VK_CLEAR,   KB_KEY_CENTER },
00078   { VK_ADD,   KB_KEY_KEYPAD_PLUS },
00079   { VK_RETURN,  KB_KEY_KEYPAD_ENTER },
00080   { VK_DIVIDE,  KB_KEY_KEYPAD_SLASH },
00081 };
00082 #endif
00083 
00084 #ifdef _WIN32
00085 //
00086 // Array for storage of gamma ramp data
00087 //
00088 static WORD savedGammaRamp[3][0x100];
00089 static HDC  hdc = 0;
00090 #endif // _WIN32
00091 
00092 // Forward declare GLUT callback functions
00093 static void idle (void);
00094 static void reshape (int w, int h);
00095 static void motion (int x, int y);
00096 static void passive_motion (int x, int y);
00097 static void mouse (int button, int updown, int x, int y);
00098 static void keyboard (unsigned char key, int x, int y);
00099 static void special (int key, int x, int y);
00100 static void redraw (void);
00101 
00102 //
00103 // Initialize OpenGL, GLUT, PLIB graphics libraries, etc.
00104 //   Code in this function may be dependent on INI settings and globals
00105 //
00106 static void InitGraphics ()
00107 {
00108   int   fake_argc = 1 ;
00109   char *fake_argv[3] ;
00110   fake_argv[0] = "Fly! Legacy";
00111   fake_argv[1] = "Fly! Legacy";
00112   fake_argv[2] = NULL ;
00113 
00114   // Get screen resolution from globals
00115   int w = globals->screenWidth;
00116   int h = globals->screenHeight;
00117   int bpp = globals->screenDepth;
00118   int refresh = globals->screenRefresh;
00119 
00120   // Get fullscreen mode from INI settings
00121   int autoFullScreen = 0;
00122   GetIniVar ("Graphics", "autoFullScreen", &autoFullScreen);
00123 
00124   // Initialise GLUT
00125   glutInit               ( &fake_argc, fake_argv ) ;
00126   glutInitDisplayMode    ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;
00127   if (autoFullScreen) {
00128     char game[64];
00129     sprintf (game, "%dx%d:%d@%d", w, h, bpp, refresh);
00130     glutGameModeString (game);
00131     glutEnterGameMode ();
00132   } else {
00133     glutInitWindowPosition ( 0, 0 ) ;
00134     glutInitWindowSize     ( w, h ) ;
00135     glutCreateWindow       ( fake_argv[1] ) ;
00136   }
00137   glutIdleFunc (idle);
00138   glutMouseFunc (mouse);
00139   glutMotionFunc (motion);
00140   glutPassiveMotionFunc (passive_motion);
00141   glutDisplayFunc (redraw);
00142   glutReshapeFunc (reshape);
00143   glutKeyboardFunc (keyboard);
00144   glutSpecialFunc (special);
00145 
00146   // Miscellaneous one-time GL setup
00147   glClearColor ( 0, 0, 0, 1.0f ) ;
00148 
00149 #ifdef _WIN32
00150   // Get display gamma value from graphics INI settings
00151   float gamma = 1.0f;
00152   GetIniFloat ("Graphics", "displayGamma", &gamma);
00153 
00154   // Get current gamma ramp to be restored at exit
00155   hdc = wglGetCurrentDC ();
00156   if (!GetDeviceGammaRamp (hdc, savedGammaRamp)) {
00157     WARNINGLOG ("Failed to get Win32 gamma ramp");
00158   }
00159 
00160   // Calculate gamma ramp table
00161   float invgamma = 1.0f / gamma;
00162   WORD ramp[3][0x100];
00163   for (int i=0; i<0x100; i++) {
00164     float factor = pow((float)i / 256.0f, invgamma);
00165     if (factor > 1.0f) factor = 1.0f;
00166     WORD value = (WORD)((factor * 65535.0f) + 0.5f);
00167     ramp[0][i] = value;
00168     ramp[1][i] = value;
00169     ramp[2][i] = value;
00170   }
00171 
00172   // Set the new gamma ramp
00173   if (!SetDeviceGammaRamp (hdc, ramp)) {
00174     WARNINGLOG ("Failed to set Win32 gamma ramp");
00175   }
00176 #endif // _WIN32
00177 
00178   // Disable GLUT cursor
00179   glutSetCursor (GLUT_CURSOR_NONE);
00180 
00181   // Initialise SSG
00182 
00184   char *mark1 = new char[32];
00185   strcpy (mark1, "ssgInit Start");
00186   ssgInit ();
00187   char *mark2 = new char[32];
00188   strcpy (mark2, "ssgInit End");
00189 
00190   globals->context = new ssgContext;
00191   ssgSetNearFar (1.0, 1.0E20); 
00192 }
00193 
00194 void InitFonts (void)
00195 {
00197   char *mark1 = new char[32];
00198   strcpy (mark1, "ftascm10 Start");
00199   strcpy (globals->fonts.ftascm10.fontName, "ART\\FTASCM10.RAW");
00200   LoadFont (&globals->fonts.ftascm10);
00201   char *mark2 = new char[32];
00202   strcpy (mark2, "ftascm10 End");
00203   strcpy (globals->fonts.ftdigi9.fontName, "ART\\FTDIGI9.RAW");
00204   LoadFont (&globals->fonts.ftdigi9);
00205   strcpy (globals->fonts.ftdigi9b.fontName, "ART\\FTDIGI9B.RAW");
00206   LoadFont (&globals->fonts.ftdigi9b);
00207   strcpy (globals->fonts.ftdigi9d.fontName, "ART\\FTDIGI9D.RAW");
00208   LoadFont (&globals->fonts.ftdigi9d);
00209   strcpy (globals->fonts.ftdigi13.fontName, "ART\\FTDIGI13.RAW");
00210   LoadFont (&globals->fonts.ftdigi13);
00211   strcpy (globals->fonts.ftmicro5.fontName, "ART\\FTMICRO5.RAW");
00212   LoadFont (&globals->fonts.ftmicro5);
00213   strcpy (globals->fonts.ftmno14b.fontName, "ART\\FTMNO14B.RAW");
00214   LoadFont (&globals->fonts.ftmno14b);
00215   strcpy (globals->fonts.ftmono12.fontName, "ART\\FTMONO12.RAW");
00216   LoadFont (&globals->fonts.ftmono12);
00217   strcpy (globals->fonts.ftsmal10.fontName, "ART\\FTSMAL10.RAW");
00218   LoadFont (&globals->fonts.ftsmal10);
00219   strcpy (globals->fonts.ftthin24.fontName, "ART\\FTTHIN24.RAW");
00220   LoadFont (&globals->fonts.ftthin24);
00221   strcpy (globals->fonts.fttiny7.fontName, "ART\\FTTINY7.RAW");
00222   LoadFont (&globals->fonts.fttiny7);
00223   strcpy (globals->fonts.ftasci10.fontName, "ART\\FTASCI10.RAW");
00224   LoadFont (&globals->fonts.ftasci10);
00225 
00234 /*
00235   strcpy (globals->fonts.ftnorm14.fontName, "ART\\FTNORM14.RAW");
00236   LoadFont (&globals->fonts.ftnorm14);
00237   strcpy (globals->fonts.ftnorm28.fontName, "ART\\FTNORM28.RAW");
00238   LoadFont (&globals->fonts.ftnorm28);
00239   strcpy (globals->fonts.fttiny7w.fontName, "ART\\FTTINY7W.RAW");
00240   LoadFont (&globals->fonts.fttiny7w);
00241   strcpy (globals->fonts.ftdos12.fontName, "ART\\FTDOS12.RAW");
00242   LoadFont (&globals->fonts.ftdos12);
00243 */
00244 }
00245 
00246 void cleanup_fonts (void)
00247 {
00248   FreeFont (&globals->fonts.ftascm10);
00249   FreeFont (&globals->fonts.ftdigi9);
00250   FreeFont (&globals->fonts.ftdigi9b);
00251   FreeFont (&globals->fonts.ftdigi9d);
00252   FreeFont (&globals->fonts.ftdigi13);
00253   FreeFont (&globals->fonts.ftmicro5);
00254   FreeFont (&globals->fonts.ftmno14b);
00255   FreeFont (&globals->fonts.ftmono12);
00256   FreeFont (&globals->fonts.ftsmal10);
00257   FreeFont (&globals->fonts.ftthin24);
00258   FreeFont (&globals->fonts.fttiny7);
00259   FreeFont (&globals->fonts.ftasci10);
00260 //  FreeFont (&globals->fonts.ftnorm14);
00261 //  FreeFont (&globals->fonts.ftnorm28);
00262 //  FreeFont (&globals->fonts.fttiny7w);
00263 //  FreeFont (&globals->fonts.ftdos12);
00264 }
00265 
00266 
00268 CDatabase*   dbAirport;
00269 CDatabase*   dbAtsRoute;
00270 CDatabase*   dbComm;
00271 CDatabase*   dbCountry;
00272 CDatabase*   dbState;
00273 CDatabase*   dbIls;
00274 CDatabase*   dbNavaid;
00275 CDatabase*   dbObstruct;
00276 CDatabase*   dbRunway;
00277 CDatabase*   dbWaypoint;
00278 
00279 //
00280 // Initialize databases
00281 //   Code in this function may be dependent on INI settings and POD filesystem
00282 //
00283 void LoadDatabases (void)
00284 {
00285   // Load Airport database
00286   dbAirport = new CDatabase ("Airport.dbt");
00287   dbAirport->Mount ("Airport.dbd");
00288   dbAirport->AddIndex ("Airport.dbi");
00289   dbAirport->AddIndex ("AprtCtry.dbi");
00290   dbAirport->AddIndex ("AprtStat.dbi");
00291   dbAirport->AddIndex ("AprtFaa.dbi");
00292   dbAirport->AddIndex ("AprtIcao.dbi");
00293   dbAirport->AddIndex ("AprtGlob.dbi");
00294   dbAirport->AddIndex ("AprtName.dbi");
00295 
00296   // Load ATS (Air Traffic System) Routing database
00297   dbAtsRoute = new CDatabase ("AtsRoute.dbt");
00298   dbAtsRoute->Mount ("AtsRoute.dbd");
00299 
00300   // Load Comm facility database
00301   dbComm = new CDatabase ("Comm.dbt");
00302   dbComm->Mount ("Comm.dbd");
00303   dbComm->AddIndex ("Comm.dbi");
00304   dbComm->AddIndex ("CommGlob.dbi");
00305   
00306   // Load Country name database
00307   dbCountry = new CDatabase ("Country.dbt");
00308   dbCountry->Mount ("Country.dbd");
00309   dbCountry->AddIndex ("Country.dbi");
00310   dbCountry->AddIndex ("CtryName.dbi");
00311 
00312   // Load State name database
00313   dbState = new CDatabase ("State.dbt");
00314   dbState->Mount ("State.dbd");
00315   dbState->AddIndex ("Statctry.dbi");
00316   dbState->AddIndex ("State.dbi");
00317   dbState->AddIndex ("StatName.dbi");
00318 
00319   // Load ILS Facility database
00320   dbIls = new CDatabase ("Ils.dbt");
00321   dbIls->Mount ("Ils.dbd");
00322   dbIls->AddIndex ("Ils.dbi");
00323   dbIls->AddIndex ("IlsGlob.dbi");
00324   dbIls->AddIndex ("IlsLocal.dbi");
00325 
00326   // Load Navaid database
00327   dbNavaid = new CDatabase ("Navaid.dbt");
00328   dbNavaid->Mount ("Navaid.dbd");
00329   dbNavaid->AddIndex ("Navaid.dbi");
00330   dbNavaid->AddIndex ("NavNdbId.dbi");
00331   dbNavaid->AddIndex ("NavNdbNm.dbi");
00332   dbNavaid->AddIndex ("NavVorId.dbi");
00333   dbNavaid->AddIndex ("NavVorNm.dbi");
00334 
00335   // Load Obstruction database
00336   dbObstruct = new CDatabase ("Obstruct.dbt");
00337   dbObstruct->Mount ("Obstruct.dbd");
00338   dbObstruct->AddIndex ("ObstGlob.dbi");
00339 
00340   // Load Runway database
00341   dbRunway = new CDatabase ("Runway.dbt");
00342   dbRunway->Mount ("Runway.dbd");
00343   dbRunway->AddIndex ("Runway.dbi");
00344 
00345   // Load Waypoint database
00346   dbWaypoint = new CDatabase ("Waypoint.dbt");
00347   dbWaypoint->Mount ("Waypoint.dbd");
00348   dbWaypoint->AddIndex ("Waypoint.dbi");
00349   dbWaypoint->AddIndex ("WayKey.dbi");
00350 }
00351 
00352 void UnloadDatabases (void)
00353 {
00354   delete dbAirport;
00355   delete dbAtsRoute;
00356   delete dbComm;
00357   delete dbCountry;
00358   delete dbState;
00359   delete dbIls;
00360   delete dbNavaid;
00361   delete dbObstruct;
00362   delete dbRunway;
00363   delete dbWaypoint;
00364 }
00365 
00366 //
00367 // Initialize global variable structure.
00368 //   Code in this function may be dependent on INI settings.
00369 //   Code in this function may not be dependent on POD filesystem
00370 //
00371 static void InitGlobalsNoPodFilesystem (void)
00372 {
00373   bool iniChanged = false;
00374 
00375   globals = new SGlobals;
00376 
00377   // Log files
00378   globals->logDebug = new CLogFile ("Logs\\Debug.log", "w");
00379   globals->logWarning = new CLogFile ("Logs\\Warning.log", "w");
00380 
00381   //
00382   // Screen resolution/colour depth
00383   //
00384 
00385   // Get screen resolution/depth
00386   int w = 1024;
00387   GetIniVar ("Graphics", "gamePIXX", &w);
00388 
00389   int h = 768;
00390   GetIniVar ("Graphics", "gamePIXY", &h);
00391 
00392   // Validate screen width/height
00393   bool screen640 = (w == 640) && (h == 480);
00394   bool screen800 = (w == 800) && (h == 600);
00395   bool screen1024 = (w == 1024) && (h == 768);
00396   if (!(screen640 || screen800 || screen1024)) {
00397     // Default to 1024 x 768
00398     if (globals->logWarning) globals->logWarning->Write ("Invalid screen resolution in INI settings, default to 1024x768");
00399     w = 1024;
00400     h = 768;
00401     SetIniVar ("Graphics", "gamePIXX", w);
00402     SetIniVar ("Graphics", "gamePIXY", h);
00403     iniChanged = true;
00404   }
00405 
00406   // Get colour depth from globals and validate
00407   int bpp = 32;
00408   GetIniVar ("Graphics", "gameBitsPerPixel", &bpp);
00409   if ((bpp != 16) && (bpp != 32)) {
00410     // Default to 32
00411     if (globals->logWarning) globals->logWarning->Write ("Invalid screen colour depth in INI settings, default to 32bpp");
00412     bpp = 32;
00413     SetIniVar ("Graphics", "gameBitsPerPixel", bpp);
00414     iniChanged = true;
00415   }
00416 
00417   // Get refresh rate
00418   int refresh = 0;
00419   GetIniVar ("Graphics", "gameRefreshRate", &refresh);
00420 
00421   // Store screen settings in global variables
00422   globals->screenWidth = w;
00423   globals->screenHeight = h;
00424   globals->screenDepth = bpp;
00425   globals->screenRefresh = refresh;
00426 
00427   //
00428   // Panel scrolling parameters
00429   //
00430   int i = -1;
00431   GetIniVar ("Cockpit", "mouseScrollingEnabled", &i);
00432   if (i == -1) {
00433     // Parameter was not set
00434     i = 1;
00435     SetIniVar ("Cockpit", "mouseScrollingEnabled", i);
00436     iniChanged = true;
00437   }
00438   globals->mouseScrollingEnabled = (i != 0);
00439 
00440   // Panel scroll step
00441   i = -1;
00442   GetIniVar ("Cockpit", "panelScrollStep", &i);
00443   if (i == -1) {
00444     // Parameter was not set
00445     i = 10;
00446     SetIniVar ("Cockpit", "panelScrollStep", i);
00447     iniChanged = true;
00448   }
00449   globals->panelScrollStep = i;
00450 
00451   // Panel creep (mouse scroll) step
00452   i = -1;
00453   GetIniVar ("Cockpit", "panelCreepStep", &i);
00454   if (i == -1) {
00455     // Parameter was not set
00456     i = 10;
00457     SetIniVar ("Cockpit", "panelCreepStep", i);
00458     iniChanged = true;
00459   }
00460   globals->panelCreepStep = i;
00461 
00462   // Global settings
00463   globals->settings = new SGlobalSettings;
00464 
00465   // Render sky dome in wireframe mode
00466   i = -1;
00467   GetIniVar ("Graphics", "skydomeWireframe", &i);
00468   if (i == -1) {
00469     // Parameter was not set, assign default
00470     i = 0;
00471     SetIniVar ("Graphics", "skydomeWireframe", i);
00472     iniChanged = true;
00473   }
00474   globals->settings->skydomeWireframe = (i != 0);
00475 
00476   // Render terrain in wireframe mode
00477   i = -1;
00478   GetIniVar ("Graphics", "terrainWireframe", &i);
00479   if (i == -1) {
00480     // Parameter was not set, assign default
00481     i = 0;
00482     SetIniVar ("Graphics", "terrainWireframe", i);
00483     iniChanged = true;
00484   }
00485   globals->settings->terrainWireframe = (i != 0);
00486 
00487   // Render aircraft in wireframe mode
00488   i = -1;
00489   GetIniVar ("Graphics", "aircraftWireframe", &i);
00490   if (i == -1) {
00491     // Parameter was not set, assign default
00492     i = 0;
00493     SetIniVar ("Graphics", "aircraftWireframe", i);
00494     iniChanged = true;
00495   }
00496   globals->settings->aircraftWireframe = (i != 0);
00497 
00498   // Display terrain in relief-shaded mode instead of textured
00499   i = -1;
00500   GetIniVar ("Graphics", "terrainReliefShaded", &i);
00501   if (i == -1) {
00502     // Parameter was not set, assign default
00503     i = 0;
00504     SetIniVar ("Graphics", "terrainReliefShaded", i);
00505     iniChanged = true;
00506   }
00507   globals->settings->terrainReliefShaded = (i != 0);
00508 
00509   // Save INI settings if we have changed anything
00510   if (iniChanged) {
00511     SaveIniSettings ();
00512   }
00513 
00514   // Time Manager
00515   globals->timemgr = new CTimeManager;
00516   globals->timemgr->Prepare ();
00517   globals->timemgr->SetTimeScale (1.0);
00518 
00519   // Audio Manager
00520   globals->audiomgr = new CAudioManager;
00521   globals->audiomgr->Init ();
00522 
00523   // Cursor manager
00524   globals->cursormgr = new CCursorManager;
00525 
00526   // Slew manager
00527   globals->slewmgr = new CSlewManager;
00528 
00529   // Frame rate trackers
00530   globals->simRate = new CFrameRateTracker (200);
00531   globals->drawRate = new CFrameRateTracker (200);
00532 
00533   // Initialize various application object pointers
00534   globals->sit = NULL;
00535   globals->keymap = NULL;
00536   globals->terrainmgr = NULL;
00537   globals->skymgr = NULL;
00538   globals->fuimgr = NULL;
00539 }
00540 
00541 static void InitGlobalsWithPodFilesystem (void)
00542 {
00543   LoadDatabases ();
00544 
00545   // Terrain manager
00546   globals->terrainmgr = new CTerrainManager;
00547 
00548   // Sky manager
00549   globals->skymgr = new CSkyManager;
00550 
00551   // FUI (Fly! User Interface) manager
00552   globals->fuimgr = new CFuiManager;
00553   FILE *f = fopen ("Debug\\Fui.txt", "w");
00554   globals->fuimgr->Print (f);
00555   fclose (f);
00556 }
00557 
00558 
00559 //
00560 // Application cleanup/shutdown functions
00561 //
00562 void CleanupGlobals (void)
00563 {
00564   cleanup_ui ();
00565   cleanup_fonts();
00566 
00567   if (globals->settings != NULL)    delete globals->settings;
00568   if (globals->context != NULL)     delete globals->context;
00569   if (globals->sit != NULL)         delete globals->sit;
00570   if (globals->keymap != NULL)      delete globals->keymap;
00571   if (globals->timemgr != NULL)     delete globals->timemgr;
00572   if (globals->cursormgr != NULL)   delete globals->cursormgr;
00573   if (globals->audiomgr != NULL)    delete globals->audiomgr;
00574   if (globals->fuimgr != NULL)      delete globals->fuimgr;
00575   if (globals->terrainmgr != NULL)  delete globals->terrainmgr;
00576   if (globals->skymgr != NULL)      delete globals->skymgr;
00577   if (globals->slewmgr != NULL)     delete globals->slewmgr;
00578   if (globals->logDebug != NULL)    delete globals->logDebug;
00579   if (globals->logWarning != NULL)  delete globals->logWarning;
00580 
00581   // Clean up POD filesystems
00582   pshutdown (&globals->pfs);
00583 
00584   delete globals;
00585 }
00586 
00587 
00588 #if defined(_DEBUG) && defined(HAVE_CRTDBG_H)
00589 //
00590 // Define global for memory state debugging
00591 //
00592 _CrtMemState memoryState;
00593 #endif
00594 
00595 //
00596 // This function should be called prior to program exit in order to
00597 //   gracefully shut down, deallocate heap memory, close open files, etc.
00598 //
00599 void ShutdownAll (void)
00600 {
00601   // Unload all databases
00602   UnloadDatabases ();
00603 
00604   // Clean up INI settings database
00605   UnloadIniSettings ();
00606 
00607   // Clean up global variables
00608   CleanupGlobals ();
00609 
00610 #ifdef _WIN32
00611   // Restore saved gamma ramp
00612   if (!SetDeviceGammaRamp (hdc, savedGammaRamp)) {
00613     if (globals->logWarning) globals->logWarning->Write ("Failed to set Win32 gamma ramp");
00614   }
00615 #endif // _WIN32
00616 }
00617 
00618 
00619 static void idle (void)
00620 {
00621 #ifdef WIN32
00622   // PROTOTYPE : Windows keyboard handling.  GLUT keyboard events do not support
00623   //  all numeric keypad keys (e.g. 5, Enter, +, etc.) that are required.
00624   //  This prototype is temporary until a better workaround can be found.
00625   //  It may just be required to implement this in another thread and have
00626   //  keyboard events sent to the main thread.
00627 
00628   BYTE keys[256];
00629   GetKeyboardState(keys);
00630 
00631   // Update the key modifier state
00632   int flymod = KB_MODIFIER_NONE;
00633   bool shift = (keys[VK_SHIFT] & 0x80) != 0;
00634   if (shift) {
00635     flymod |= KB_MODIFIER_SHIFT;
00636   }
00637   bool ctrl = (keys[VK_CONTROL] & 0x80) != 0;
00638   if (ctrl) {
00639     flymod |= KB_MODIFIER_CTRL;
00640   }
00641   bool alt = (keys[VK_MENU] & 0x80) != 0;
00642   if (alt) {
00643     flymod |= KB_MODIFIER_ALT;
00644   }
00645 
00646   // Initialize table of key states on first call to this function
00647   static bool first = true;
00648   if (first) {
00649     // Initialize key state array on the first call to this function
00650     first = false;
00651     for (int i=0; i<256; i++) {
00652       savedkeys[i] = (keys[i] & 0x80) != 0;
00653     }
00654   }
00655 
00656   // Check for keys that are not supported by GLUT, and pass them to the sim
00657   //   on keydown events.
00658   int nKeys = sizeof(nonGlutKeys) / sizeof(SNonGlutKey);
00659   for (int i=0; i<nKeys; i++) {
00660     BYTE vk = nonGlutKeys[i].vk;
00661     if (keys[vk] & 0x80) {
00662       // Key is pressed; check if saved key state is pressed
00663       if (!savedkeys[vk]) {
00664         // Key state has changed from unpressed to pressed
00665         savedkeys[vk] = true;
00666         globals->keymap->KeyPress (nonGlutKeys[i].key, (EKeyboardModifiers)flymod);
00667       }
00668     } else {
00669       // Key is not pressed; clear saved key state
00670       savedkeys[vk] = false;
00671     }
00672   }
00673 #endif // WIN32
00674 }
00675 
00676 
00677 //
00678 // GLUT window reshape
00679 //
00680 static void reshape ( int w, int h )
00681 {
00682   glViewport ( 0, 0, w, h ) ;
00683 }
00684 
00685 
00686 //
00687 // GLUT mouse motion event
00688 //
00689 void motion ( int x, int y )
00690 {
00691   bool used = false;
00692 
00693   // Send mouse motion data to FUI
00694   if (globals->fuimgr) used = globals->fuimgr->MouseMove (x, y);
00695 
00696   if (!used) {
00697     // Send mouse motion data to PUI for potential processing
00698     puMouse (x, y);
00699 
00700     // Send mouse motion for camera manager for panel scrolling
00701     if (globals->sit) {
00702       CPanel *panl = globals->sit->GetCurrentPanel ();
00703       if (panl) {
00704         // Send mouse event to panel
00705         panl->MouseMotion (x, y);
00706       }
00707     }
00708   }
00709 
00710   // Send mouse motion to cursor manager
00711   if (globals->cursormgr) {
00712     globals->cursormgr->MouseMotion (x, y);
00713   }
00714 
00715   // Force screen redraw
00716   glutPostRedisplay () ;
00717 }
00718 
00719 
00720 //
00721 // GLUT passive mouse motion event
00722 //
00723 void passive_motion ( int x, int y )
00724 {
00725   bool used = false;
00726 
00727   // Send mouse motion data to FUI
00728   if (globals->fuimgr) used = globals->fuimgr->MouseMove (x, y);
00729 
00730   if (!used) {
00731     // Send mouse motion data to PUI
00732     puMouse (x, y);
00733 
00734     // Send mouse motion for camera manager for panel scrolling
00735     if (globals->sit) {
00736       CPanel *panl = globals->sit->GetCurrentPanel ();
00737       if (panl) {
00738         // Send mouse event to panel
00739         panl->MouseMotion (x, y);
00740       }
00741     }
00742   }
00743 
00744   // Send mouse motion to cursor manager
00745   if (globals->cursormgr) {
00746     globals->cursormgr->MouseMotion (x, y);
00747   }
00748 
00749   // Force screen redraw
00750   glutPostRedisplay () ;
00751 }
00752 
00753 
00754 //
00755 // GLUT mouse event
00756 //
00757 void mouse ( int button, int updown, int x, int y )
00758 {
00759   bool used = false;
00760 
00761   // Send mouse click events to FUI for processing
00762   EMouseButton b = MOUSE_BUTTON_LEFT;
00763   switch (updown) {
00764   case GLUT_DOWN:
00765     switch (button) {
00766     case GLUT_LEFT_BUTTON:
00767       b = MOUSE_BUTTON_LEFT;
00768       break;
00769 
00770     case GLUT_MIDDLE_BUTTON:
00771       b = MOUSE_BUTTON_MIDDLE;
00772       break;
00773 
00774     case GLUT_RIGHT_BUTTON:
00775       b = MOUSE_BUTTON_RIGHT;
00776       break;
00777     }
00778     used = globals->fuimgr->MouseClick (x, y, b);
00779     break;
00780 
00781   case GLUT_UP:
00782     switch (button) {
00783     case GLUT_LEFT_BUTTON:
00784       b = MOUSE_BUTTON_LEFT;
00785       break;
00786 
00787     case GLUT_MIDDLE_BUTTON:
00788       b = MOUSE_BUTTON_MIDDLE;
00789       break;
00790 
00791     case GLUT_RIGHT_BUTTON:
00792       b = MOUSE_BUTTON_RIGHT;
00793       break;
00794     }
00795     used = globals->fuimgr->MouseStopClick (x, y, b);
00796     break;
00797   }
00798 
00799   if (!used) {
00800     // Send mouse event to PUI for potential processing
00801     puMouse (button, updown, x, y);
00802 
00803     // Send mouse motion for camera manager for gauge interaction
00804     if (globals->sit) {
00805       CPanel *panl = globals->sit->GetCurrentPanel ();
00806       if (panl) {
00807         // Send mouse event to panel
00808         panl->MouseClick (button, updown, x, y);
00809       }
00810     }
00811   }
00812 
00813   // Force screen redraw
00814   glutPostRedisplay () ;
00815 }
00816 
00817 
00818 //
00819 // GLUT keyboard event
00820 //
00821 static void keyboard (unsigned char key, int x, int y)
00822 {
00823   // Pass keystroke to PUI keyboard handler
00824   if (!puKeyboard (key, PU_DOWN)) {
00825 
00826     // Ignore keypresses if there is no keymap definition
00827     if (globals->keymap == NULL) return;
00828 
00829     // Convert GLUT modifiers to FlyLegacy modifiers
00830     int glutmod = glutGetModifiers ();
00831     EKeyboardModifiers flymod = glutModifiersToFlyLegacyModifiers (glutmod);
00832 
00833     // Get FlyLegacy key code
00834     EKeyboardKeys flykey;
00835     if (glutKeyToFlyLegacyKey (key, &flykey)) {
00836       globals->keymap->KeyPress (flykey, flymod);
00837     } else {
00838       if (globals->logWarning) globals->logWarning->Write ("keyboard : Unmapped GLUT key %d", key);
00839     }
00840   }
00841 }
00842 
00843 //
00844 // GLUT special keys event
00845 //
00846 static void special (int key, int x, int y)
00847 {
00848   // Pass keystroke to PUI keyboard handler 
00849   if (!puKeyboard (key + PU_KEY_GLUT_SPECIAL_OFFSET, PU_DOWN)) {
00850 
00851     // Non-windows keyboard event handling
00852 
00853     // Ignore keypresses if there is no keymap definition
00854     if (globals->keymap == NULL) return;
00855 
00856     // Get GLUT modifiers and convert to FlyLegacy modifiers
00857     int glutmod = glutGetModifiers ();
00858     EKeyboardModifiers flymod = glutModifiersToFlyLegacyModifiers (glutmod);
00859 
00860     // Get FlyLegacy key code
00861     EKeyboardKeys flykey;
00862     if (glutSpecialToFlyLegacyKey (key, &flykey)) {
00863       globals->keymap->KeyPress (flykey, flymod);
00864     } else {
00865       if (globals->logWarning) globals->logWarning->Write ("special : Unmapped GLUT key %d", key);
00866     }
00867   }
00868 }
00869 
00870 
00871 //
00872 // Initialize splash screen
00873 //
00874 SBitmap *bmSplash = NULL;
00875 SSurface *surfSplash = NULL;
00876 
00877 static void InitSplashScreen (void)
00878 {
00879   // Load splash screen .PBM
00880   bmSplash = new SBitmap;
00881   strcpy (bmSplash->bitmapName, "UI\\LOADING SCREEN\\OPENING.PBM");
00882   LoadBitmap (bmSplash) ;
00883   int w, h;
00884   GetBitmapSize (bmSplash, &w, &h);
00885 
00886   // Create SSurface
00887   surfSplash = CreateSurface (globals->screenWidth, globals->screenHeight);
00888   EraseSurface (surfSplash);
00889   surfSplash->xScreen = 0;
00890   surfSplash->yScreen = 0;
00891 
00892   // Draw bitmap to surface
00893   int x = (globals->screenWidth - w) / 2;
00894   int y = (globals->screenHeight - h) / 2;
00895   DrawBitmap (surfSplash, bmSplash, x, y, 0);
00896 
00897   // Overlay text
00898   char buildString[80];
00899   sprintf (buildString, "%s Build %d.%d.%03d", 
00900            FLY_LEGACY_TITLE,
00901            FLY_LEGACY_MAJOR_VERSION,
00902            FLY_LEGACY_MINOR_VERSION,
00903            FLY_LEGACY_BUILD);
00904   unsigned int black = MakeRGB (0, 0, 0);
00905   unsigned int white = MakeRGB (255, 255, 255);
00906   x = globals->screenWidth / 2;
00907   y = ((globals->screenHeight - h) / 2) + 20;
00908   DrawTextC (surfSplash, &globals->fonts.ftthin24, x+1, y+1, black, buildString);
00909   DrawTextC (surfSplash, &globals->fonts.ftthin24, x, y, white, buildString);
00910 }
00911 
00912 static void Draw2D (SSurface *surf)
00913 {
00914   // Set projection matrix to 2D screen size
00915   glMatrixMode(GL_PROJECTION);
00916   glPushMatrix();
00917   glLoadIdentity();
00918   gluOrtho2D (0, globals->screenWidth, 0, globals->screenHeight);
00919 
00920   // Set up OpenGL drawing state
00921   glPushAttrib (GL_ENABLE_BIT);
00922   glEnable (GL_ALPHA_TEST);
00923   glDisable (GL_DEPTH_TEST);
00924   glDisable (GL_LIGHTING);
00925   glDisable (GL_COLOR_MATERIAL);
00926   glDisable (GL_TEXTURE_2D);
00927 
00928   // Blit the surface
00929   glRasterPos2i (0, 0);
00930   Blit (surf);
00931 
00932   // Restore original OpenGL state
00933   glPopAttrib();
00934 
00935   // Restore original projection matrix
00936   glMatrixMode(GL_PROJECTION);
00937   glPopMatrix();
00938 
00939   // Check for an OpenGL error
00940   GLenum e = glGetError ();
00941   if (e != GL_NO_ERROR) {
00942     gtfo ("CPanel::Draw:Return : GL Error 0x%04X", e);
00943   }
00944 }
00945 
00946 static void RedrawSplashScreen (void)
00947 {
00948   // Blit surface
00949   Draw2D (surfSplash);
00950 }
00951 
00952 static void CleanupSplashScreen (void)
00953 {
00954   FreeBitmap (bmSplash);
00955   delete bmSplash;
00956   FreeSurface (surfSplash);
00957 }
00958 
00959 //
00960 // Initialization occurs while splash screen is displayed
00961 //
00962 static void Initialize (void)
00963 {
00964   // Set default cursor.  This depends on initialization of the cursor manager
00965   //   and POD filesystems (to find the cursor control and image files)
00966   globals->crsrArrow = globals->cursormgr->BindCursor ("MPARROW.CSR");
00967   globals->cursormgr->SetCursor (globals->crsrArrow);
00968 
00969   // Initialize various subsystems.  These initialization functions may be
00970   //   dependent on INI settings and/or POD filesystem
00971   init_keyboard ();
00972   init_globe_tile_table ();
00973 
00974   InitGlobalsWithPodFilesystem();
00975 }
00976 
00977 //
00978 // Redraw function when application is in loading screen state
00979 //
00980 SBitmap *bmLoading;
00981 SSurface *surfLoading;
00982 static void InitLoadingScreen (void)
00983 {
00984   // Loading screen .PBM
00985   bmLoading = new SBitmap;
00986   strcpy (bmLoading->bitmapName, "UI\\LOADING SCREEN\\LOADING.PBM");
00987   LoadBitmap (bmLoading);
00988   int w, h;
00989   GetBitmapSize (bmLoading, &w, &h);
00990 
00991   // Create SSurface
00992   surfLoading = CreateSurface (globals->screenWidth, globals->screenHeight);
00993   EraseSurface (surfLoading);
00994   surfLoading->xScreen = 0;
00995   surfLoading->yScreen = 0;
00996 
00997   // Draw bitmap to surface
00998   if ((w > globals->screenWidth) || (h > globals->screenHeight)) {
00999     // Image is larger than the screen...just copy a portion to fit the surface
01000     int x1 = (w - globals->screenWidth) / 2;
01001     int y1 = (h - globals->screenHeight) / 2;
01002     int x2 = x1 + globals->screenWidth;
01003     int y2 = y1 + globals->screenHeight;
01004     DrawBitmapPartial (surfLoading, bmLoading, 0, 0, x1, y1, x2, y2, 0);
01005   } else {
01006     // Image is smaller or equal to the screen size
01007     int x = (globals->screenWidth - w) / 2;
01008     int y = (globals->screenHeight - h) / 2;
01009     DrawBitmap (surfLoading, bmLoading, x, y, 0);
01010   }
01011 }
01012 
01013 static void RedrawLoadingScreen (void)
01014 {
01015   // Overlay % progress
01016 
01017   // Blit surface
01018   Draw2D (surfLoading);
01019 }
01020 
01021 static void CleanupLoadingScreen (void)
01022 {
01023   if (bmLoading != NULL) {
01024     FreeBitmap (bmLoading);
01025     delete bmLoading;
01026     bmLoading = NULL;
01027   }
01028 
01029   if (surfLoading != NULL) { 
01030     FreeSurface (surfLoading);
01031     surfLoading = NULL;
01032   }
01033 }
01034 
01035 //
01036 // Redraw function when application is in load situation state
01037 //
01038 static void LoadStartupSituation (void)
01039 {
01040   // Load default situation
01041   char sitFilename[80];
01042   strcpy (sitFilename, "");
01043   GetIniString ("UI", "startupSituation", sitFilename, 80);
01044   if (strlen (sitFilename) == 0) {
01045     // No default startup situation specified in INI settings
01046     strcpy (sitFilename, "Default.sit");
01047     SetIniString ("UI", "startupSituation", sitFilename);
01048     SaveIniSettings ();
01049   }
01050 
01051   char *mark1 = new char[32];
01052   strcpy (mark1, "sit start");
01053   globals->sit = new CSituation (sitFilename);
01054   char *mark2 = new char[32];
01055   strcpy (mark2, "sit end");
01056 
01057 //  globals->sit = new CSituation ("Default.sit");  // Default for testing
01058 //  globals->sit = new CSituation ("Flyhawk.sit");  // Flyhawk  - Cessna 172
01059 //  globals->sit = new CSituation ("TRI1.sit");   // Harvey   - Piper Malibu
01060 //  globals->sit = new CSituation ("TRI1B.sit");  // TRI3     - "Dragonfly" Malibu
01061 //  globals->sit = new CSituation ("TRI2.sit");   // Java     - Piper Navajo
01062 //  globals->sit = new CSituation ("TRI3.sit");   // TRI3     - Beech KingAir
01063 //  globals->sit = new CSituation ("TRI3B.sit");  // TRI3B    - "Barracuda" KingAir
01064 //  globals->sit = new CSituation ("TRI4.sit");   // TRI4     - Peregrine 800TR
01065 //  globals->sit = new CSituation ("Pilatus.sit");  // Pilatus  - Pilatus PC-12
01066 //  globals->sit = new CSituation ("Stearman.sit"); // Stearman - Stearman Biplane
01067 //  globals->sit = new CSituation ("Stearflt.sit"); // Stearflt - Stearman w/Floats
01068 }
01069 
01070 //
01071 // Redraw function when application is in simulation state
01072 //
01073 static unsigned int   nFrames = 0;      // Sim frame rate counter
01074 static float          tFrames = 0.0f;   // Sim frame rate timer
01075 static float          frameRate = 0.0f; // Sim frame rate
01076 
01077 static void RedrawSimulation (void)
01078 {
01079   // Call the time manager to indicate that another cycle is occurring.
01080   //   This represents the redraw cycle, not necessarily the simulation
01081   //   cycle, though at present they are coupled.
01082   globals->timemgr->Update ();
01083   float dRealT = globals->timemgr->GetDeltaRealTime();
01084   float dSimT  = globals->timemgr->GetDeltaSimTime();
01085 
01086   // Accumulate frame rate statistics every second
01087   nFrames++;
01088   tFrames += dRealT;
01089   if (tFrames > 1.0f) {
01090     frameRate = (float)nFrames / tFrames;
01091     tFrames = 0.0f;
01092     nFrames = 0;
01093   }
01094 
01095 //  char debug[80];
01096 //  sprintf (debug, "dT = %f   frameRate=%5.2f", dRealT, frameRate);
01097 //  DrawNoticeToUser (debug, 1);
01098 
01099   // Update situation
01100   if (globals->sit != NULL) {
01101     globals->sit->Timeslice (dSimT);
01102   }
01103 
01104   // The global CSituation object contains all information about the current
01105   //   simulation state, user vehicle, camera mode, etc.
01107   globals->sit->Draw (dRealT);
01108 
01109   // Draw UI components
01110   DrawUi (dRealT);
01111   globals->fuimgr->Draw ();
01112 
01113   // Draw cursor
01114   globals->cursormgr->Draw ();
01115 }
01116 
01117 //
01118 // Initialize splash screen
01119 //
01120 SBitmap *bmExit = NULL;
01121 SSurface *surfExit = NULL;
01122 
01123 static void InitExitScreen (void)
01124 {
01125   // Load screen .PBM
01126   bmExit = new SBitmap;
01127   strcpy (bmExit->bitmapName, "UI\\LOADING SCREEN\\LEAVING.PBM");
01128   LoadBitmap (bmExit);
01129   int w, h;
01130   GetBitmapSize (bmExit, &w, &h);
01131 
01132   // Create SSurface
01133   surfExit = CreateSurface (globals->screenWidth, globals->screenHeight);
01134   EraseSurface (surfExit);
01135   surfExit->xScreen = 0;
01136   surfExit->yScreen = 0;
01137 
01138   // Draw bitmap to surface
01139   int x = (globals->screenWidth - w) / 2;
01140   int y = (globals->screenHeight - h) / 2;
01141   DrawBitmap (surfExit, bmExit, x, y, 0);
01142 
01143   // Draw text
01144   char exitMsg[80];
01145   strcpy (exitMsg, "You are cleared for departure...");
01146   unsigned int white = MakeRGB (255, 255, 255);
01147   DrawTextC (surfExit, &globals->fonts.ftthin24,
01148              globals->screenWidth / 2, globals->screenHeight - 40,
01149              white, exitMsg);
01150 }
01151 
01152 static void RedrawExitScreen (void)
01153 {
01154   // Blit surface
01155   Draw2D (surfExit);
01156 }
01157 
01158 static void CleanupExitScreen (void)
01159 {
01160   FreeBitmap (bmExit);
01161   delete bmExit;
01162   FreeSurface (surfExit);
01163 }
01164 
01165 static void ExitApp ()
01166 {
01167   // Gracefully shut down and clean up before exiting
01168   ShutdownAll ();
01169 
01170   // Exit fullscreen mode
01171   glutLeaveGameMode ();
01172 
01173   CleanupExitScreen ();
01174 
01175 #if defined(_DEBUG) && defined(HAVE_CRTDBG_H)
01176   // Check for memory leaks
01177   HANDLE hfile = CreateFile ("Logs\\MemoryLeaks.log",
01178                              GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
01179                              FILE_ATTRIBUTE_NORMAL, NULL);
01180   _CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_FILE);
01181   _CrtSetReportFile (_CRT_WARN, hfile);
01182   _CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_FILE);
01183   _CrtSetReportFile (_CRT_ERROR, hfile);
01184   _CrtMemDumpAllObjectsSince(&memoryState);
01185   CloseHandle (hfile);
01186 #endif
01187 
01188 //  fprintf (stdout, "Press Enter key to exit...");
01189 //  char s[80];
01190 //  gets(s);
01191 
01192 #if defined(WIN32) && defined(_DEBUG)
01193   // Avoid MSVC6 crash on exit() when debugging
01194   TerminateProcess (GetCurrentProcess(), 0);
01195 #else
01196   exit (0);
01197 #endif // _WIN32 && _DEBUG
01198 }
01199 
01200 //
01201 // GLUT redraw event
01202 //
01203 static void redraw ()
01204 {
01205   // Clear the back buffer
01206   glEnable (GL_DEPTH_TEST);
01207   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01208 
01209   switch (globals->appState) {
01210   case APP_SPLASH_SCREEN:
01211     // Display splash screen
01212     InitSplashScreen ();
01213     RedrawSplashScreen ();
01214     globals->appState = APP_INIT;
01215     break;
01216 
01217   case APP_INIT:
01218     {
01219     // Perform application initialization
01220     Initialize();
01221     RedrawSplashScreen ();
01222     globals->appState = APP_GENERATE_SITUATION;
01223     }
01224     break;
01225 
01226   case APP_GENERATE_SITUATION:
01227     // Currently nothing to do.
01228     
01235     RedrawSplashScreen ();
01236     globals->appState = APP_LOADING_SCREEN;
01237     break;
01238 
01239   case APP_LOADING_SCREEN:
01240     // Display "Loading..." screen
01241     InitLoadingScreen ();
01242     RedrawLoadingScreen ();
01243     CleanupSplashScreen ();
01244     globals->appState = APP_LOAD_SITUATION;
01245     break;
01246 
01247   case APP_LOAD_SITUATION:
01248     // Load situation
01249     {
01250     LoadStartupSituation ();
01251     RedrawLoadingScreen ();
01252     globals->appState = APP_PREPARE;
01253     }
01254     break;
01255 
01256   case APP_PREPARE:
01257     // Prepare situation for simulation
01258     globals->sit->Prepare ();
01259     globals->appState = APP_SIMULATION;
01260     RedrawLoadingScreen ();
01261     CleanupLoadingScreen ();
01262     break;
01263 
01264   case APP_SIMULATION:
01265     // Run simulation
01266     RedrawSimulation ();
01267     break;
01268 
01269   case APP_EXIT_SCREEN:
01270     // Display Exit screen
01271     InitExitScreen ();
01272     RedrawExitScreen ();
01273     globals->appState = APP_EXIT;
01274     break;
01275 
01276   case APP_EXIT:
01277     // Exit application...program does not return from this function
01278     ExitApp ();
01279     break;
01280   }
01281 
01282   glutPostRedisplay ();
01283   glutSwapBuffers ();
01284 }
01285 
01286 
01287 int main (int argc, char **argv)
01288 {
01289 #if defined(_DEBUG) && defined(HAVE_CRTDBG_H)
01290 
01291   _CrtMemCheckpoint (&memoryState);
01292 #endif
01293 
01294   // Load application settings from INI file
01295   LoadIniSettings ();
01296 
01297   // Initialize global variables.  Some globals are dependent on INI settings
01298   //   so this initialization must be done after the INI file has been loaded
01299   InitGlobalsNoPodFilesystem ();
01300   globals->appState = APP_SPLASH_SCREEN;
01301 
01302   // Initialize OpenGL and GLUT to enable game mode activation
01303   InitGraphics ();
01304 
01305   // Initialize the system pod filesystem.  The top-level reference to the POD
01306   //   filesystem is stored in the global variable struct, so this must
01307   //   be called after globals have been instantiated.
01308   char flyRootFolder[64];
01309   strcpy (flyRootFolder, "");
01310   GetIniString ("UI", "flyRootFolder", flyRootFolder, 64);
01311   if (strlen (flyRootFolder) == 0) {
01312     strcpy (flyRootFolder, "C:\\Program Files\\Terminal Reality\\Fly! II");
01313     SetIniString ("UI", "flyRootFolder", flyRootFolder);
01314     SaveIniSettings ();
01315   }
01316   pinit (&globals->pfs, flyRootFolder, false);
01317   char *mark1 = new char[32];
01318   strcpy (mark1, "padd Start");
01319   paddpodfolder (&globals->pfs, "System");
01320   char *mark2 = new char[32];
01321   strcpy (mark2, "System End");
01322   padddiskfolder (&globals->pfs, "Saved Simulations");
01323   padddiskfolder (&globals->pfs, "System");
01324   padddiskfolder (&globals->pfs, "Art");
01325   padddiskfolder (&globals->pfs, "BT");
01326   padddiskfolder (&globals->pfs, "Data");
01327   padddiskfolder (&globals->pfs, "Ui");
01328   padddiskfolder (&globals->pfs, "World");
01329   padddiskfolder (&globals->pfs, "Scenery");
01330   paddpodfolder (&globals->pfs, "Aircraft");
01331   paddpodfolder (&globals->pfs, "Scenery\\Shared");
01332   char *mark9 = new char[32];
01333   strcpy (mark9, "padd End");
01335  
01336 /*
01337   // DEBUG : Dump pod filesystem contents
01338   FILE *fPfsDump = fopen ("Logs\\PfsDump.log", "w");
01339   if (fPfsDump) {
01340     pfsdump (&globals->pfs, fPfsDump);
01341   }
01342   fclose (fPfsDump);
01343 */
01344 
01345   // Initialize subsystems so that mouse and keyboard callbacks can be handled
01346   init_ui ();
01347   char *mark3 = new char[32];
01348   strcpy (mark3, "fonts Start");
01349   InitFonts ();
01350   char *mark4 = new char[32];
01351   strcpy (mark4, "fonts End");
01352 
01353   // Enter GLUT main loop.
01354   glutMainLoop ();
01355 
01356   // Check for an OpenGL error
01357   GLenum e = glGetError ();
01358   if (e != GL_NO_ERROR) {
01359     gtfo ("main() : GL Error 0x%08x", e);
01360   }
01361 
01362   return 0;
01363 }
01364 
01365 
01366 #ifdef _WINDOWS
01367 //
01368 // Windows main() function
01369 //
01370 int APIENTRY WinMain (HINSTANCE hInstance,
01371                       HINSTANCE hPrevInstance,
01372                       LPSTR lpCmdLine,
01373                       int nShowCmd)
01374 {
01375   main(0, NULL);
01376   return 0;
01377 }
01378 #endif // _WINDOWS
01379 
01380 
01381 void GTFO::operator() (const char* fmt, ...)
01382 {
01383   glutLeaveGameMode ();
01384 
01385   CLogFile *log = new CLogFile ("Logs\\gtfo.log", "a");
01386 
01387   char usermsg[512];
01388   // Format user message from varargs
01389   if (fmt != NULL) {
01390     va_list argp;
01391     va_start(argp, fmt);
01392     vsprintf(usermsg, fmt, argp);
01393     va_end(argp);
01394   } else {
01395     // NULL user message format string
01396     strcpy (usermsg, "");
01397   }
01398 
01399   // Trim all but last two path components from filename
01401   char separator = '\\';
01402   int nSeparators = 0;
01403   int len = strlen(m_file);
01404 
01405   // Initialize file buffer with entire filename
01406   char file[1024];
01407   char *c;
01408   for (c = (m_file + len); c >= m_file; c--) {
01409     if (*c == separator) {
01410       nSeparators++;
01411       if (nSeparators == 2) {
01412         // Found two separators...extract remnant to buffer
01413         c++;
01414         break;
01415       }
01416     }
01417   }
01418   strcpy (file, c);
01419 
01420   // Output log message
01421   log->Write ("Abnormal exit\n  File: %s  Line: %d\n  %s\n\n", file, m_line, usermsg);
01422 
01423   delete log;
01424 
01425 #if defined(WIN32) && defined(_DEBUG)
01426   TerminateProcess (GetCurrentProcess(), 0);
01427 #endif
01428   exit (0);
01429 }
01430 
01431 void WARN::operator() (const char* fmt, ...)
01432 {
01433   if (globals->logWarning != NULL) {
01434     char usermsg[512];
01435     // Format user message from varargs
01436     if (fmt != NULL) {
01437       va_list argp;
01438       va_start(argp, fmt);
01439       vsprintf(usermsg, fmt, argp);
01440       va_end(argp);
01441     } else {
01442       // NULL user message format string
01443       strcpy (usermsg, "");
01444     }
01445 
01446     // Trim all but last two path components from filename
01448     char separator = '\\';
01449     int nSeparators = 0;
01450     int len = strlen(m_file);
01451 
01452     // Initialize file buffer with entire filename
01453     char file[1024];
01454     char *c;
01455     for (c = (m_file + len); c >= m_file; c--) {
01456       if (*c == separator) {
01457         nSeparators++;
01458         if (nSeparators == 2) {
01459           // Found two separators...extract remnant to buffer
01460           c++;
01461           break;
01462         }
01463       }
01464     }
01465     strcpy (file, c);
01466 
01467     // Output log message
01468     globals->logWarning->Write ("Warning\n  File: %s  Line: %d\n  %s\n\n",
01469       file, m_line, usermsg);
01470   }
01471 }
01472 
01473 void DEBUG::operator() (const char* fmt, ...)
01474 {
01475   if (globals->logDebug != NULL) {
01476     char usermsg[512];
01477     // Format user message from varargs
01478     if (fmt != NULL) {
01479       va_list argp;
01480       va_start(argp, fmt);
01481       vsprintf(usermsg, fmt, argp);
01482       va_end(argp);
01483     } else {
01484       // NULL user message format string
01485       strcpy (usermsg, "");
01486     }
01487 
01488     // Trim all but last two path components from filename
01490     char separator = '\\';
01491     int nSeparators = 0;
01492     int len = strlen(m_file);
01493 
01494     // Initialize file buffer with entire filename
01495     char file[1024];
01496     char *c;
01497     for (c = (m_file + len); c >= m_file; c--) {
01498       if (*c == separator) {
01499         nSeparators++;
01500         if (nSeparators == 2) {
01501           // Found two separators...extract remnant to buffer
01502           c++;
01503           break;
01504         }
01505       }
01506     }
01507     strcpy (file, c);
01508 
01509     // Output log message
01510     globals->logDebug->Write ("Debug\n  File: %s  Line: %d\n  %s\n\n",
01511       file, m_line, usermsg);
01512   }
01513 }
SourceForge.net Logo Documentation generated by doxygen