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