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