1 // main.cpp: initialisation & main loop
12 extern void clear_command(); clear_command();
13 extern void clear_console(); clear_console();
14 extern void clear_mdls(); clear_mdls();
15 extern void clear_sound(); clear_sound();
19 void quit() // normal exit
21 extern void writeinitcfg();
31 void fatal(const char *s
, ...) // failure exit
34 s_sprintfdlv(msg
,s
,s
);
37 MessageBox(NULL
, msg
, "sauerbraten fatal error", MB_OK
|MB_SYSTEMMODAL
);
43 double getaccurateticks()
46 LARGE_INTEGER count
, freq
;
47 QueryPerformanceCounter(&count
);
48 QueryPerformanceFrequency(&freq
);
49 return double(count
.QuadPart
)/double(freq
.QuadPart
)*1000;
51 return SDL_GetTicks(); // FIXME: do something equally good on linux etc
55 SDL_Surface
*screen
= NULL
;
58 int totalmillis
= 0, lastmillis
= 0;
60 dynent
*player
= NULL
;
62 static bool initing
= false, restoredinits
= false;
67 if(restoredinits
) conoutf("Please restart Sauerbraten for this setting to take effect.");
68 else conoutf("Please restart Sauerbraten with the -r command-line option for this setting to take effect.");
73 VARF(scr_w
, 320, 1024, 10000, initwarning());
74 VARF(scr_h
, 200, 768, 10000, initwarning());
75 VARF(colorbits
, 0, 0, 32, initwarning());
76 VARF(depthbits
, 0, 0, 32, initwarning());
77 VARF(stencilbits
, 0, 1, 32, initwarning());
78 VARF(fsaa
, 0, 0, 16, initwarning());
79 VARF(vsync
, -1, -1, 1, initwarning());
83 FILE *f
= openfile("init.cfg", "w");
85 fprintf(f
, "// automatically written on exit, DO NOT MODIFY\n// modify settings in game\n");
86 fprintf(f
, "scr_w %d\n", scr_w
);
87 fprintf(f
, "scr_h %d\n", scr_h
);
88 fprintf(f
, "colorbits %d\n", colorbits
);
89 fprintf(f
, "depthbits %d\n", depthbits
);
90 fprintf(f
, "stencilbits %d\n", stencilbits
);
91 fprintf(f
, "fsaa %d\n", fsaa
);
92 fprintf(f
, "vsync %d\n", vsync
);
93 extern int useshaders
, shaderprecision
;
94 fprintf(f
, "shaders %d\n", useshaders
);
95 fprintf(f
, "shaderprecision %d\n", shaderprecision
);
96 extern int soundchans
, soundfreq
, soundbufferlen
;
97 fprintf(f
, "soundchans %d\n", soundchans
);
98 fprintf(f
, "soundfreq %d\n", soundfreq
);
99 fprintf(f
, "soundbufferlen %d\n", soundbufferlen
);
103 void screenshot(char *filename
)
105 SDL_Surface
*image
= SDL_CreateRGBSurface(SDL_SWSURFACE
, screen
->w
, screen
->h
, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0);
107 uchar
*tmp
= new uchar
[screen
->w
*screen
->h
*3];
108 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
109 glReadPixels(0, 0, screen
->w
, screen
->h
, GL_RGB
, GL_UNSIGNED_BYTE
, tmp
);
110 uchar
*dst
= (uchar
*)image
->pixels
;
113 memcpy(dst
, &tmp
[3*screen
->w
*(screen
->h
-i
-1)], 3*screen
->w
);
114 endianswap(dst
, 3, screen
->w
);
121 s_sprintf(buf
)("screenshot_%d.bmp", lastmillis
);
125 SDL_SaveBMP(image
, findfile(filename
, "wb"));
126 SDL_FreeSurface(image
);
129 COMMAND(screenshot
, "s");
132 void computescreen(const char *text
, Texture
*t
)
134 int w
= screen
->w
, h
= screen
->h
;
136 glMatrixMode(GL_MODELVIEW
);
139 glEnable(GL_TEXTURE_2D
);
140 glDisable(GL_DEPTH_TEST
);
141 glDisable(GL_CULL_FACE
);
142 glClearColor(0.15f
, 0.15f
, 0.15f
, 1);
144 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
145 glMatrixMode(GL_PROJECTION
);
149 glOrtho(0, w
*3, h
*3, 0, -1, 1);
150 glClear(GL_COLOR_BUFFER_BIT
);
151 draw_text(text
, 70, 2*FONTH
+ FONTH
/2);
153 glOrtho(0, w
, h
, 0, -1, 1);
157 glBindTexture(GL_TEXTURE_2D
, t
->gl
);
159 int x
= (w
-640)/2, y
= (h
-320)/2;
160 glBegin(GL_TRIANGLE_FAN
);
161 glTexCoord2f(0.5f
, 0.5f
); glVertex2f(x
+640/2.0f
, y
+320/2.0f
);
164 float c
= 0.5f
+0.5f
*cosf(2*M_PI
*j
/64.0f
), s
= 0.5f
+0.5f
*sinf(2*M_PI
*j
/64.0f
);
165 glTexCoord2f(c
, 320.0f
/640.0f
*(s
-0.5f
)+0.5f
);
166 glVertex2f(x
+640*c
, y
+320*s
);
169 int sz
= 256, x
= (w
-sz
)/2, y
= min(384, h
-256);
171 glTexCoord2f(0, 0); glVertex2i(x
, y
);
172 glTexCoord2f(1, 0); glVertex2i(x
+sz
, y
);
173 glTexCoord2f(1, 1); glVertex2i(x
+sz
, y
+sz
);
174 glTexCoord2f(0, 1); glVertex2i(x
, y
+sz
);
179 int x
= (w
-512)/2, y
= 128;
180 settexture("data/sauer_logo_512_256a.png");
182 glTexCoord2f(0, 0); glVertex2i(x
, y
);
183 glTexCoord2f(1, 0); glVertex2i(x
+512, y
);
184 glTexCoord2f(1, 1); glVertex2i(x
+512, y
+256);
185 glTexCoord2f(0, 1); glVertex2i(x
, y
+256);
187 SDL_GL_SwapBuffers();
189 glMatrixMode(GL_MODELVIEW
);
191 glDisable(GL_TEXTURE_2D
);
192 glEnable(GL_DEPTH_TEST
);
193 glEnable(GL_CULL_FACE
);
196 static void bar(float bar
, int w
, int o
, float r
, float g
, float b
)
199 float x1
= side
, x2
= bar
*(w
*3-2*side
)+side
;
202 glBegin(GL_TRIANGLE_STRIP
);
205 float c
= cosf(M_PI
/2 + k
/9.0f
*M_PI
), s
= 1 + sinf(M_PI
/2 + k
/9.0f
*M_PI
);
206 glVertex2f(x2
- c
*FONTH
, y1
+ s
*FONTH
);
207 glVertex2f(x1
+ c
*FONTH
, y1
+ s
*FONTH
);
212 glColor3f(0.3f
, 0.3f
, 0.3f
);
213 glBegin(GL_LINE_LOOP
);
216 float c
= cosf(M_PI
/2 + k
/9.0f
*M_PI
), s
= 1 + sinf(M_PI
/2 + k
/9.0f
*M_PI
);
217 glVertex2f(x1
+ c
*FONTH
, y1
+ s
*FONTH
);
221 float c
= cosf(M_PI
/2 + k
/9.0f
*M_PI
), s
= 1 - sinf(M_PI
/2 + k
/9.0f
*M_PI
);
222 glVertex2f(x2
- c
*FONTH
, y1
+ s
*FONTH
);
228 void show_out_of_renderloop_progress(float bar1
, const char *text1
, float bar2
, const char *text2
, GLuint tex
) // also used during loading
230 if(!inbetweenframes
) return;
232 clientkeepalive(); // make sure our connection doesn't time out while loading maps etc.
234 int w
= screen
->w
, h
= screen
->h
;
237 glDisable(GL_DEPTH_TEST
);
238 glMatrixMode(GL_MODELVIEW
);
241 glMatrixMode(GL_PROJECTION
);
244 glOrtho(0, w
*3, h
*3, 0, -1, 1);
245 notextureshader
->set();
251 bar(1, w
, 4, 0, 0, 0.8f
);
252 if(bar1
>0) bar(bar1
, w
, 4, 0, 0.5f
, 1);
257 bar(1, w
, 6, 0.5f
, 0, 0);
258 bar(bar2
, w
, 6, 0.75f
, 0, 0);
264 glEnable(GL_TEXTURE_2D
);
265 defaultshader
->set();
267 if(text1
) draw_text(text1
, 2*FONTH
, 4*FONTH
+ FONTH
/2);
268 if(bar2
>0) draw_text(text2
, 2*FONTH
, 6*FONTH
+ FONTH
/2);
274 glBindTexture(GL_TEXTURE_2D
, tex
);
275 int sz
= 256, x
= (w
-sz
)/2, y
= min(384, h
-256);
280 glTexCoord2f(0, 0); glVertex2i(x
, y
);
281 glTexCoord2f(1, 0); glVertex2i(x
+sz
, y
);
282 glTexCoord2f(1, 1); glVertex2i(x
+sz
, y
+sz
);
283 glTexCoord2f(0, 1); glVertex2i(x
, y
+sz
);
287 glDisable(GL_TEXTURE_2D
);
290 glMatrixMode(GL_MODELVIEW
);
292 glEnable(GL_DEPTH_TEST
);
293 SDL_GL_SwapBuffers();
296 void setfullscreen(bool enable
)
298 if(enable
== !(screen
->flags
&SDL_FULLSCREEN
))
300 #if defined(WIN32) || defined(__APPLE__)
301 conoutf("\"fullscreen\" variable not supported on this platform. Use the -t command-line option.");
302 extern int fullscreen
;
303 fullscreen
= !enable
;
305 SDL_WM_ToggleFullScreen(screen
);
306 SDL_WM_GrabInput((screen
->flags
&SDL_FULLSCREEN
) ? SDL_GRAB_ON
: SDL_GRAB_OFF
);
311 void screenres(int *w
, int *h
)
313 #if !defined(WIN32) && !defined(__APPLE__)
319 #if defined(WIN32) || defined(__APPLE__)
324 SDL_Surface
*surf
= SDL_SetVideoMode(*w
, *h
, 0, SDL_OPENGL
|SDL_RESIZABLE
|(screen
->flags
&SDL_FULLSCREEN
));
329 glViewport(0, 0, scr_w
, scr_h
);
333 VARF(fullscreen
, 0, 0, 1, setfullscreen(fullscreen
!=0));
335 COMMAND(screenres
, "ii");
337 VARFP(gamma
, 30, 100, 300,
339 float f
= gamma
/100.0f
;
340 if(SDL_SetGamma(f
,f
,f
)==-1)
342 conoutf("Could not set gamma (card/driver doesn't support it?)");
343 conoutf("sdl: %s", SDL_GetError());
347 void keyrepeat(bool on
)
349 SDL_EnableKeyRepeat(on
? SDL_DEFAULT_REPEAT_DELAY
: 0,
350 SDL_DEFAULT_REPEAT_INTERVAL
);
353 VARF(gamespeed
, 10, 100, 1000, if(multiplayer()) gamespeed
= 100);
355 VARF(paused
, 0, 0, 1, if(multiplayer()) paused
= 0);
357 VAR(maxfps
, 5, 200, 500);
359 void limitfps(int &millis
, int curmillis
)
361 static int fpserror
= 0;
362 int delay
= 1000/maxfps
- (millis
-curmillis
);
363 if(delay
< 0) fpserror
= 0;
366 fpserror
+= 1000%maxfps
;
367 if(fpserror
>= maxfps
)
380 #if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__)
381 void stackdumper(unsigned int type
, EXCEPTION_POINTERS
*ep
)
383 if(!ep
) fatal("unknown type");
384 EXCEPTION_RECORD
*er
= ep
->ExceptionRecord
;
385 CONTEXT
*context
= ep
->ContextRecord
;
387 s_sprintf(out
)("Sauerbraten Win32 Exception: 0x%x [0x%x]\n\n", er
->ExceptionCode
, er
->ExceptionCode
==EXCEPTION_ACCESS_VIOLATION
? er
->ExceptionInformation
[1] : -1);
388 STACKFRAME sf
= {{context
->Eip
, 0, AddrModeFlat
}, {}, {context
->Ebp
, 0, AddrModeFlat
}, {context
->Esp
, 0, AddrModeFlat
}, 0};
389 SymInitialize(GetCurrentProcess(), NULL
, TRUE
);
391 while(::StackWalk(IMAGE_FILE_MACHINE_I386
, GetCurrentProcess(), GetCurrentThread(), &sf
, context
, NULL
, ::SymFunctionTableAccess
, ::SymGetModuleBase
, NULL
))
393 struct { IMAGEHLP_SYMBOL sym
; string n
; } si
= { { sizeof( IMAGEHLP_SYMBOL
), 0, 0, 0, sizeof(string
) } };
394 IMAGEHLP_LINE li
= { sizeof( IMAGEHLP_LINE
) };
396 if(SymGetSymFromAddr(GetCurrentProcess(), (DWORD
)sf
.AddrPC
.Offset
, &off
, &si
.sym
) && SymGetLineFromAddr(GetCurrentProcess(), (DWORD
)sf
.AddrPC
.Offset
, &off
, &li
))
398 char *del
= strrchr(li
.FileName
, '\\');
399 s_sprintf(t
)("%s - %s [%d]\n", si
.sym
.Name
, del
? del
+ 1 : li
.FileName
, li
.LineNumber
);
407 #define MAXFPSHISTORY 60
409 int fpspos
= 0, fpshistory
[MAXFPSHISTORY
];
411 void resetfpshistory()
413 loopi(MAXFPSHISTORY
) fpshistory
[i
] = 1;
417 void updatefpshistory(int millis
)
419 fpshistory
[fpspos
++] = max(1, min(1000, millis
));
420 if(fpspos
>=MAXFPSHISTORY
) fpspos
= 0;
423 void getfps(int &fps
, int &bestdiff
, int &worstdiff
)
425 int total
= fpshistory
[MAXFPSHISTORY
-1], best
= total
, worst
= total
;
426 loopi(MAXFPSHISTORY
-1)
428 int millis
= fpshistory
[i
];
430 if(millis
< best
) best
= millis
;
431 if(millis
> worst
) worst
= millis
;
434 fps
= (1000*MAXFPSHISTORY
)/total
;
435 bestdiff
= 1000/best
-fps
;
436 worstdiff
= fps
-1000/worst
;
439 bool inbetweenframes
= false;
441 static bool findarg(int argc
, char **argv
, const char *str
)
443 for(int i
= 1; i
<argc
; i
++) if(strstr(argv
[i
], str
)==argv
[i
]) return true;
447 static int clockrealbase
= 0, clockvirtbase
= 0;
448 static void clockreset() { clockrealbase
= SDL_GetTicks(); clockvirtbase
= totalmillis
; }
449 VARFP(clockerror
, 990000, 1000000, 1010000, clockreset());
450 VARFP(clockfix
, 0, 0, 1, clockreset());
452 int main(int argc
, char **argv
)
455 //atexit((void (__cdecl *)(void))_CrtDumpMemoryLeaks);
463 bool dedicated
= false;
464 int fs
= SDL_FULLSCREEN
, par
= 0;
465 char *load
= NULL
, *initscript
= NULL
;
467 #define log(s) puts("init: " s)
470 for(int i
= 1; i
<argc
; i
++)
472 if(argv
[i
][0]=='-') switch(argv
[i
][1])
474 case 'q': printf("Using home directory: %s\n", &argv
[i
][2]); sethomedir(&argv
[i
][2]); break;
475 case 'k': printf("Adding package directory: %s\n", &argv
[i
][2]); addpackagedir(&argv
[i
][2]); break;
476 case 'r': execfile(argv
[i
][2] ? &argv
[i
][2] : (char *)"init.cfg"); restoredinits
= true; break;
477 case 'd': dedicated
= true; break;
478 case 'w': scr_w
= atoi(&argv
[i
][2]); if(scr_w
<320) scr_w
= 320; if(!findarg(argc
, argv
, "-h")) scr_h
= (scr_w
*3)/4; break;
479 case 'h': scr_h
= atoi(&argv
[i
][2]); if(scr_h
<200) scr_h
= 200; if(!findarg(argc
, argv
, "-w")) scr_w
= (scr_h
*4)/3; break;
480 case 'z': depthbits
= atoi(&argv
[i
][2]); break;
481 case 'b': colorbits
= atoi(&argv
[i
][2]); break;
482 case 'a': fsaa
= atoi(&argv
[i
][2]); break;
483 case 'v': vsync
= atoi(&argv
[i
][2]); break;
484 case 't': fs
= 0; break;
485 case 's': stencilbits
= atoi(&argv
[i
][2]); break;
488 extern int useshaders
, shaderprecision
;
489 int n
= atoi(&argv
[i
][2]);
490 useshaders
= n
? 1 : 0;
491 shaderprecision
= min(max(n
- 1, 0), 3);
496 char pkgdir
[] = "packages/";
497 load
= strstr(path(&argv
[i
][2]), path(pkgdir
));
498 if(load
) load
+= sizeof(pkgdir
)-1;
499 else load
= &argv
[i
][2];
502 case 'x': initscript
= &argv
[i
][2]; break;
503 default: if(!serveroption(argv
[i
])) gameargs
.add(argv
[i
]); break;
505 else gameargs
.add(argv
[i
]);
512 par
= SDL_INIT_NOPARACHUTE
;
515 SetEnvironmentVariable("SDL_DEBUG", "1");
520 //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
523 if(SDL_Init(SDL_INIT_TIMER
|SDL_INIT_VIDEO
|SDL_INIT_AUDIO
|par
)<0) fatal("Unable to initialize SDL: %s", SDL_GetError());
526 if(enet_initialize()<0) fatal("Unable to initialise network module");
528 initserver(dedicated
); // never returns if dedicated
531 int resize
= SDL_RESIZABLE
;
532 #if defined(WIN32) || defined(__APPLE__)
535 SDL_Rect
**modes
= SDL_ListModes(NULL
, SDL_OPENGL
|resize
|fs
);
536 if(modes
&& modes
!=(SDL_Rect
**)-1)
538 bool hasmode
= false;
539 for(int i
= 0; modes
[i
]; i
++)
541 if(scr_w
<= modes
[i
]->w
&& scr_h
<= modes
[i
]->h
) { hasmode
= true; break; }
543 if(!hasmode
) { scr_w
= modes
[0]->w
; scr_h
= modes
[0]->h
; }
546 if(colorbits
&& modes
)
547 hasbpp
= SDL_VideoModeOK(modes
!=(SDL_Rect
**)-1 ? modes
[0]->w
: scr_w
, modes
!=(SDL_Rect
**)-1 ? modes
[0]->h
: scr_h
, colorbits
, SDL_OPENGL
|resize
|fs
)==colorbits
;
549 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER
, 1);
550 #if SDL_VERSION_ATLEAST(1, 2, 11)
551 if(vsync
>=0) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL
, vsync
);
553 static int configs
[] =
555 0x7, /* try everything */
556 0x6, 0x5, 0x3, /* try disabling one at a time */
557 0x4, 0x2, 0x1, /* try disabling two at a time */
558 0 /* try disabling everything */
561 loopi(sizeof(configs
)/sizeof(configs
[0]))
564 if(!depthbits
&& config
&1) continue;
565 if(!stencilbits
&& config
&2) continue;
566 if(!fsaa
&& config
&4) continue;
567 if(depthbits
) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE
, config
&1 ? depthbits
: 0);
570 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE
, config
&2 ? 1 : 0);
571 hasstencil
= (config
&2)!=0;
575 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS
, config
&4 ? 1 : 0);
576 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES
, config
&4 ? fsaa
: 0);
578 screen
= SDL_SetVideoMode(scr_w
, scr_h
, hasbpp
? colorbits
: 0, SDL_OPENGL
|resize
|fs
);
581 if(!screen
) fatal("Unable to create OpenGL screen: %s", SDL_GetError());
584 if(!hasbpp
) conoutf("%d bit color buffer not supported - disabling", colorbits
);
585 if(depthbits
&& (config
&1)==0) conoutf("%d bit z-buffer not supported - disabling", depthbits
);
586 if(stencilbits
&& (config
&2)==0) conoutf("Stencil buffer not supported - disabling");
587 if(fsaa
&& (config
&4)==0) conoutf("%dx anti-aliasing not supported - disabling", fsaa
);
596 SDL_WM_SetCaption("sauerbraten engine", NULL
);
600 SDL_WM_GrabInput(SDL_GRAB_ON
);
605 gl_init(scr_w
, scr_h
, hasbpp
? colorbits
: 0, config
&1 ? depthbits
: 0, config
&4 ? fsaa
: 0);
606 notexture
= textureload("data/notexture.png");
607 if(!notexture
) fatal("could not find core textures");
610 persistidents
= false;
611 if(!execfile("data/stdlib.cfg")) fatal("cannot find data files (you are running from the wrong folder, try .bat file in the main folder)"); // this is the first file we load.
612 if(!execfile("data/font.cfg")) fatal("cannot find font definitions");
613 if(!setfont("default")) fatal("no default font specified");
615 computescreen("initializing...");
616 inbetweenframes
= true;
623 camera1
= player
= cl
->iterdynents(0);
630 exec("data/keymap.cfg");
631 exec("data/stdedit.cfg");
632 exec("data/menus.cfg");
633 exec("data/sounds.cfg");
634 exec("data/brush.cfg");
635 execfile("mybrushes.cfg");
636 if(cl
->savedservers()) execfile(cl
->savedservers());
638 persistidents
= true;
640 if(!execfile(cl
->savedconfig())) exec(cl
->defaultconfig());
641 execfile(cl
->autoexec());
643 persistidents
= false;
646 s_strcpy(gamecfgname
, "data/game_");
647 s_strcat(gamecfgname
, cl
->gameident());
648 s_strcat(gamecfgname
, ".cfg");
651 persistidents
= true;
655 cc
->gameconnect(false);
656 cc
->changemap(load
? load
: cl
->defaultmap());
658 if(initscript
) execute(initscript
);
664 int ignore
= 5, grabmouse
= 0;
667 static int frames
= 0;
668 int millis
= SDL_GetTicks() - clockrealbase
;
669 if(clockfix
) millis
= int(millis
*(double(clockerror
)/1000000));
670 millis
+= clockvirtbase
;
671 if(millis
<totalmillis
) millis
= totalmillis
;
672 limitfps(millis
, totalmillis
);
673 int elapsed
= millis
-totalmillis
;
674 if(multiplayer(false)) curtime
= elapsed
;
677 static int timeerr
= 0;
678 int scaledtime
= elapsed
*gamespeed
+ timeerr
;
679 curtime
= scaledtime
/100;
680 timeerr
= scaledtime
%100;
681 if(curtime
>200) curtime
= 200;
682 if(paused
) curtime
= 0;
685 if(lastmillis
) cl
->updateworld(worldpos
, curtime
, lastmillis
);
689 lastmillis
+= curtime
;
690 totalmillis
= millis
;
692 checksleep(lastmillis
);
696 if(frames
) updatefpshistory(elapsed
);
699 // miscellaneous general game effects
705 inbetweenframes
= false;
706 SDL_GL_SwapBuffers();
707 if(frames
>2) gl_drawframe(screen
->w
, screen
->h
);
708 inbetweenframes
= true;
711 int lasttype
= 0, lastbut
= 0;
712 while(SDL_PollEvent(&event
))
720 #if !defined(WIN32) && !defined(__APPLE__)
721 case SDL_VIDEORESIZE
:
722 screenres(&event
.resize
.w
, &event
.resize
.h
);
728 keypress(event
.key
.keysym
.sym
, event
.key
.state
==SDL_PRESSED
, event
.key
.keysym
.unicode
);
731 case SDL_ACTIVEEVENT
:
732 if(event
.active
.state
& SDL_APPINPUTFOCUS
)
733 grabmouse
= event
.active
.gain
;
735 if(event
.active
.gain
)
739 case SDL_MOUSEMOTION
:
740 if(ignore
) { ignore
--; break; }
742 if(!(screen
->flags
&SDL_FULLSCREEN
) && grabmouse
)
745 if(event
.motion
.y
== 0) break; //let mac users drag windows via the title bar
747 if(event
.motion
.x
== screen
->w
/ 2 && event
.motion
.y
== screen
->h
/ 2) break;
748 SDL_WarpMouse(screen
->w
/ 2, screen
->h
/ 2);
750 if((screen
->flags
&SDL_FULLSCREEN
) || grabmouse
)
752 if(!g3d_movecursor(event
.motion
.xrel
, event
.motion
.yrel
))
753 mousemove(event
.motion
.xrel
, event
.motion
.yrel
);
756 case SDL_MOUSEBUTTONDOWN
:
757 case SDL_MOUSEBUTTONUP
:
758 if(lasttype
==event
.type
&& lastbut
==event
.button
.button
) break; // why?? get event twice without it
759 keypress(-event
.button
.button
, event
.button
.state
!=0, 0);
760 lasttype
= event
.type
;
761 lastbut
= event
.button
.button
;
770 #if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__)
771 } __except(stackdumper(0, GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH
) { return 0; }