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