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