c4e738c18961acfdb751cfa9c2b5e072e1a70108
[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 "BKE_node.h"   
58 #include "BLI_blenlib.h"
59 #include "DNA_scene_types.h"
60 #include "BLO_readfile.h"
61 #include "BLO_readblenfile.h"
62         
63         int GHOST_HACK_getFirstFile(char buf[]);
64         
65 #ifdef __cplusplus
66 }
67 #endif // __cplusplus
68
69 #include "GPU_draw.h"
70
71 /**********************************
72 * End Blender include block
73 **********************************/
74
75 #include "SYS_System.h"
76 #include "GPG_Application.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 #ifndef _WIN32
183         printf("  -i: parent windows ID \n");
184 #endif
185 #ifdef _WIN32
186         printf("  -c: keep console window open\n");
187 #endif
188         printf("  -g: game engine options:\n");
189         printf("       Name            Default      Description\n");
190         printf("       ----------------------------------------\n");
191         printf("       fixedtime          0         Do the same timestep each frame \"Enable all frames\"\n");
192         printf("       nomipmap           0         Disable mipmaps\n");
193         printf("       show_framerate     0         Show the frame rate\n");
194         printf("       show_properties    0         Show debug properties\n");
195         printf("       show_profile       0         Show profiling information\n");
196         printf("       blender_material   0         Enable material settings\n");
197         printf("\n");
198         printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program);
199         printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program);
200 }
201
202 static void get_filename(int argc, char **argv, char *filename)
203 {
204 #ifdef __APPLE__
205 /* On Mac we park the game file (called game.blend) in the application bundle.
206 * The executable is located in the bundle as well.
207 * Therefore, we can locate the game relative to the executable.
208         */
209         int srclen = ::strlen(argv[0]);
210         int len = 0;
211         char *gamefile = NULL;
212         
213         filename[0] = '\0';
214
215         if (argc > 1) {
216                 if (BLI_exists(argv[argc-1])) {
217                         BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
218                 }
219                 if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
220                         static char firstfilebuf[512];
221                         if (GHOST_HACK_getFirstFile(firstfilebuf)) {
222                                 BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE);
223                         }
224                 }                        
225         }
226         
227         srclen -= ::strlen("MacOS/blenderplayer");
228         if (srclen > 0) {
229                 len = srclen + ::strlen("Resources/game.blend"); 
230                 gamefile = new char [len + 1];
231                 ::strcpy(gamefile, argv[0]);
232                 ::strcpy(gamefile + srclen, "Resources/game.blend");
233                 //::printf("looking for file: %s\n", filename);
234                 
235                 if (BLI_exists(gamefile))
236                         BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE);
237
238                 delete gamefile;
239         }
240         
241 #else
242         filename[0] = '\0';
243
244         if(argc > 1)
245                 BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
246 #endif // !_APPLE
247 }
248
249 static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL) {
250         BlendReadError error;
251         BlendFileData *bfd = NULL;
252         
253         /* try to load ourself, will only work if we are a runtime */
254         if (blo_is_a_runtime(progname)) {
255                 bfd= blo_read_runtime(progname, &error);
256                 if (bfd) {
257                         bfd->type= BLENFILETYPE_RUNTIME;
258                         strcpy(bfd->main->name, progname);
259                 }
260         } else {
261                 bfd= BLO_read_from_file(progname, &error);
262         }
263         
264         /*
265         if (bfd && bfd->type == BLENFILETYPE_BLEND) {
266                 BLO_blendfiledata_free(bfd);
267                 bfd = NULL;
268                 error = BRE_NOT_A_PUBFILE;
269         }
270         */
271         
272         if (!bfd && filename) {
273                 bfd = load_game_data(filename);
274                 if (!bfd) {
275                         printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
276                 }
277         }
278         
279         return bfd;
280 }
281
282 int main(int argc, char** argv)
283 {
284         int i;
285         bool error = false;
286         SYS_SystemHandle syshandle = SYS_GetSystem();
287         bool fullScreen = false;
288         bool fullScreenParFound = false;
289         bool windowParFound = false;
290         bool closeConsole = true;
291         RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
292         bool stereoWindow = false;
293         bool stereoParFound = false;
294         int windowLeft = 100;
295         int windowTop = 100;
296         int windowWidth = 640;
297         int windowHeight = 480;
298         GHOST_TUns32 fullScreenWidth = 0;
299         GHOST_TUns32 fullScreenHeight= 0;
300         int fullScreenBpp = 32;
301         int fullScreenFrequency = 60;
302         char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */
303         int pyGlobalDictString_Length = 0;
304         GHOST_TEmbedderWindowID parentWindow = 0;
305
306
307         
308 #ifdef __linux__
309 #ifdef __alpha__
310         signal (SIGFPE, SIG_IGN);
311 #endif /* __alpha__ */
312 #endif /* __linux__ */
313         BLI_where_am_i(bprogname, argv[0]);
314 #ifdef __APPLE__
315     // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
316     /*
317     IBNibRef            nibRef;
318     WindowRef           window;
319     OSStatus            err;
320         
321           // Create a Nib reference passing the name of the nib file (without the .nib extension)
322           // CreateNibReference only searches into the application bundle.
323           err = ::CreateNibReference(CFSTR("main"), &nibRef);
324           if (err) return -1;
325           
326                 // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
327                 // object. This name is set in InterfaceBuilder when the nib is created.
328                 err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
329                 if (err) return -1;
330                 
331                   // We don't need the nib reference anymore.
332                   ::DisposeNibReference(nibRef);
333     */
334 #endif // __APPLE__
335
336         init_nodesystem();
337         
338         GEN_init_messaging_system();
339  
340         // Parse command line options
341 #ifndef NDEBUG
342         printf("argv[0] = '%s'\n", argv[0]);
343 #endif
344
345 #ifdef WIN32
346         if (scr_saver_init(argc, argv))
347         {
348                 switch (scr_saver_mode)
349                 {
350                 case SCREEN_SAVER_MODE_CONFIGURATION:
351                         MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
352                         break;
353                 case SCREEN_SAVER_MODE_PASSWORD:
354                         /* This is W95 only, which we currently do not support.
355                            Fall-back to normal screen saver behaviour in that case... */
356                 case SCREEN_SAVER_MODE_SAVER:
357                         fullScreen = true;
358                         fullScreenParFound = true;
359                         break;
360
361                 case SCREEN_SAVER_MODE_PREVIEW:
362                         /* This will actually be handled somewhere below... */
363                         break;
364                 }
365         }
366 #endif
367         for (i = 1; (i < argc) && !error 
368 #ifdef WIN32
369                 && scr_saver_mode == SCREEN_SAVER_MODE_NONE
370 #endif
371                 ;)
372
373         {
374 #ifndef NDEBUG
375                 printf("argv[%d] = '%s'   , %i\n", i, argv[i],argc);
376 #endif
377                 if (argv[i][0] == '-')
378                 {
379                         switch (argv[i][1])
380                         {
381                         case 'g':
382                                 // Parse game options
383                                 {
384                                         i++;
385                                         if (i < argc)
386                                         {
387                                                 char* paramname = argv[i];
388                                                 // Check for single value versus assignment
389                                                 if (i+1 < argc && (*(argv[i+1]) == '='))
390                                                 {
391                                                         i++;
392                                                         if (i + 1 < argc)
393                                                         {
394                                                                 i++;
395                                                                 // Assignment
396                                                                 SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
397                                                                 SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
398                                                                 SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
399 #ifndef NDEBUG
400                                                                 printf("%s = '%s'\n", paramname, argv[i]);
401 #endif
402                                                                 i++;
403                                                         }
404                                                         else
405                                                         {
406                                                                 error = true;
407                                                                 printf("error: argument assignment %s without value.\n", paramname);
408                                                         }
409                                                 }
410                                                 else
411                                                 {
412 //                                                      SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
413                                                 }
414                                         }
415                                 }
416                                 break;
417                                 
418                         case 'p':
419                                 // Parse window position and size options
420                                 if (argv[i][2] == 0) {
421                                         i++;
422                                         if ((i + 4) < argc)
423                                         {
424                                                 windowLeft = atoi(argv[i++]);
425                                                 windowTop = atoi(argv[i++]);
426                                                 windowWidth = atoi(argv[i++]);
427                                                 windowHeight = atoi(argv[i++]);
428                                                 windowParFound = true;
429                                         }
430                                         else
431                                         {
432                                                 error = true;
433                                                 printf("error: too few options for window argument.\n");
434                                         }
435                                 } else { /* mac specific */
436                                 
437                     if (strncmp(argv[i], "-psn_", 5)==0) 
438                         i++; /* skip process serial number */
439                                 }
440                                 break;
441                         case 'f':
442                                 i++;
443                                 fullScreen = true;
444                                 fullScreenParFound = true;
445                                 if ((i + 2) < argc && argv[i][0] != '-' && argv[i+1][0] != '-')
446                                 {
447                                         fullScreenWidth = atoi(argv[i++]);
448                                         fullScreenHeight = atoi(argv[i++]);
449                                         if ((i + 1) < argc && argv[i][0] != '-')
450                                         {
451                                                 fullScreenBpp = atoi(argv[i++]);
452                                                 if ((i + 1) < argc && argv[i][0] != '-')
453                                                         fullScreenFrequency = atoi(argv[i++]);
454                                         }
455                                 }
456                                 break;
457                         case 'w':
458                                 // Parse window position and size options
459                                 {
460                                         fullScreen = false;
461                                         fullScreenParFound = true;
462                                         i++;
463                                 }
464                                 break;
465                         case 'h':
466                                 usage(argv[0]);
467                                 return 0;
468                                 break;
469 #ifndef _WIN32
470                         case 'i':
471                                 i++;
472                                 if ( (i + 1) < argc )
473                                         parentWindow = atoi(argv[i++]);                                         
474 #ifndef NDEBUG
475                                 printf("XWindows ID = %d\n", parentWindow);
476 #endif //NDEBUG
477
478 #endif  // _WIN32                       
479                         case 'c':
480                                 i++;
481                                 closeConsole = false;
482                                 break;
483                         case 's':  // stereo
484                                 i++;
485                                 if ((i + 1) < argc)
486                                 {
487                                         stereomode = (RAS_IRasterizer::StereoMode) atoi(argv[i]);
488                                         if (stereomode < RAS_IRasterizer::RAS_STEREO_NOSTEREO || stereomode >= RAS_IRasterizer::RAS_STEREO_MAXSTEREO)
489                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
490                                         
491                                         if(!strcmp(argv[i], "nostereo"))  // ok, redundant but clear
492                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
493                                         
494                                         // only the hardware pageflip method needs a stereo window
495                                         if(!strcmp(argv[i], "hwpageflip")) {
496                                                 stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
497                                                 stereoWindow = true;
498                                         }
499                                         if(!strcmp(argv[i], "syncdoubling"))
500                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
501                                         
502                                         if(!strcmp(argv[i], "anaglyph"))
503                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;
504                                         
505                                         if(!strcmp(argv[i], "sidebyside"))
506                                                 stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;
507                                         
508                                         if(!strcmp(argv[i], "vinterlace"))
509                                                 stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;
510                                         
511 #if 0
512                                         // future stuff
513                                         if(strcmp(argv[i], "stencil")
514                                                 stereomode = RAS_STEREO_STENCIL;
515 #endif
516                                         
517                                         i++;
518                                         stereoParFound = true;
519                                 }
520                                 else
521                                 {
522                                         error = true;
523                                         printf("error: too few options for stereo argument.\n");
524                                 }
525                                 break;
526                         default:
527                                 printf("Unkown argument: %s\n", argv[i++]);
528                                 break;
529                         }
530                 }
531                 else
532                 {
533                         i++;
534                 }
535         }
536         
537         if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
538         {
539                 error = true;
540                 printf("error: window size too small.\n");
541         }
542         
543         if (error )
544         {
545                 usage(argv[0]);
546                 return 0;
547         }
548
549 #ifdef WIN32
550         if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
551 #endif
552         {
553 #ifdef __APPLE__
554                 //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
555                 //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
556                 //fullScreen = false;           // Can't use full screen
557 #endif
558
559                 if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
560                 {
561                         GPU_set_mipmap(0);
562                 }
563                 
564                 // Create the system
565                 if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
566                 {
567                         GHOST_ISystem* system = GHOST_ISystem::getSystem();
568                         assertd(system);
569                         
570                         if (!fullScreenWidth || !fullScreenHeight)
571                                 system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
572                         // process first batch of events. If the user
573                         // drops a file on top off the blenderplayer icon, we 
574                         // recieve an event with the filename
575                         
576                         system->processEvents(0);
577                         
578                         // this bracket is needed for app (see below) to get out
579                         // of scope before GHOST_ISystem::disposeSystem() is called.
580                         {
581                                 int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
582                                 STR_String exitstring = "";
583                                 GPG_Application app(system);
584                                 bool firstTimeRunning = true;
585                                 char filename[FILE_MAXDIR + FILE_MAXFILE];
586                                 char *titlename;
587                                 char pathname[160];
588
589                                 get_filename(argc, argv, filename);
590                                 if(filename[0])
591                                         BLI_convertstringcwd(filename);
592                                 
593                                 do
594                                 {
595                                         // Read the Blender file
596                                         BlendFileData *bfd;
597                                         
598                                         // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
599                                         if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
600                                         {
601                                                 char basedpath[240];
602                                                 
603                                                 // base the actuator filename with respect
604                                                 // to the original file working directory
605                                                 strcpy(basedpath, exitstring.Ptr());
606                                                 BLI_convertstringcode(basedpath, pathname);
607                                                 
608                                                 bfd = load_game_data(basedpath);
609
610                                                 if (!bfd)
611                                                 {
612                                                         // just add "//" in front of it
613                                                         char temppath[242];
614                                                         strcpy(temppath, "//");
615                                                         strcat(temppath, basedpath);
616                                 
617                                                         BLI_convertstringcode(temppath, pathname);
618                                                         bfd = load_game_data(temppath);
619                                                 }
620                                         }
621                                         else
622                                         {
623                                                 bfd = load_game_data(bprogname, filename[0]? filename: NULL);
624                                         }
625                                         
626                                         //::printf("game data loaded from %s\n", filename);
627                                         
628                                         if (!bfd) {
629                                                 usage(argv[0]);
630                                                 error = true;
631                                                 exitcode = KX_EXIT_REQUEST_QUIT_GAME;
632                                         } 
633                                         else 
634                                         {
635 #ifdef WIN32
636 #ifdef NDEBUG
637                                                 if (closeConsole)
638                                                 {
639                                                         //::FreeConsole();    // Close a console window
640                                                 }
641 #endif // NDEBUG
642 #endif // WIN32
643                                                 Main *maggie = bfd->main;
644                                                 Scene *scene = bfd->curscene;
645                                                 G.main = maggie;
646                                                 G.fileflags  = bfd->fileflags;
647
648                                                 //Seg Fault; icon.c gIcons == 0
649                                                 BKE_icons_init(1);
650                                                 
651                                                 titlename = maggie->name;
652                                                 
653                                                 // Set the GameLogic.globalDict from marshal'd data, so we can load new blend files
654                                                 // abd keep data in GameLogic.globalDict
655                                                 app.SetPyGlobalDictMarshal(pyGlobalDictString, pyGlobalDictString_Length);
656                                                 
657                                                 // Check whether the game should be displayed full-screen
658                                                 if ((!fullScreenParFound) && (!windowParFound))
659                                                 {
660                                                         // Only use file settings when command line did not override
661                                                         if (scene->r.fullscreen) {
662                                                                 //printf("fullscreen option found in Blender file\n");
663                                                                 fullScreen = true;
664                                                                 fullScreenWidth= scene->r.xplay;
665                                                                 fullScreenHeight= scene->r.yplay;
666                                                                 fullScreenFrequency= scene->r.freqplay;
667                                                                 fullScreenBpp = scene->r.depth;
668                                                         }
669                                                         else
670                                                         {
671                                                                 fullScreen = false;
672                                                                 windowWidth = scene->r.xplay;
673                                                                 windowHeight = scene->r.yplay;
674                                                         }
675                                                 }
676                                                 
677                                                 
678                                                 // Check whether the game should be displayed in stereo
679                                                 if (!stereoParFound)
680                                                 {
681                                                         stereomode = (RAS_IRasterizer::StereoMode) scene->r.stereomode;
682                                                         if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
683                                                                 stereoWindow = true;
684                                                 }
685                                                 
686                                                 //                                      GPG_Application app (system, maggie, startscenename);
687                                                 app.SetGameEngineData(maggie, scene);
688                                                 
689                                                 if (firstTimeRunning)
690                                                 {
691                                                         firstTimeRunning = false;
692
693                                                         // set the filename only the first time as in KetsjiEmbedded
694                                                         strcpy (pathname, maggie->name);
695                                                         // also copy here (used by GameLogic.getBaseDirectory)
696                                                         strcpy (G.sce, maggie->name);
697
698                                                         if (fullScreen)
699                                                         {
700 #ifdef WIN32
701                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
702                                                                 {
703                                                                         app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
704                                                                                 stereoWindow, stereomode);
705                                                                 }
706                                                                 else
707 #endif
708                                                                 {
709                                                                         app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
710                                                                                 stereoWindow, stereomode);
711                                                                 }
712                                                         }
713                                                         else
714                                                         {
715 #ifdef __APPLE__
716                                                                 // on Mac's we'll show the executable name instead of the 'game.blend' name
717                                                                 char tempname[1024], *appstring;
718                                                                 ::strcpy(tempname, titlename);
719                                                                 
720                                                                 appstring = strstr(tempname, ".app/");
721                                                                 if (appstring) {
722                                                                         appstring[2] = 0;
723                                                                         titlename = &tempname[0];
724                                                                 }
725 #endif
726                                                                 // Strip the path so that we have the name of the game file
727                                                                 STR_String path = titlename;
728 #ifndef WIN32
729                                                                 vector<STR_String> parts = path.Explode('/');
730 #else  // WIN32
731                                                                 vector<STR_String> parts = path.Explode('\\');
732 #endif // WIN32                        
733                                                                 STR_String title;
734                                                                 if (parts.size())
735                                                                 {
736                                                                         title = parts[parts.size()-1];
737                                                                         parts = title.Explode('.');
738                                                                         if (parts.size() > 1)
739                                                                         {
740                                                                                 title = parts[0];
741                                                                         }
742                                                                 }
743                                                                 else
744                                                                 {
745                                                                         title = "blenderplayer";
746                                                                 }
747 #ifdef WIN32
748                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
749                                                                 {
750                                                                         app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode);
751                                                                 }
752                                                                 else
753 #endif
754                                                                 {
755                                                                                                                                                                                                                 if (parentWindow != 0)
756                                                                                 app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode);
757                                                                         else
758                                                                                 app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
759                                                                                 stereoWindow, stereomode);
760                                                                 }
761                                                         }
762                                                 }
763                                                 else
764                                                 {
765                                                         app.StartGameEngine(stereomode);
766                                                         exitcode = KX_EXIT_REQUEST_NO_REQUEST;
767                                                 }
768                                                 
769                                                 // Add the application as event consumer
770                                                 system->addEventConsumer(&app);
771                                                 
772                                                 // Enter main loop
773                                                 bool run = true;
774                                                 while (run)
775                                                 {
776                                                         system->processEvents(false);
777                                                         system->dispatchEvents();
778                                                         if ((exitcode = app.getExitRequested()))
779                                                         {
780                                                                 run = false;
781                                                                 exitstring = app.getExitString();
782                                                         }
783                                                 }
784                                                 app.StopGameEngine();
785                                                 
786                                                 // GameLogic.globalDict has been converted into a buffer
787                                                 // store in pyGlobalDictString so we can restore after python has stopped and started.
788                                                 pyGlobalDictString = app.GetPyGlobalDictMarshal();
789                                                 pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength();
790                                                 
791                                                 BLO_blendfiledata_free(bfd);
792                                         }
793                                 } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
794                         }
795
796                         // Seg Fault; icon.c gIcons == 0
797                         BKE_icons_free();
798
799                         // Dispose the system
800                         GHOST_ISystem::disposeSystem();
801                 } else {
802                         error = true;
803                         printf("error: couldn't create a system.\n");
804                 }
805         }
806
807         free_nodesystem();
808
809         if (pyGlobalDictString) {
810                 free(pyGlobalDictString);
811                 pyGlobalDictString = NULL;
812         }
813         
814         return error ? -1 : 0;
815 }
816
817