== bugfix ==
[blender.git] / source / gameengine / GamePlayer / ghost / GPG_ghost.cpp
1 /**
2 * $Id$
3 *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31 * Start up of the Blender Player on GHOST.
32 */
33
34 #include <iostream>
35 #include <math.h>
36
37 #ifdef __linux__
38 #ifdef __alpha__
39 #include <signal.h>
40 #endif /* __alpha__ */
41 #endif /* __linux__ */
42
43 #ifdef __APPLE__
44 // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
45 //#include <Carbon/Carbon.h>
46 //#include <CFBundle.h>
47 #endif // __APPLE__
48 #include "GEN_messaging.h"
49 #include "KX_KetsjiEngine.h"
50
51 /**********************************
52 * Begin Blender include block
53 **********************************/
54 #ifdef __cplusplus
55 extern "C"
56 {
57 #endif  // __cplusplus
58 #include "BKE_global.h" 
59 #include "BKE_icons.h"  
60 #include "BLI_blenlib.h"
61 #include "DNA_scene_types.h"
62 #include "BLO_readfile.h"
63 #include "BLO_readblenfile.h"
64         
65         int GHOST_HACK_getFirstFile(char buf[]);
66         
67 #ifdef __cplusplus
68 }
69 #endif // __cplusplus
70 /**********************************
71 * End Blender include block
72 **********************************/
73
74 #include "SYS_System.h"
75 #include "GPG_Application.h"
76 #include "GPC_PolygonMaterial.h"
77
78 #include "GHOST_ISystem.h"
79 #include "RAS_IRasterizer.h"
80
81 #include "BKE_main.h"
82 #include "BKE_utildefines.h"
83
84 #ifdef WIN32
85 #include <windows.h>
86 #ifdef NDEBUG
87 #include <wincon.h>
88 #endif // NDEBUG
89 #endif // WIN32
90
91 const int kMinWindowWidth = 100;
92 const int kMinWindowHeight = 100;
93
94 char bprogname[FILE_MAXDIR+FILE_MAXFILE];
95
96 #ifdef WIN32
97 typedef enum 
98 {
99   SCREEN_SAVER_MODE_NONE = 0,
100   SCREEN_SAVER_MODE_PREVIEW,
101   SCREEN_SAVER_MODE_SAVER,
102   SCREEN_SAVER_MODE_CONFIGURATION,
103   SCREEN_SAVER_MODE_PASSWORD,
104 } ScreenSaverMode;
105
106 static ScreenSaverMode scr_saver_mode = SCREEN_SAVER_MODE_NONE;
107 static HWND scr_saver_hwnd = NULL;
108
109 static BOOL scr_saver_init(int argc, char **argv) 
110 {
111         scr_saver_mode = SCREEN_SAVER_MODE_NONE;
112         scr_saver_hwnd = NULL;
113         BOOL ret = FALSE;
114
115         int len = ::strlen(argv[0]);
116         if (len > 4 && !::stricmp(".scr", argv[0] + len - 4))
117         {
118                 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
119                 ret = TRUE;
120                 if (argc >= 2)
121                 {
122                         if (argc >= 3)
123                         {
124                                 scr_saver_hwnd = (HWND) ::atoi(argv[2]);
125                         }
126                         if (!::stricmp("/c", argv[1]))
127                         {
128                                 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
129                                 if (scr_saver_hwnd == NULL)
130                                         scr_saver_hwnd = ::GetForegroundWindow();
131                         }
132                         else if (!::stricmp("/s", argv[1]))
133                         {
134                                 scr_saver_mode = SCREEN_SAVER_MODE_SAVER;
135                         }
136                         else if (!::stricmp("/a", argv[1]))
137                         {
138                                 scr_saver_mode = SCREEN_SAVER_MODE_PASSWORD;
139                         }
140                         else if (!::stricmp("/p", argv[1])
141                                  || !::stricmp("/l", argv[1]))
142                         {
143                                 scr_saver_mode = SCREEN_SAVER_MODE_PREVIEW;
144                         }
145                 }
146         }
147         return ret;
148 }
149
150 #endif /* WIN32 */
151
152 void usage(char* program)
153 {
154         char * consoleoption;
155 #ifdef _WIN32
156         consoleoption = "-c ";
157 #else
158         consoleoption = "";
159 #endif
160         
161         printf("usage:   %s [-w [-p l t w h]] %s[-g gamengineoptions] "
162                 "[-s stereomode] filename.blend\n", program, consoleoption);
163         printf("  -h: Prints this command summary\n");
164         printf("  -w: display in a window\n");
165         printf("  -p: specify window position\n");
166         printf("       l = window left coordinate\n");
167         printf("       t = window top coordinate\n");
168         printf("       w = window width\n");
169         printf("       h = window height\n");
170         printf("  -f: start game in full screen mode\n");
171         printf("       fw = full screen mode pixel width\n");
172         printf("       fh = full screen mode pixel height\n");
173         printf("       fb = full screen mode bits per pixel\n");
174         printf("       ff = full screen mode frequency\n");
175         printf("  -s: start player in stereo\n");
176         printf("       stereomode: hwpageflip       (Quad buffered shutter glasses)\n");
177         printf("                   syncdoubling     (Above Below)\n");
178         printf("                   sidebyside       (Left Right)\n");
179         printf("                   anaglyph         (Red-Blue glasses)\n");
180         printf("                   vinterlace       (Vertical interlace for autostereo display)\n");
181         printf("                             depending on the type of stereo you want\n");
182 #ifdef _WIN32
183         printf("  -c: keep console window open\n");
184 #endif
185         printf("  -g: game engine options:\n");
186         printf("       Name            Default      Description\n");
187         printf("       ----------------------------------------\n");
188         printf("       fixedtime          0         Do the same timestep each frame \"Enable all frames\"\n");
189         printf("       nomipmap           0         Disable mipmaps\n");
190         printf("       show_framerate     0         Show the frame rate\n");
191         printf("       show_properties    0         Show debug properties\n");
192         printf("       show_profile       0         Show profiling information\n");
193         printf("       vertexarrays       1         Enable vertex arrays\n");
194         printf("       blender_material   0         Enable material settings\n");
195         printf("\n");
196         printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program);
197         printf("example: %s -g vertexarrays = 0 c:\\loadtest.blend\n", program);
198 }
199
200 char *get_filename(int argc, char **argv) {
201 #ifdef __APPLE__
202 /* On Mac we park the game file (called game.blend) in the application bundle.
203 * The executable is located in the bundle as well.
204 * Therefore, we can locate the game relative to the executable.
205         */
206         int srclen = ::strlen(argv[0]);
207         int len = 0;
208         char *filename = NULL;
209         
210         if (argc > 1) {
211                 if (BLI_exists(argv[argc-1])) {
212                         len = ::strlen(argv[argc-1]);
213                         filename = new char [len + 1];
214                         ::strcpy(filename, argv[argc-1]);
215                         return(filename);
216                 }
217                 if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
218                         static char firstfilebuf[512];
219                         if (GHOST_HACK_getFirstFile(firstfilebuf)) {
220                                 len = ::strlen(firstfilebuf);
221                                 filename = new char [len + 1];
222                                 ::strcpy(filename, firstfilebuf);
223                                 return(filename);
224                         }
225                 }                        
226         }
227         
228         srclen -= ::strlen("MacOS/blenderplayer");
229         if (srclen > 0) {
230                 len = srclen + ::strlen("Resources/game.blend"); 
231                 filename = new char [len + 1];
232                 ::strcpy(filename, argv[0]);
233                 ::strcpy(filename + srclen, "Resources/game.blend");
234                 //::printf("looking for file: %s\n", filename);
235                 
236                 if (BLI_exists(filename)) {
237                         return (filename);
238                 }
239         }
240         
241         return(NULL);
242 #else
243         return (argc>1)?argv[argc-1]:NULL;
244 #endif // !_APPLE
245 }
246
247 static BlendFileData *load_game_data(char *progname, char *filename = NULL) {
248         BlendReadError error;
249         BlendFileData *bfd = NULL;
250         
251         /* try to load ourself, will only work if we are a runtime */
252         if (blo_is_a_runtime(progname)) {
253                 bfd= blo_read_runtime(progname, &error);
254                 if (bfd) {
255                         bfd->type= BLENFILETYPE_RUNTIME;
256                         strcpy(bfd->main->name, progname);
257                 }
258         } else {
259                 bfd= BLO_read_from_file(progname, &error);
260         }
261         
262         /*
263         if (bfd && bfd->type == BLENFILETYPE_BLEND) {
264                 BLO_blendfiledata_free(bfd);
265                 bfd = NULL;
266                 error = BRE_NOT_A_PUBFILE;
267         }
268         */
269         
270         if (!bfd && filename) {
271                 bfd = load_game_data(filename);
272                 if (!bfd) {
273                         printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
274                 }
275         }
276         
277         return bfd;
278 }
279
280 int main(int argc, char** argv)
281 {
282         int i;
283         bool error = false;
284         SYS_SystemHandle syshandle = SYS_GetSystem();
285         bool fullScreen = false;
286         bool fullScreenParFound = false;
287         bool windowParFound = false;
288         bool closeConsole = true;
289         RAS_IRasterizer::StereoMode stereomode;
290         bool stereoWindow = false;
291         bool stereoParFound = false;
292         int windowLeft = 100;
293         int windowTop = 100;
294         int windowWidth = 640;
295         int windowHeight = 480;
296         GHOST_TUns32 fullScreenWidth = 0;
297         GHOST_TUns32 fullScreenHeight= 0;
298         int fullScreenBpp = 32;
299         int fullScreenFrequency = 60;
300
301 #ifdef __linux__
302 #ifdef __alpha__
303         signal (SIGFPE, SIG_IGN);
304 #endif /* __alpha__ */
305 #endif /* __linux__ */
306         BLI_where_am_i(bprogname, argv[0]);
307 #ifdef __APPLE__
308     // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
309     /*
310     IBNibRef            nibRef;
311     WindowRef           window;
312     OSStatus            err;
313         
314           // Create a Nib reference passing the name of the nib file (without the .nib extension)
315           // CreateNibReference only searches into the application bundle.
316           err = ::CreateNibReference(CFSTR("main"), &nibRef);
317           if (err) return -1;
318           
319                 // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
320                 // object. This name is set in InterfaceBuilder when the nib is created.
321                 err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
322                 if (err) return -1;
323                 
324                   // We don't need the nib reference anymore.
325                   ::DisposeNibReference(nibRef);
326     */
327 #endif // __APPLE__
328         
329         GEN_init_messaging_system();
330  
331         // Parse command line options
332 #ifndef NDEBUG
333         printf("argv[0] = '%s'\n", argv[0]);
334 #endif
335
336 #ifdef WIN32
337         if (scr_saver_init(argc, argv))
338         {
339                 switch (scr_saver_mode)
340                 {
341                 case SCREEN_SAVER_MODE_CONFIGURATION:
342                         MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
343                         break;
344                 case SCREEN_SAVER_MODE_PASSWORD:
345                         /* This is W95 only, which we currently do not support.
346                            Fall-back to normal screen saver behaviour in that case... */
347                 case SCREEN_SAVER_MODE_SAVER:
348                         fullScreen = true;
349                         fullScreenParFound = true;
350                         break;
351
352                 case SCREEN_SAVER_MODE_PREVIEW:
353                         /* This will actually be handled somewhere below... */
354                         break;
355                 }
356         }
357 #endif
358         for (i = 1; (i < argc) && !error 
359 #ifdef WIN32
360                 && scr_saver_mode == SCREEN_SAVER_MODE_NONE
361 #endif
362                 ;)
363
364         {
365 #ifndef NDEBUG
366                 printf("argv[%d] = '%s'   , %i\n", i, argv[i],argc);
367 #endif
368                 if (argv[i][0] == '-')
369                 {
370                         switch (argv[i][1])
371                         {
372                         case 'g':
373                                 // Parse game options
374                                 {
375                                         i++;
376                                         if (i < argc)
377                                         {
378                                                 char* paramname = argv[i];
379                                                 // Check for single value versus assignment
380                                                 if (i+1 < argc && (*(argv[i+1]) == '='))
381                                                 {
382                                                         i++;
383                                                         if (i + 1 < argc)
384                                                         {
385                                                                 i++;
386                                                                 // Assignment
387                                                                 SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
388                                                                 SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
389                                                                 SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
390 #ifndef NDEBUG
391                                                                 printf("%s = '%s'\n", paramname, argv[i]);
392 #endif
393                                                                 i++;
394                                                         }
395                                                         else
396                                                         {
397                                                                 error = true;
398                                                                 printf("error: argument assignment %s without value.\n", paramname);
399                                                         }
400                                                 }
401                                                 else
402                                                 {
403 //                                                      SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
404                                                 }
405                                         }
406                                 }
407                                 break;
408                                 
409                         case 'p':
410                                 // Parse window position and size options
411                                 if (argv[i][2] == 0) {
412                                         i++;
413                                         if ((i + 4) < argc)
414                                         {
415                                                 windowLeft = atoi(argv[i++]);
416                                                 windowTop = atoi(argv[i++]);
417                                                 windowWidth = atoi(argv[i++]);
418                                                 windowHeight = atoi(argv[i++]);
419                                                 windowParFound = true;
420                                         }
421                                         else
422                                         {
423                                                 error = true;
424                                                 printf("error: too few options for window argument.\n");
425                                         }
426                                 } else { /* mac specific */
427                                 
428                     if (strncmp(argv[i], "-psn_", 5)==0) 
429                         i++; /* skip process serial number */
430                                 }
431                                 break;
432                         case 'f':
433                                 i++;
434                                 fullScreen = true;
435                                 fullScreenParFound = true;
436                                 if ((i + 2) < argc && argv[i][0] != '-' && argv[i+1][0] != '-')
437                                 {
438                                         fullScreenWidth = atoi(argv[i++]);
439                                         fullScreenHeight = atoi(argv[i++]);
440                                         if ((i + 1) < argc && argv[i][0] != '-')
441                                         {
442                                                 fullScreenBpp = atoi(argv[i++]);
443                                                 if ((i + 1) < argc && argv[i][0] != '-')
444                                                         fullScreenFrequency = atoi(argv[i++]);
445                                         }
446                                 }
447                                 break;
448                         case 'w':
449                                 // Parse window position and size options
450                                 {
451                                         fullScreen = false;
452                                         fullScreenParFound = true;
453                                         i++;
454                                 }
455                                 break;
456                         case 'h':
457                                 usage(argv[0]);
458                                 return 0;
459                                 break;
460                         case 'c':
461                                 i++;
462                                 closeConsole = false;
463                                 break;
464                         case 's':  // stereo
465                                 i++;
466                                 if ((i + 1) < argc)
467                                 {
468                                         stereomode = (RAS_IRasterizer::StereoMode) atoi(argv[i]);
469                                         if (stereomode < RAS_IRasterizer::RAS_STEREO_NOSTEREO || stereomode >= RAS_IRasterizer::RAS_STEREO_MAXSTEREO)
470                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
471                                         
472                                         if(!strcmp(argv[i], "nostereo"))  // ok, redundant but clear
473                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
474                                         
475                                         // only the hardware pageflip method needs a stereo window
476                                         if(!strcmp(argv[i], "hwpageflip")) {
477                                                 stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
478                                                 stereoWindow = true;
479                                         }
480                                         if(!strcmp(argv[i], "syncdoubling"))
481                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
482                                         
483                                         if(!strcmp(argv[i], "anaglyph"))
484                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;
485                                         
486                                         if(!strcmp(argv[i], "sidebyside"))
487                                                 stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;
488                                         
489                                         if(!strcmp(argv[i], "vinterlace"))
490                                                 stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;
491                                         
492 #if 0
493                                         // future stuff
494                                         if(strcmp(argv[i], "stencil")
495                                                 stereomode = RAS_STEREO_STENCIL;
496 #endif
497                                         
498                                         i++;
499                                         stereoParFound = true;
500                                 }
501                                 else
502                                 {
503                                         error = true;
504                                         printf("error: too few options for stereo argument.\n");
505                                 }
506                                 break;
507                         default:
508                                 printf("Unkown argument: %s\n", argv[i++]);
509                                 break;
510                         }
511                 }
512                 else
513                 {
514                         i++;
515                 }
516         }
517         
518         if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
519         {
520                 error = true;
521                 printf("error: window size too small.\n");
522         }
523         
524         if (error )
525         {
526                 usage(argv[0]);
527                 return 0;
528         }
529
530         if (!stereoParFound) stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
531
532 #ifdef WIN32
533         if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
534 #endif
535         {
536 #ifdef __APPLE__
537                 //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
538                 SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
539                 //fullScreen = false;           // Can't use full screen
540 #endif
541
542                 if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
543                 {
544                         GPC_PolygonMaterial::SetMipMappingEnabled(0);
545                 }
546                 
547                 // Create the system
548                 if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
549                 {
550                         GHOST_ISystem* system = GHOST_ISystem::getSystem();
551                         assertd(system);
552                         
553                         if (!fullScreenWidth || !fullScreenHeight)
554                                 system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
555                         // process first batch of events. If the user
556                         // drops a file on top off the blenderplayer icon, we 
557                         // recieve an event with the filename
558                         
559                         system->processEvents(0);
560                         
561                         // this bracket is needed for app (see below) to get out
562                         // of scope before GHOST_ISystem::disposeSystem() is called.
563                         {
564                                 int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
565                                 STR_String exitstring = "";
566                                 GPG_Application app(system, NULL, exitstring);
567                                 bool firstTimeRunning = true;
568                                 
569                                 do
570                                 {
571                                         // Read the Blender file
572                                         char *filename = get_filename(argc, argv);
573                                         char *titlename;
574                                         char pathname[160];
575                                         BlendFileData *bfd;
576                                         
577                                         // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
578                                         if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
579                                         {
580                                                 char basedpath[240];
581                                                 
582                                                 // base the actuator filename with respect
583                                                 // to the original file working directory
584                                                 strcpy(basedpath, exitstring.Ptr());
585                                                 BLI_convertstringcode(basedpath, pathname, 0);
586                                                 
587                                                 bfd = load_game_data(basedpath);
588                                         }
589                                         else
590                                         {
591                                                 bfd = load_game_data(argv[0], filename);
592                                         }
593                                         
594                                         //::printf("game data loaded from %s\n", filename);
595                                         
596                                         if (!bfd) {
597                                                 usage(argv[0]);
598                                                 error = true;
599                                                 exitcode = KX_EXIT_REQUEST_QUIT_GAME;
600                                         } 
601                                         else 
602                                         {
603 #ifdef WIN32
604 #ifdef NDEBUG
605                                                 if (closeConsole)
606                                                 {
607                                                         //::FreeConsole();    // Close a console window
608                                                 }
609 #endif // NDEBUG
610 #endif // WIN32
611                                                 Main *maggie = bfd->main;
612                                                 Scene *scene = bfd->curscene;
613                                                 strcpy (pathname, maggie->name);
614                                                 char *startscenename = scene->id.name + 2;
615                                                 G.fileflags  = bfd->fileflags;
616
617                                                 //Seg Fault; icon.c gIcons == 0
618                                                 BKE_icons_init(1);
619                                                 
620                                                 titlename = maggie->name;
621                                                 
622                                                 // Check whether the game should be displayed full-screen
623                                                 if ((!fullScreenParFound) && (!windowParFound))
624                                                 {
625                                                         // Only use file settings when command line did not override
626                                                         if (scene->r.fullscreen) {
627                                                                 //printf("fullscreen option found in Blender file\n");
628                                                                 fullScreen = true;
629                                                                 fullScreenWidth= scene->r.xplay;
630                                                                 fullScreenHeight= scene->r.yplay;
631                                                                 fullScreenFrequency= scene->r.freqplay;
632                                                                 fullScreenBpp = scene->r.depth;
633                                                         }
634                                                         else
635                                                         {
636                                                                 fullScreen = false;
637                                                                 windowWidth = scene->r.xplay;
638                                                                 windowHeight = scene->r.yplay;
639                                                         }
640                                                 }
641                                                 
642                                                 
643                                                 // Check whether the game should be displayed in stereo
644                                                 if (!stereoParFound)
645                                                 {
646                                                         stereomode = (RAS_IRasterizer::StereoMode) scene->r.stereomode;
647                                                         if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
648                                                                 stereoWindow = true;
649                                                 }
650                                                 
651                                                 //                                      GPG_Application app (system, maggie, startscenename);
652                                                 app.SetGameEngineData(maggie, startscenename);
653                                                 
654                                                 if (firstTimeRunning)
655                                                 {
656                                                         firstTimeRunning = false;
657                                                         
658                                                         if (fullScreen)
659                                                         {
660 #ifdef WIN32
661                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
662                                                                 {
663                                                                         app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
664                                                                                 stereoWindow, stereomode);
665                                                                 }
666                                                                 else
667 #endif
668                                                                 {
669                                                                         app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
670                                                                                 stereoWindow, stereomode);
671                                                                 }
672                                                         }
673                                                         else
674                                                         {
675 #ifdef __APPLE__
676                                                                 // on Mac's we'll show the executable name instead of the 'game.blend' name
677                                                                 char tempname[1024], *appstring;
678                                                                 ::strcpy(tempname, titlename);
679                                                                 
680                                                                 appstring = strstr(tempname, ".app/");
681                                                                 if (appstring) {
682                                                                         appstring[2] = 0;
683                                                                         titlename = &tempname[0];
684                                                                 }
685 #endif
686                                                                 // Strip the path so that we have the name of the game file
687                                                                 STR_String path = titlename;
688 #ifndef WIN32
689                                                                 vector<STR_String> parts = path.Explode('/');
690 #else  // WIN32
691                                                                 vector<STR_String> parts = path.Explode('\\');
692 #endif // WIN32                        
693                                                                 STR_String title;
694                                                                 if (parts.size())
695                                                                 {
696                                                                         title = parts[parts.size()-1];
697                                                                         parts = title.Explode('.');
698                                                                         if (parts.size() > 1)
699                                                                         {
700                                                                                 title = parts[0];
701                                                                         }
702                                                                 }
703                                                                 else
704                                                                 {
705                                                                         title = "blenderplayer";
706                                                                 }
707 #ifdef WIN32
708                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
709                                                                 {
710                                                                         app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode);
711                                                                 }
712                                                                 else
713 #endif
714                                                                 {
715                                                                         app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
716                                                                                 stereoWindow, stereomode);
717                                                                 }
718                                                         }
719                                                 }
720                                                 else
721                                                 {
722                                                         app.StartGameEngine(stereomode);
723                                                         exitcode = KX_EXIT_REQUEST_NO_REQUEST;
724                                                 }
725                                                 
726                                                 // Add the application as event consumer
727                                                 system->addEventConsumer(&app);
728                                                 
729                                                 // Enter main loop
730                                                 bool run = true;
731                                                 while (run)
732                                                 {
733                                                         system->processEvents(false);
734                                                         system->dispatchEvents();
735                                                         if ((exitcode = app.getExitRequested()))
736                                                         {
737                                                                 run = false;
738                                                                 exitstring = app.getExitString();
739                                                         }
740                                                 }
741                                                 app.StopGameEngine();
742                                                 BLO_blendfiledata_free(bfd);
743                                                 
744 #ifdef __APPLE__
745                                                 if (filename) {
746                                                         delete [] filename;
747                                                 }
748 #endif // __APPLE__
749                                         }
750                                 } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
751                         }
752
753                         // Seg Fault; icon.c gIcons == 0
754                         BKE_icons_free();
755
756                         // Dispose the system
757                         GHOST_ISystem::disposeSystem();
758                 } else {
759                         error = true;
760                         printf("error: couldn't create a system.\n");
761                 }
762         }
763
764         return error ? -1 : 0;
765 }
766
767