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