- add convenience functions BLI_split_dir_part / BLI_split_file_part, which just...
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file gameengine/GamePlayer/ghost/GPG_ghost.cpp
32  *  \ingroup player
33  */
34
35
36 #include <iostream>
37 #include <math.h>
38
39 #ifdef __linux__
40 #ifdef __alpha__
41 #include <signal.h>
42 #endif /* __alpha__ */
43 #endif /* __linux__ */
44
45 #ifdef __APPLE__
46 // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
47 //#include <Carbon/Carbon.h>
48 //#include <CFBundle.h>
49 #endif // __APPLE__
50 #include "KX_KetsjiEngine.h"
51 #include "KX_PythonInit.h"
52
53 /**********************************
54 * Begin Blender include block
55 **********************************/
56 #ifdef __cplusplus
57 extern "C"
58 {
59 #endif  // __cplusplus
60 #include "MEM_guardedalloc.h"
61 #include "BKE_blender.h"        
62 #include "BKE_global.h" 
63 #include "BKE_icons.h"  
64 #include "BKE_node.h"   
65 #include "BKE_report.h"
66 #include "BKE_library.h"
67 #include "BLI_threads.h"
68 #include "BLI_blenlib.h"
69 #include "DNA_scene_types.h"
70 #include "DNA_userdef_types.h"
71 #include "BLO_readfile.h"
72 #include "BLO_runtime.h"
73 #include "IMB_imbuf.h"
74 #include "BKE_text.h"
75 #include "BKE_sound.h"
76         
77         int GHOST_HACK_getFirstFile(char buf[]);
78         
79 extern char bprogname[];        /* holds a copy of argv[0], from creator.c */
80 extern char btempdir[];         /* use this to store a valid temp directory */
81
82 // For BLF
83 #include "BLF_api.h"
84 #include "BLF_translation.h"
85 extern int datatoc_bfont_ttf_size;
86 extern char datatoc_bfont_ttf[];
87
88 #ifdef __cplusplus
89 }
90 #endif // __cplusplus
91
92 #include "GPU_draw.h"
93
94 /**********************************
95 * End Blender include block
96 **********************************/
97
98 #include "BL_System.h"
99 #include "GPG_Application.h"
100
101 #include "GHOST_ISystem.h"
102 #include "RAS_IRasterizer.h"
103
104 #include "BKE_main.h"
105 #include "BKE_utildefines.h"
106
107 #include "RNA_define.h"
108
109 #ifdef WIN32
110 #include <windows.h>
111 #if !defined(DEBUG)
112 #include <wincon.h>
113 #endif // !defined(DEBUG)
114 #endif // WIN32
115
116 const int kMinWindowWidth = 100;
117 const int kMinWindowHeight = 100;
118
119 char bprogname[FILE_MAX];
120 char bprogdir[FILE_MAX];
121
122 static void mem_error_cb(const char *errorStr)
123 {
124         fprintf(stderr, "%s", errorStr);
125         fflush(stderr);
126 }
127
128 #ifdef WIN32
129 typedef enum 
130 {
131   SCREEN_SAVER_MODE_NONE = 0,
132   SCREEN_SAVER_MODE_PREVIEW,
133   SCREEN_SAVER_MODE_SAVER,
134   SCREEN_SAVER_MODE_CONFIGURATION,
135   SCREEN_SAVER_MODE_PASSWORD,
136 } ScreenSaverMode;
137
138 static ScreenSaverMode scr_saver_mode = SCREEN_SAVER_MODE_NONE;
139 static HWND scr_saver_hwnd = NULL;
140
141 static BOOL scr_saver_init(int argc, char **argv) 
142 {
143         scr_saver_mode = SCREEN_SAVER_MODE_NONE;
144         scr_saver_hwnd = NULL;
145         BOOL ret = FALSE;
146
147         int len = ::strlen(argv[0]);
148         if (len > 4 && !::stricmp(".scr", argv[0] + len - 4))
149         {
150                 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
151                 ret = TRUE;
152                 if (argc >= 2)
153                 {
154                         if (argc >= 3)
155                         {
156                                 scr_saver_hwnd = (HWND) ::atoi(argv[2]);
157                         }
158                         if (!::stricmp("/c", argv[1]))
159                         {
160                                 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
161                                 if (scr_saver_hwnd == NULL)
162                                         scr_saver_hwnd = ::GetForegroundWindow();
163                         }
164                         else if (!::stricmp("/s", argv[1]))
165                         {
166                                 scr_saver_mode = SCREEN_SAVER_MODE_SAVER;
167                         }
168                         else if (!::stricmp("/a", argv[1]))
169                         {
170                                 scr_saver_mode = SCREEN_SAVER_MODE_PASSWORD;
171                         }
172                         else if (!::stricmp("/p", argv[1])
173                                  || !::stricmp("/l", argv[1]))
174                         {
175                                 scr_saver_mode = SCREEN_SAVER_MODE_PREVIEW;
176                         }
177                 }
178         }
179         return ret;
180 }
181
182 #endif /* WIN32 */
183
184 void usage(const char* program, bool isBlenderPlayer)
185 {
186         const char * consoleoption;
187         const char * filename = "";
188         const char * pathname = "";
189
190 #ifdef _WIN32
191         consoleoption = "-c ";
192 #else
193         consoleoption = "";
194 #endif
195
196         if (isBlenderPlayer) {
197                 filename = "filename.blend";
198 #ifdef _WIN32
199                 pathname = "c:\\";
200 #else
201                 pathname = "//home//user//";
202 #endif
203         }
204         
205         printf("usage:   %s [-w [w h l t]] [-f [fw fh fb ff]] %s[-g gamengineoptions] "
206                 "[-s stereomode] [-m aasamples] %s\n", program, consoleoption, filename);
207         printf("  -h: Prints this command summary\n\n");
208         printf("  -w: display in a window\n");
209         printf("       --Optional parameters--\n"); 
210         printf("       w = window width\n");
211         printf("       h = window height\n\n");
212         printf("       l = window left coordinate\n");
213         printf("       t = window top coordinate\n");
214         printf("       Note: If w or h is defined, both must be defined.\n");
215         printf("          Also, if l or t is defined, all options must be used.\n\n");
216         printf("  -f: start game in full screen mode\n");
217         printf("       --Optional parameters--\n");
218         printf("       fw = full screen mode pixel width\n");
219         printf("       fh = full screen mode pixel height\n\n");
220         printf("       fb = full screen mode bits per pixel\n");
221         printf("       ff = full screen mode frequency\n");
222         printf("       Note: If fw or fh is defined, both must be defined.\n");
223         printf("          Also, if fb is used, fw and fh must be used. ff requires all options.\n\n");
224         printf("  -s: start player in stereo\n");
225         printf("       stereomode: hwpageflip       (Quad buffered shutter glasses)\n");
226         printf("                   syncdoubling     (Above Below)\n");
227         printf("                   sidebyside       (Left Right)\n");
228         printf("                   anaglyph         (Red-Blue glasses)\n");
229         printf("                   vinterlace       (Vertical interlace for autostereo display)\n");
230         printf("                             depending on the type of stereo you want\n\n");
231         printf("  -D: start player in dome mode\n");
232         printf("       --Optional parameters--\n");
233         printf("       angle    = field of view in degrees\n");
234         printf("       tilt     = tilt angle in degrees\n");
235         printf("       warpdata = a file to use for warping the image (absolute path)\n");      
236         printf("       mode: fisheye                (Fisheye)\n");
237         printf("             truncatedfront         (Front-Truncated)\n");
238         printf("             truncatedrear          (Rear-Truncated)\n");
239         printf("             cubemap                (Cube Map)\n");
240         printf("             sphericalpanoramic     (Spherical Panoramic)\n");
241         printf("                             depending on the type of dome you are using\n\n");
242         printf("  -m: maximum anti-aliasing (eg. 2,4,8,16)\n\n");
243         printf("  -i: parent windows ID \n\n");
244 #ifdef _WIN32
245         printf("  -c: keep console window open\n\n");
246 #endif
247         printf("  -d: turn debugging on\n\n");
248         printf("  -g: game engine options:\n\n");
249         printf("       Name                       Default      Description\n");
250         printf("       ------------------------------------------------------------------------\n");
251         printf("       fixedtime                      0         \"Enable all frames\"\n");
252         printf("       nomipmap                       0         Disable mipmaps\n");
253         printf("       show_framerate                 0         Show the frame rate\n");
254         printf("       show_properties                0         Show debug properties\n");
255         printf("       show_profile                   0         Show profiling information\n");
256         printf("       blender_material               0         Enable material settings\n");
257         printf("       ignore_deprecation_warnings    1         Ignore deprecation warnings\n");
258         printf("\n");
259         printf("  - : all arguments after this are ignored, allowing python to access them from sys.argv\n");
260         printf("\n");
261         printf("example: %s -w 320 200 10 10 -g noaudio%s%s\n", program, pathname, filename);
262         printf("example: %s -g show_framerate = 0 %s%s\n", program, pathname, filename);
263         printf("example: %s -i 232421 -m 16 %s%s\n\n", program, pathname, filename);
264 }
265
266 static void get_filename(int argc, char **argv, char *filename)
267 {
268 #ifdef __APPLE__
269 /* On Mac we park the game file (called game.blend) in the application bundle.
270 * The executable is located in the bundle as well.
271 * Therefore, we can locate the game relative to the executable.
272         */
273         int srclen = ::strlen(argv[0]);
274         int len = 0;
275         char *gamefile = NULL;
276         
277         filename[0] = '\0';
278
279         if (argc > 1) {
280                 if (BLI_exists(argv[argc-1])) {
281                         BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
282                 }
283                 if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
284                         static char firstfilebuf[512];
285                         if (GHOST_HACK_getFirstFile(firstfilebuf)) {
286                                 BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE);
287                         }
288                 }                        
289         }
290         
291         srclen -= ::strlen("MacOS/blenderplayer");
292         if (srclen > 0) {
293                 len = srclen + ::strlen("Resources/game.blend"); 
294                 gamefile = new char [len + 1];
295                 ::strcpy(gamefile, argv[0]);
296                 ::strcpy(gamefile + srclen, "Resources/game.blend");
297                 //::printf("looking for file: %s\n", filename);
298                 
299                 if (BLI_exists(gamefile))
300                         BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE);
301
302                 delete [] gamefile;
303         }
304         
305 #else
306         filename[0] = '\0';
307
308         if(argc > 1)
309                 BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
310 #endif // !_APPLE
311 }
312
313 static BlendFileData *load_game_data(const char *progname, char *filename = NULL, char *relativename = NULL)
314 {
315         ReportList reports;
316         BlendFileData *bfd = NULL;
317
318         BKE_reports_init(&reports, RPT_STORE);
319         
320         /* try to load ourself, will only work if we are a runtime */
321         if (BLO_is_a_runtime(progname)) {
322                 bfd= BLO_read_runtime(progname, &reports);
323                 if (bfd) {
324                         bfd->type= BLENFILETYPE_RUNTIME;
325                         BLI_strncpy(bfd->main->name, progname, sizeof(bfd->main->name));
326                 }
327         } else {
328                 bfd= BLO_read_from_file(progname, &reports);
329         }
330         
331         if (!bfd && filename) {
332                 bfd = load_game_data(filename);
333                 if (!bfd) {
334                         printf("Loading %s failed: ", filename);
335                         BKE_reports_print(&reports, RPT_ERROR);
336                 }
337         }
338
339         BKE_reports_clear(&reports);
340         
341         return bfd;
342 }
343
344 int main(int argc, char** argv)
345 {
346         int i;
347         int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */
348         bool error = false;
349         SYS_SystemHandle syshandle = SYS_GetSystem();
350         bool fullScreen = false;
351         bool fullScreenParFound = false;
352         bool windowParFound = false;
353 #ifdef WIN32
354         bool closeConsole = true;
355 #endif
356         RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
357         bool stereoWindow = false;
358         bool stereoParFound = false;
359         int stereoFlag = STEREO_NOSTEREO;
360         int domeFov = -1;
361         int domeTilt = -200;
362         int domeMode = 0;
363         char* domeWarp = NULL;
364         Text *domeText  = NULL;
365         int windowLeft = 100;
366         int windowTop = 100;
367         int windowWidth = 640;
368         int windowHeight = 480;
369         GHOST_TUns32 fullScreenWidth = 0;
370         GHOST_TUns32 fullScreenHeight= 0;
371         int fullScreenBpp = 32;
372         int fullScreenFrequency = 60;
373         GHOST_TEmbedderWindowID parentWindow = 0;
374         bool isBlenderPlayer = false;
375         int validArguments=0;
376         GHOST_TUns16 aasamples = 0;
377         
378 #ifdef __linux__
379 #ifdef __alpha__
380         signal (SIGFPE, SIG_IGN);
381 #endif /* __alpha__ */
382 #endif /* __linux__ */
383         BLI_where_am_i(bprogname, sizeof(bprogname), argv[0]);
384         BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
385 #ifdef __APPLE__
386         // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
387         /*
388         IBNibRef                nibRef;
389         WindowRef               window;
390         OSStatus                err;
391
392           // Create a Nib reference passing the name of the nib file (without the .nib extension)
393           // CreateNibReference only searches into the application bundle.
394           err = ::CreateNibReference(CFSTR("main"), &nibRef);
395           if (err) return -1;
396           
397                 // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
398                 // object. This name is set in InterfaceBuilder when the nib is created.
399                 err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
400                 if (err) return -1;
401                 
402                   // We don't need the nib reference anymore.
403                   ::DisposeNibReference(nibRef);
404         */
405 #endif // __APPLE__
406         
407         // We don't use threads directly in the BGE, but we need to call this so things like
408         // freeing up GPU_Textures works correctly.
409         BLI_threadapi_init();
410
411         RNA_init();
412
413         init_nodesystem();
414         
415         initglobals();
416
417         // We load our own G.main, so free the one that initglobals() gives us
418         free_main(G.main);
419         G.main = NULL;
420
421         IMB_init();
422
423         // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
424         BLF_init(11, U.dpi);
425         BLF_lang_init();
426         BLF_lang_encoding("");
427         BLF_lang_set("");
428
429         BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
430
431         // Parse command line options
432 #if defined(DEBUG)
433         printf("argv[0] = '%s'\n", argv[0]);
434 #endif
435
436 #ifdef WIN32
437         if (scr_saver_init(argc, argv))
438         {
439                 switch (scr_saver_mode)
440                 {
441                 case SCREEN_SAVER_MODE_CONFIGURATION:
442                         MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
443                         break;
444                 case SCREEN_SAVER_MODE_PASSWORD:
445                         /* This is W95 only, which we currently do not support.
446                            Fall-back to normal screen saver behaviour in that case... */
447                 case SCREEN_SAVER_MODE_SAVER:
448                         fullScreen = true;
449                         fullScreenParFound = true;
450                         break;
451
452                 case SCREEN_SAVER_MODE_PREVIEW:
453                         /* This will actually be handled somewhere below... */
454                         break;
455                 }
456         }
457 #endif
458         // XXX add the ability to change this values to the command line parsing.
459         U.mixbufsize = 2048;
460         U.audiodevice = 2;
461         U.audiorate = 44100;
462         U.audioformat = 0x24;
463         U.audiochannels = 2;
464
465         // XXX this one too
466         U.anisotropic_filter = 2;
467
468         sound_init_once();
469
470         /* if running blenderplayer the last argument can't be parsed since it has to be the filename. */
471         isBlenderPlayer = !BLO_is_a_runtime(argv[0]);
472         if (isBlenderPlayer)
473                 validArguments = argc - 1;
474         else
475                 validArguments = argc;
476
477         for (i = 1; (i < validArguments) && !error 
478 #ifdef WIN32
479                 && scr_saver_mode == SCREEN_SAVER_MODE_NONE
480 #endif
481                 ;)
482
483         {
484 #if defined(DEBUG)
485                 printf("argv[%d] = '%s'   , %i\n", i, argv[i],argc);
486 #endif
487                 if (argv[i][0] == '-')
488                 {
489                         /* ignore all args after " - ", allow python to have own args */
490                         if (argv[i][1]=='\0') {
491                                 argc_py_clamped= i;
492                                 break;
493                         }
494                         
495                         switch (argv[i][1])
496                         {
497                         case 'g':
498                                 // Parse game options
499                                 {
500                                         i++;
501                                         if (i <= validArguments)
502                                         {
503                                                 char* paramname = argv[i];
504                                                 // Check for single value versus assignment
505                                                 if (i+1 <= validArguments && (*(argv[i+1]) == '='))
506                                                 {
507                                                         i++;
508                                                         if (i + 1 <= validArguments)
509                                                         {
510                                                                 i++;
511                                                                 // Assignment
512                                                                 SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
513                                                                 SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
514                                                                 SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
515 #if defined(DEBUG)
516                                                                 printf("%s = '%s'\n", paramname, argv[i]);
517 #endif
518                                                                 i++;
519                                                         }
520                                                         else
521                                                         {
522                                                                 error = true;
523                                                                 printf("error: argument assignment %s without value.\n", paramname);
524                                                         }
525                                                 }
526                                                 else
527                                                 {
528 //                                                      SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
529                                                 }
530                                         }
531                                 }
532                                 break;
533
534                         case 'd':
535                                 i++;
536                                 G.f |= G_DEBUG;     /* std output printf's */
537                                 MEM_set_memory_debug();
538                                 break;
539
540                         case 'f':
541                                 i++;
542                                 fullScreen = true;
543                                 fullScreenParFound = true;
544                                 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
545                                 {
546                                         fullScreenWidth = atoi(argv[i++]);
547                                         fullScreenHeight = atoi(argv[i++]);
548                                         if ((i + 1) <= validArguments && argv[i][0] != '-')
549                                         {
550                                                 fullScreenBpp = atoi(argv[i++]);
551                                                 if ((i + 1) <= validArguments && argv[i][0] != '-')
552                                                         fullScreenFrequency = atoi(argv[i++]);
553                                         }
554                                 }
555                                 break;
556                         case 'w':
557                                 // Parse window position and size options
558                                 i++;
559                                 fullScreen = false;
560                                 windowParFound = true;
561
562                                 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
563                                 {
564                                         windowWidth = atoi(argv[i++]);
565                                         windowHeight = atoi(argv[i++]);
566                                         if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
567                                         {
568                                                 windowLeft = atoi(argv[i++]);
569                                                 windowTop = atoi(argv[i++]);
570                                         }
571                                 }
572                                 break;
573                                         
574                         case 'h':
575                                 usage(argv[0], isBlenderPlayer);
576                                 return 0;
577                                 break;
578                         case 'i':
579                                 i++;
580                                 if ( (i + 1) <= validArguments )
581                                         parentWindow = atoi(argv[i++]); 
582                                 else {
583                                         error = true;
584                                         printf("error: too few options for parent window argument.\n");
585                                 }
586 #if defined(DEBUG)
587                                 printf("XWindows ID = %d\n", parentWindow);
588 #endif // defined(DEBUG)
589                                 break;
590                         case 'm':
591                                 i++;
592                                 if ((i+1) <= validArguments )
593                                 aasamples = atoi(argv[i++]);
594                                 break;
595                         case 'c':
596                                 i++;
597 #ifdef WIN32
598                                 closeConsole = false;
599 #endif
600                                 break;
601                         case 's':  // stereo
602                                 i++;
603                                 if ((i + 1) <= validArguments)
604                                 {
605                                         stereomode = (RAS_IRasterizer::StereoMode) atoi(argv[i]);
606                                         if (stereomode < RAS_IRasterizer::RAS_STEREO_NOSTEREO || stereomode >= RAS_IRasterizer::RAS_STEREO_MAXSTEREO)
607                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
608                                         
609                                         if(!strcmp(argv[i], "nostereo"))  // ok, redundant but clear
610                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
611                                         
612                                         // only the hardware pageflip method needs a stereo window
613                                         else if(!strcmp(argv[i], "hwpageflip")) {
614                                                 stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
615                                                 stereoWindow = true;
616                                         }
617                                         else if(!strcmp(argv[i], "syncdoubling"))
618                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
619                                         
620                                         else if(!strcmp(argv[i], "anaglyph"))
621                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;
622                                         
623                                         else if(!strcmp(argv[i], "sidebyside"))
624                                                 stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;
625                                         
626                                         else if(!strcmp(argv[i], "vinterlace"))
627                                                 stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;
628                                         
629 #if 0
630                                         // future stuff
631                                         else if(!strcmp(argv[i], "stencil")
632                                                 stereomode = RAS_STEREO_STENCIL;
633 #endif
634                                         
635                                         i++;
636                                         stereoParFound = true;
637                                         stereoFlag = STEREO_ENABLED;
638                                 }
639                                 else
640                                 {
641                                         error = true;
642                                         printf("error: too few options for stereo argument.\n");
643                                 }
644                                 break;
645                         case 'D':
646                                 stereoFlag = STEREO_DOME;
647                                 stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
648                                 i++;
649                                 if ((i + 1) <= validArguments)
650                                 {
651                                         if(!strcmp(argv[i], "angle")){
652                                                 i++;
653                                                 domeFov = atoi(argv[i++]);
654                                         }
655                                         if(!strcmp(argv[i], "tilt")){
656                                                 i++;
657                                                 domeTilt = atoi(argv[i++]);
658                                         }
659                                         if(!strcmp(argv[i], "warpdata")){
660                                                 i++;
661                                                 domeWarp = argv[i++];
662                                         }
663                                         if(!strcmp(argv[i], "mode")){
664                                                 i++;
665                                                 if(!strcmp(argv[i], "fisheye"))
666                                                         domeMode = DOME_FISHEYE;
667                                                         
668                                                 else if(!strcmp(argv[i], "truncatedfront"))
669                                                         domeMode = DOME_TRUNCATED_FRONT;
670                                                         
671                                                 else if(!strcmp(argv[i], "truncatedrear"))
672                                                         domeMode = DOME_TRUNCATED_REAR;
673                                                         
674                                                 else if(!strcmp(argv[i], "cubemap"))
675                                                         domeMode = DOME_ENVMAP;
676                                                         
677                                                 else if(!strcmp(argv[i], "sphericalpanoramic"))
678                                                         domeMode = DOME_PANORAM_SPH;
679
680                                                 else
681                                                         printf("error: %s is not a valid dome mode.\n", argv[i]);
682                                         }
683                                         i++;
684                                 }
685                                 break;
686                         default:
687                                 printf("Unknown argument: %s\n", argv[i++]);
688                                 break;
689                         }
690                 }
691                 else
692                 {
693                         i++;
694                 }
695         }
696         
697         if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
698         {
699                 error = true;
700                 printf("error: window size too small.\n");
701         }
702         
703         if (error )
704         {
705                 usage(argv[0], isBlenderPlayer);
706                 return 0;
707         }
708
709 #ifdef WIN32
710         if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
711 #endif
712         {
713 #ifdef __APPLE__
714                 //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
715                 //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
716                 //fullScreen = false;           // Can't use full screen
717 #endif
718
719                 if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
720                 {
721                         GPU_set_mipmap(0);
722                 }
723
724                 GPU_set_anisotropic(U.anisotropic_filter);
725                 
726                 // Create the system
727                 if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
728                 {
729                         GHOST_ISystem* system = GHOST_ISystem::getSystem();
730                         assertd(system);
731                         
732                         if (!fullScreenWidth || !fullScreenHeight)
733                                 system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
734                         // process first batch of events. If the user
735                         // drops a file on top off the blenderplayer icon, we 
736                         // receive an event with the filename
737                         
738                         system->processEvents(0);
739                         
740                         // this bracket is needed for app (see below) to get out
741                         // of scope before GHOST_ISystem::disposeSystem() is called.
742                         {
743                                 int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
744                                 STR_String exitstring = "";
745                                 GPG_Application app(system);
746                                 bool firstTimeRunning = true;
747                                 char filename[FILE_MAXDIR + FILE_MAXFILE];
748                                 char pathname[FILE_MAXDIR + FILE_MAXFILE];
749                                 char *titlename;
750
751                                 get_filename(argc_py_clamped, argv, filename);
752                                 if(filename[0])
753                                         BLI_path_cwd(filename);
754                                 
755
756                                 // fill the GlobalSettings with the first scene files
757                                 // those may change during the game and persist after using Game Actuator
758                                 GlobalSettings gs;
759
760                                 do
761                                 {
762                                         // Read the Blender file
763                                         BlendFileData *bfd;
764                                         
765                                         // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
766                                         if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
767                                         {
768                                                 char basedpath[240];
769                                                 
770                                                 // base the actuator filename relative to the last file
771                                                 BLI_strncpy(basedpath, exitstring.Ptr(), sizeof(basedpath));
772                                                 BLI_path_abs(basedpath, pathname);
773                                                 
774                                                 bfd = load_game_data(basedpath);
775
776                                                 if (!bfd)
777                                                 {
778                                                         // just add "//" in front of it
779                                                         char temppath[242];
780                                                         strcpy(temppath, "//");
781                                                         strcat(temppath, basedpath);
782                                 
783                                                         BLI_path_abs(temppath, pathname);
784                                                         bfd = load_game_data(temppath);
785                                                 }
786                                         }
787                                         else
788                                         {
789                                                 bfd = load_game_data(bprogname, filename[0]? filename: NULL);
790                                         }
791                                         
792                                         //::printf("game data loaded from %s\n", filename);
793                                         
794                                         if (!bfd) {
795                                                 usage(argv[0], isBlenderPlayer);
796                                                 error = true;
797                                                 exitcode = KX_EXIT_REQUEST_QUIT_GAME;
798                                         } 
799                                         else 
800                                         {
801 #ifdef WIN32
802 #if !defined(DEBUG)
803                                                 if (closeConsole)
804                                                 {
805                                                         //::FreeConsole();    // Close a console window
806                                                 }
807 #endif // !defined(DEBUG)
808 #endif // WIN32
809                                                 Main *maggie = bfd->main;
810                                                 Scene *scene = bfd->curscene;
811                                                 G.main = maggie;
812
813                                                 if (firstTimeRunning) {
814                                                         G.fileflags  = bfd->fileflags;
815
816                                                         gs.matmode= scene->gm.matmode;
817                                                         gs.glslflag= scene->gm.flag;
818                                                 }
819
820                                                 //Seg Fault; icon.c gIcons == 0
821                                                 BKE_icons_init(1);
822                                                 
823                                                 titlename = maggie->name;
824                                                 
825                                                 // Check whether the game should be displayed full-screen
826                                                 if ((!fullScreenParFound) && (!windowParFound))
827                                                 {
828                                                         // Only use file settings when command line did not override
829                                                         if (scene->gm.fullscreen) {
830                                                                 //printf("fullscreen option found in Blender file\n");
831                                                                 fullScreen = true;
832                                                                 fullScreenWidth= scene->gm.xplay;
833                                                                 fullScreenHeight= scene->gm.yplay;
834                                                                 fullScreenFrequency= scene->gm.freqplay;
835                                                                 fullScreenBpp = scene->gm.depth;
836                                                         }
837                                                         else
838                                                         {
839                                                                 fullScreen = false;
840                                                                 windowWidth = scene->gm.xplay;
841                                                                 windowHeight = scene->gm.yplay;
842                                                         }
843                                                 }
844                                                 
845                                                 
846                                                 // Check whether the game should be displayed in stereo
847                                                 if (!stereoParFound)
848                                                 {
849                                                         if(scene->gm.stereoflag == STEREO_ENABLED){
850                                                                 stereomode = (RAS_IRasterizer::StereoMode) scene->gm.stereomode;
851                                                                 if (stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
852                                                                         stereoWindow = true;
853                                                         }
854                                                 }
855                                                 else
856                                                         scene->gm.stereoflag = STEREO_ENABLED;
857
858                                                 if (stereoFlag == STEREO_DOME){
859                                                         stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
860                                                         scene->gm.stereoflag = STEREO_DOME;
861                                                         if (domeFov > 89)
862                                                                 scene->gm.dome.angle = domeFov;
863                                                         if (domeTilt > -180)
864                                                                 scene->gm.dome.tilt = domeTilt;
865                                                         if (domeMode > 0)
866                                                                 scene->gm.dome.mode = domeMode;
867                                                         if (domeWarp)
868                                                         {
869                                                                 //XXX to do: convert relative to absolute path
870                                                                 domeText= add_text(domeWarp, "");
871                                                                 if(!domeText)
872                                                                         printf("error: invalid warpdata text file - %s\n", domeWarp);
873                                                                 else
874                                                                         scene->gm.dome.warptext = domeText;
875                                                         }
876                                                 }
877                                                 
878                                                 //                                      GPG_Application app (system, maggie, startscenename);
879                                                 app.SetGameEngineData(maggie, scene, &gs, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */
880                                                 BLI_strncpy(pathname, maggie->name, sizeof(pathname));
881                                                 if(G.main != maggie) {
882                                                         BLI_strncpy(G.main->name, maggie->name, sizeof(G.main->name));
883                                                 }
884 #ifdef WITH_PYTHON
885                                                 setGamePythonPath(G.main->name);
886 #endif
887                                                 if (firstTimeRunning)
888                                                 {
889                                                         firstTimeRunning = false;
890
891                                                         if (fullScreen)
892                                                         {
893 #ifdef WIN32
894                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
895                                                                 {
896                                                                         app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
897                                                                                 stereoWindow, stereomode, aasamples);
898                                                                 }
899                                                                 else
900 #endif
901                                                                 {
902                                                                         app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
903                                                                                 stereoWindow, stereomode, aasamples);
904                                                                 }
905                                                         }
906                                                         else
907                                                         {
908 #ifdef __APPLE__
909                                                                 // on Mac's we'll show the executable name instead of the 'game.blend' name
910                                                                 char tempname[1024], *appstring;
911                                                                 ::strcpy(tempname, titlename);
912                                                                 
913                                                                 appstring = strstr(tempname, ".app/");
914                                                                 if (appstring) {
915                                                                         appstring[2] = 0;
916                                                                         titlename = &tempname[0];
917                                                                 }
918 #endif
919                                                                 // Strip the path so that we have the name of the game file
920                                                                 STR_String path = titlename;
921 #ifndef WIN32
922                                                                 vector<STR_String> parts = path.Explode('/');
923 #else  // WIN32
924                                                                 vector<STR_String> parts = path.Explode('\\');
925 #endif // WIN32                        
926                                                                 STR_String title;
927                                                                 if (parts.size())
928                                                                 {
929                                                                         title = parts[parts.size()-1];
930                                                                         parts = title.Explode('.');
931                                                                         if (parts.size() > 1)
932                                                                         {
933                                                                                 title = parts[0];
934                                                                         }
935                                                                 }
936                                                                 else
937                                                                 {
938                                                                         title = "blenderplayer";
939                                                                 }
940 #ifdef WIN32
941                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
942                                                                 {
943                                                                         app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode, aasamples);
944                                                                 }
945                                                                 else
946 #endif
947                                                                 {
948                                                                                                                                                                                                                 if (parentWindow != 0)
949                                                                                 app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode, aasamples);
950                                                                         else
951                                                                                 app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
952                                                                                 stereoWindow, stereomode, aasamples);
953                                                                 }
954                                                         }
955                                                 }
956                                                 else
957                                                 {
958                                                         app.StartGameEngine(stereomode);
959                                                         exitcode = KX_EXIT_REQUEST_NO_REQUEST;
960                                                 }
961                                                 
962                                                 // Add the application as event consumer
963                                                 system->addEventConsumer(&app);
964                                                 
965                                                 // Enter main loop
966                                                 bool run = true;
967                                                 while (run)
968                                                 {
969                                                         system->processEvents(false);
970                                                         system->dispatchEvents();
971                                                         if ((exitcode = app.getExitRequested()))
972                                                         {
973                                                                 run = false;
974                                                                 exitstring = app.getExitString();
975                                                                 gs = *app.getGlobalSettings();
976                                                         }
977                                                 }
978                                                 app.StopGameEngine();
979
980                                                 /* 'app' is freed automatic when out of scope. 
981                                                  * removal is needed else the system will free an already freed value */
982                                                 system->removeEventConsumer(&app);
983
984                                                 BLO_blendfiledata_free(bfd);
985                                         }
986                                 } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
987                         }
988
989                         // Seg Fault; icon.c gIcons == 0
990                         BKE_icons_free();
991
992                         // Dispose the system
993                         GHOST_ISystem::disposeSystem();
994                 } else {
995                         error = true;
996                         printf("error: couldn't create a system.\n");
997                 }
998         }
999
1000         // Cleanup
1001         RNA_exit();
1002         BLF_exit();
1003
1004 #ifdef WITH_INTERNATIONAL
1005         BLF_free_unifont();
1006 #endif
1007
1008         IMB_exit();
1009         free_nodesystem();
1010
1011         SYS_DeleteSystem(syshandle);
1012
1013         int totblock= MEM_get_memory_blocks_in_use();
1014         if(totblock!=0) {
1015                 printf("Error Totblock: %d\n",totblock);
1016                 MEM_set_error_callback(mem_error_cb);
1017                 MEM_printmemlist();
1018         }
1019
1020         return error ? -1 : 0;
1021 }
1022
1023