1 // main.cpp: initialisation & main loop
11 extern void clear_command(); clear_command();
12 extern void clear_console(); clear_console();
13 extern void clear_mdls(); clear_mdls();
14 extern void clear_sound(); clear_sound();
18 void quit() // normal exit
20 extern void writeinitcfg();
30 void fatal(const char *s
, ...) // failure exit
32 static int errors
= 0;
35 if(errors
<= 2) // print up to one extra recursive error
37 s_sprintfdlv(msg
,s
,s
);
40 if(errors
<= 1) // avoid recursion
44 MessageBox(NULL
, msg
, "sauerbraten fatal error", MB_OK
|MB_SYSTEMMODAL
);
53 SDL_Surface
*screen
= NULL
;
56 int totalmillis
= 0, lastmillis
= 0;
58 dynent
*player
= NULL
;
60 static int initing
= NOT_INITING
;
61 static bool restoredinits
= false;
63 bool initwarning(const char *desc
, int level
, int type
)
67 addchange(desc
, type
);
73 VARF(scr_w
, 320, 1024, 10000, initwarning("screen resolution"));
74 VARF(scr_h
, 200, 768, 10000, initwarning("screen resolution"));
75 VARF(colorbits
, 0, 0, 32, initwarning("color depth"));
76 VARF(depthbits
, 0, 0, 32, initwarning("depth-buffer precision"));
77 VARF(stencilbits
, 0, 1, 32, initwarning("stencil-buffer precision"));
78 VARF(fsaa
, -1, -1, 16, initwarning("anti-aliasing"));
79 VARF(vsync
, -1, -1, 1, initwarning("vertical sync"));
83 if(!restoredinits
) return;
84 FILE *f
= openfile("init.cfg", "w");
86 fprintf(f
, "// automatically written on exit, DO NOT MODIFY\n// modify settings in game\n");
87 extern int fullscreen
;
88 fprintf(f
, "fullscreen %d\n", fullscreen
);
89 fprintf(f
, "scr_w %d\n", scr_w
);
90 fprintf(f
, "scr_h %d\n", scr_h
);
91 fprintf(f
, "colorbits %d\n", colorbits
);
92 fprintf(f
, "depthbits %d\n", depthbits
);
93 fprintf(f
, "stencilbits %d\n", stencilbits
);
94 fprintf(f
, "fsaa %d\n", fsaa
);
95 fprintf(f
, "vsync %d\n", vsync
);
96 extern int useshaders
, shaderprecision
;
97 fprintf(f
, "shaders %d\n", useshaders
);
98 fprintf(f
, "shaderprecision %d\n", shaderprecision
);
99 extern int soundchans
, soundfreq
, soundbufferlen
;
100 fprintf(f
, "soundchans %d\n", soundchans
);
101 fprintf(f
, "soundfreq %d\n", soundfreq
);
102 fprintf(f
, "soundbufferlen %d\n", soundbufferlen
);
106 void screenshot(char *filename
)
108 SDL_Surface
*image
= SDL_CreateRGBSurface(SDL_SWSURFACE
, screen
->w
, screen
->h
, 24, 0x0000FF, 0x00FF00, 0xFF0000, 0);
110 uchar
*tmp
= new uchar
[screen
->w
*screen
->h
*3];
111 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
112 glReadPixels(0, 0, screen
->w
, screen
->h
, GL_RGB
, GL_UNSIGNED_BYTE
, tmp
);
113 uchar
*dst
= (uchar
*)image
->pixels
;
116 memcpy(dst
, &tmp
[3*screen
->w
*(screen
->h
-i
-1)], 3*screen
->w
);
117 endianswap(dst
, 3, screen
->w
);
124 s_sprintf(buf
)("screenshot_%d.bmp", lastmillis
);
128 SDL_SaveBMP(image
, findfile(filename
, "wb"));
129 SDL_FreeSurface(image
);
132 COMMAND(screenshot
, "s");
135 static void getcomputescreenres(int &w
, int &h
)
137 float wk
= 1, hk
= 1;
138 if(w
< 1024) wk
= 1024.0f
/w
;
139 if(h
< 768) hk
= 768.0f
/h
;
140 wk
= hk
= max(wk
, hk
);
145 void computescreen(const char *text
, Texture
*t
, const char *overlaytext
)
147 int w
= screen
->w
, h
= screen
->h
;
148 getcomputescreenres(w
, h
);
151 glEnable(GL_TEXTURE_2D
);
152 glDisable(GL_DEPTH_TEST
);
153 glDisable(GL_CULL_FACE
);
154 glClearColor(0.15f
, 0.15f
, 0.15f
, 1);
156 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
157 glMatrixMode(GL_PROJECTION
);
159 glOrtho(0, w
, h
, 0, -1, 1);
160 glMatrixMode(GL_MODELVIEW
);
162 defaultshader
->set();
165 glClear(GL_COLOR_BUFFER_BIT
);
169 glScalef(1/3.0f
, 1/3.0f
, 1);
170 draw_text(text
, 70, 2*FONTH
+ FONTH
/2);
176 glBindTexture(GL_TEXTURE_2D
, t
->id
);
178 int x
= (w
-640)/2, y
= (h
-320)/2;
179 glBegin(GL_TRIANGLE_FAN
);
180 glTexCoord2f(0.5f
, 0.5f
); glVertex2f(x
+640/2.0f
, y
+320/2.0f
);
183 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
);
184 glTexCoord2f(c
, 320.0f
/640.0f
*(s
-0.5f
)+0.5f
);
185 glVertex2f(x
+640*c
, y
+320*s
);
188 int sz
= 256, x
= (w
-sz
)/2, y
= min(384, h
-256);
190 glTexCoord2f(0, 0); glVertex2f(x
, y
);
191 glTexCoord2f(1, 0); glVertex2f(x
+sz
, y
);
192 glTexCoord2f(1, 1); glVertex2f(x
+sz
, y
+sz
);
193 glTexCoord2f(0, 1); glVertex2f(x
, y
+sz
);
200 int sz
= 256, x
= (w
-sz
)/2, y
= min(384, h
-256), tw
= text_width(overlaytext
);
201 int tx
= t
&& tw
< sz
*2 - FONTH
/3 ?
202 2*(x
+ sz
) - tw
- FONTH
/3 :
205 2*(y
+ sz
) - FONTH
*4/3 :
206 2*(y
+ sz
/2) - FONTH
/2;
208 glScalef(1/2.0f
, 1/2.0f
, 1);
209 draw_text(overlaytext
, tx
, ty
);
212 int x
= (w
-512)/2, y
= 128;
213 settexture("data/sauer_logo_512_256a.png");
215 glTexCoord2f(0, 0); glVertex2f(x
, y
);
216 glTexCoord2f(1, 0); glVertex2f(x
+512, y
);
217 glTexCoord2f(1, 1); glVertex2f(x
+512, y
+256);
218 glTexCoord2f(0, 1); glVertex2f(x
, y
+256);
220 SDL_GL_SwapBuffers();
223 glDisable(GL_TEXTURE_2D
);
224 glEnable(GL_DEPTH_TEST
);
225 glEnable(GL_CULL_FACE
);
228 static void bar(float bar
, int w
, int o
, float r
, float g
, float b
)
231 float x1
= side
, x2
= min(bar
, 1.0f
)*(w
*3-2*side
)+side
;
234 glBegin(GL_TRIANGLE_STRIP
);
237 float c
= cosf(M_PI
/2 + k
/9.0f
*M_PI
), s
= 1 + sinf(M_PI
/2 + k
/9.0f
*M_PI
);
238 glVertex2f(x2
- c
*FONTH
, y1
+ s
*FONTH
);
239 glVertex2f(x1
+ c
*FONTH
, y1
+ s
*FONTH
);
244 glColor3f(0.3f
, 0.3f
, 0.3f
);
245 glBegin(GL_LINE_LOOP
);
248 float c
= cosf(M_PI
/2 + k
/9.0f
*M_PI
), s
= 1 + sinf(M_PI
/2 + k
/9.0f
*M_PI
);
249 glVertex2f(x1
+ c
*FONTH
, y1
+ s
*FONTH
);
253 float c
= cosf(M_PI
/2 + k
/9.0f
*M_PI
), s
= 1 - sinf(M_PI
/2 + k
/9.0f
*M_PI
);
254 glVertex2f(x2
- c
*FONTH
, y1
+ s
*FONTH
);
260 void show_out_of_renderloop_progress(float bar1
, const char *text1
, float bar2
, const char *text2
, GLuint tex
) // also used during loading
262 if(!inbetweenframes
) return;
264 clientkeepalive(); // make sure our connection doesn't time out while loading maps etc.
267 interceptkey(SDLK_UNKNOWN
); // keep the event queue awake to avoid 'beachball' cursor
270 int w
= screen
->w
, h
= screen
->h
;
271 getcomputescreenres(w
, h
);
274 glDisable(GL_DEPTH_TEST
);
275 glMatrixMode(GL_MODELVIEW
);
278 glMatrixMode(GL_PROJECTION
);
281 glOrtho(0, w
*3, h
*3, 0, -1, 1);
282 notextureshader
->set();
288 bar(1, w
, 4, 0, 0, 0.8f
);
289 if(bar1
>0) bar(bar1
, w
, 4, 0, 0.5f
, 1);
294 bar(1, w
, 6, 0.5f
, 0, 0);
295 bar(bar2
, w
, 6, 0.75f
, 0, 0);
301 glEnable(GL_TEXTURE_2D
);
302 defaultshader
->set();
304 if(text1
) draw_text(text1
, 2*FONTH
, 4*FONTH
+ FONTH
/2);
305 if(bar2
>0) draw_text(text2
, 2*FONTH
, 6*FONTH
+ FONTH
/2);
311 glBindTexture(GL_TEXTURE_2D
, tex
);
312 int sz
= 256, x
= (w
-sz
)/2, y
= min(384, h
-256);
317 glTexCoord2f(0, 0); glVertex2f(x
, y
);
318 glTexCoord2f(1, 0); glVertex2f(x
+sz
, y
);
319 glTexCoord2f(1, 1); glVertex2f(x
+sz
, y
+sz
);
320 glTexCoord2f(0, 1); glVertex2f(x
, y
+sz
);
324 glDisable(GL_TEXTURE_2D
);
327 glMatrixMode(GL_MODELVIEW
);
329 glEnable(GL_DEPTH_TEST
);
330 SDL_GL_SwapBuffers();
333 void setfullscreen(bool enable
)
336 #if defined(WIN32) || defined(__APPLE__)
337 initwarning(enable
? "fullscreen" : "windowed");
339 if(enable
== !(screen
->flags
&SDL_FULLSCREEN
))
341 SDL_WM_ToggleFullScreen(screen
);
342 SDL_WM_GrabInput((screen
->flags
&SDL_FULLSCREEN
) ? SDL_GRAB_ON
: SDL_GRAB_OFF
);
348 VARF(fullscreen
, 0, 0, 1, setfullscreen(fullscreen
!=0));
350 VARF(fullscreen
, 0, 1, 1, setfullscreen(fullscreen
!=0));
353 void screenres(int *w
, int *h
)
355 #if !defined(WIN32) && !defined(__APPLE__)
356 if(initing
>= INIT_RESET
)
361 #if defined(WIN32) || defined(__APPLE__)
362 initwarning("screen resolution");
366 SDL_Surface
*surf
= SDL_SetVideoMode(*w
, *h
, 0, SDL_OPENGL
|SDL_RESIZABLE
|(screen
->flags
&SDL_FULLSCREEN
));
371 glViewport(0, 0, scr_w
, scr_h
);
375 COMMAND(screenres
, "ii");
377 VARFP(gamma
, 30, 100, 300,
379 float f
= gamma
/100.0f
;
380 if(SDL_SetGamma(f
,f
,f
)==-1)
382 conoutf(CON_ERROR
, "Could not set gamma (card/driver doesn't support it?)");
383 conoutf(CON_ERROR
, "sdl: %s", SDL_GetError());
389 float f
= gamma
/100.0f
;
391 SDL_SetGamma(1, 1, 1);
392 SDL_SetGamma(f
, f
, f
);
395 void setupscreen(int &usedcolorbits
, int &useddepthbits
, int &usedfsaa
)
397 int flags
= SDL_RESIZABLE
;
398 #if defined(WIN32) || defined(__APPLE__)
401 if(fullscreen
) flags
|= SDL_FULLSCREEN
;
402 SDL_Rect
**modes
= SDL_ListModes(NULL
, SDL_OPENGL
|flags
);
403 if(modes
&& modes
!=(SDL_Rect
**)-1)
405 bool hasmode
= false;
406 for(int i
= 0; modes
[i
]; i
++)
408 if(scr_w
<= modes
[i
]->w
&& scr_h
<= modes
[i
]->h
) { hasmode
= true; break; }
410 if(!hasmode
) { scr_w
= modes
[0]->w
; scr_h
= modes
[0]->h
; }
413 if(colorbits
&& modes
)
414 hasbpp
= SDL_VideoModeOK(modes
!=(SDL_Rect
**)-1 ? modes
[0]->w
: scr_w
, modes
!=(SDL_Rect
**)-1 ? modes
[0]->h
: scr_h
, colorbits
, SDL_OPENGL
|flags
)==colorbits
;
416 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER
, 1);
417 #if SDL_VERSION_ATLEAST(1, 2, 11)
418 if(vsync
>=0) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL
, vsync
);
420 static int configs
[] =
422 0x7, /* try everything */
423 0x6, 0x5, 0x3, /* try disabling one at a time */
424 0x4, 0x2, 0x1, /* try disabling two at a time */
425 0 /* try disabling everything */
428 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE
, 0);
429 if(!depthbits
) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE
, 16);
432 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS
, 0);
433 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES
, 0);
435 loopi(sizeof(configs
)/sizeof(configs
[0]))
438 if(!depthbits
&& config
&1) continue;
439 if(!stencilbits
&& config
&2) continue;
440 if(fsaa
<=0 && config
&4) continue;
441 if(depthbits
) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE
, config
&1 ? depthbits
: 16);
444 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE
, config
&2 ? 1 : 0);
445 hasstencil
= (config
&2)!=0;
449 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS
, config
&4 ? 1 : 0);
450 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES
, config
&4 ? fsaa
: 0);
452 screen
= SDL_SetVideoMode(scr_w
, scr_h
, hasbpp
? colorbits
: 0, SDL_OPENGL
|flags
);
455 if(!screen
) fatal("Unable to create OpenGL screen: %s", SDL_GetError());
458 if(!hasbpp
) conoutf(CON_WARN
, "%d bit color buffer not supported - disabling", colorbits
);
459 if(depthbits
&& (config
&1)==0) conoutf(CON_WARN
, "%d bit z-buffer not supported - disabling", depthbits
);
460 if(stencilbits
&& (config
&2)==0) conoutf(CON_WARN
, "Stencil buffer not supported - disabling");
461 if(fsaa
>0 && (config
&4)==0) conoutf(CON_WARN
, "%dx anti-aliasing not supported - disabling", fsaa
);
468 SDL_WM_GrabInput(SDL_GRAB_ON
);
470 SDL_WM_GrabInput(fullscreen
? SDL_GRAB_ON
: SDL_GRAB_OFF
);
473 usedcolorbits
= hasbpp
? colorbits
: 0;
474 useddepthbits
= config
&1 ? depthbits
: 0;
475 usedfsaa
= config
&4 ? fsaa
: 0;
480 clearchanges(CHANGE_GFX
);
482 computescreen("resetting OpenGL");
484 extern void cleanupva();
485 extern void cleanupparticles();
486 extern void cleanupmodels();
487 extern void cleanuptextures();
488 extern void cleanuplightmaps();
489 extern void cleanshadowmap();
490 extern void cleanreflections();
491 extern void cleanupglare();
492 extern void cleanupdepthfx();
493 extern void cleanupshaders();
494 extern void cleanupgl();
507 SDL_SetVideoMode(0, 0, 0, 0);
509 int usedcolorbits
= 0, useddepthbits
= 0, usedfsaa
= 0;
510 setupscreen(usedcolorbits
, useddepthbits
, usedfsaa
);
511 gl_init(scr_w
, scr_h
, usedcolorbits
, useddepthbits
, usedfsaa
);
513 extern void reloadfonts();
514 extern void reloadtextures();
515 extern void reloadshaders();
516 inbetweenframes
= false;
517 if(!reloadtexture(*notexture
) ||
518 !reloadtexture("data/sauer_logo_512_256a.png"))
519 fatal("failed to reload core texture");
521 inbetweenframes
= true;
522 computescreen("initializing...");
530 COMMAND(resetgl
, "");
532 void keyrepeat(bool on
)
534 SDL_EnableKeyRepeat(on
? SDL_DEFAULT_REPEAT_DELAY
: 0,
535 SDL_DEFAULT_REPEAT_INTERVAL
);
538 static int ignoremouse
= 5, grabmouse
= 0;
540 vector
<SDL_Event
> events
;
542 void pushevent(const SDL_Event
&e
)
547 bool interceptkey(int sym
)
550 while(SDL_PollEvent(&event
))
555 if(event
.key
.keysym
.sym
== sym
)
569 int lasttype
= 0, lastbut
= 0;
570 while(events
.length() || SDL_PollEvent(&event
))
572 if(events
.length()) event
= events
.remove(0);
580 #if !defined(WIN32) && !defined(__APPLE__)
581 case SDL_VIDEORESIZE
:
582 screenres(&event
.resize
.w
, &event
.resize
.h
);
588 keypress(event
.key
.keysym
.sym
, event
.key
.state
==SDL_PRESSED
, event
.key
.keysym
.unicode
);
591 case SDL_ACTIVEEVENT
:
592 if(event
.active
.state
& SDL_APPINPUTFOCUS
)
593 grabmouse
= event
.active
.gain
;
595 if(event
.active
.gain
)
599 case SDL_MOUSEMOTION
:
600 if(ignoremouse
) { ignoremouse
--; break; }
602 if(!(screen
->flags
&SDL_FULLSCREEN
) && grabmouse
)
605 if(event
.motion
.y
== 0) break; //let mac users drag windows via the title bar
607 if(event
.motion
.x
== screen
->w
/ 2 && event
.motion
.y
== screen
->h
/ 2) break;
608 SDL_WarpMouse(screen
->w
/ 2, screen
->h
/ 2);
610 if((screen
->flags
&SDL_FULLSCREEN
) || grabmouse
)
612 if(!g3d_movecursor(event
.motion
.xrel
, event
.motion
.yrel
))
613 mousemove(event
.motion
.xrel
, event
.motion
.yrel
);
616 case SDL_MOUSEBUTTONDOWN
:
617 case SDL_MOUSEBUTTONUP
:
618 if(lasttype
==event
.type
&& lastbut
==event
.button
.button
) break; // why?? get event twice without it
619 keypress(-event
.button
.button
, event
.button
.state
!=0, 0);
620 lasttype
= event
.type
;
621 lastbut
= event
.button
.button
;
627 VARF(gamespeed
, 10, 100, 1000, if(multiplayer()) gamespeed
= 100);
629 VARF(paused
, 0, 0, 1, if(multiplayer()) paused
= 0);
631 VARP(maxfps
, 0, 200, 1000);
633 void limitfps(int &millis
, int curmillis
)
636 static int fpserror
= 0;
637 int delay
= 1000/maxfps
- (millis
-curmillis
);
638 if(delay
< 0) fpserror
= 0;
641 fpserror
+= 1000%maxfps
;
642 if(fpserror
>= maxfps
)
655 #if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__)
656 void stackdumper(unsigned int type
, EXCEPTION_POINTERS
*ep
)
658 if(!ep
) fatal("unknown type");
659 EXCEPTION_RECORD
*er
= ep
->ExceptionRecord
;
660 CONTEXT
*context
= ep
->ContextRecord
;
662 s_sprintf(out
)("Sauerbraten Win32 Exception: 0x%x [0x%x]\n\n", er
->ExceptionCode
, er
->ExceptionCode
==EXCEPTION_ACCESS_VIOLATION
? er
->ExceptionInformation
[1] : -1);
663 STACKFRAME sf
= {{context
->Eip
, 0, AddrModeFlat
}, {}, {context
->Ebp
, 0, AddrModeFlat
}, {context
->Esp
, 0, AddrModeFlat
}, 0};
664 SymInitialize(GetCurrentProcess(), NULL
, TRUE
);
666 while(::StackWalk(IMAGE_FILE_MACHINE_I386
, GetCurrentProcess(), GetCurrentThread(), &sf
, context
, NULL
, ::SymFunctionTableAccess
, ::SymGetModuleBase
, NULL
))
668 struct { IMAGEHLP_SYMBOL sym
; string n
; } si
= { { sizeof( IMAGEHLP_SYMBOL
), 0, 0, 0, sizeof(string
) } };
669 IMAGEHLP_LINE li
= { sizeof( IMAGEHLP_LINE
) };
671 if(SymGetSymFromAddr(GetCurrentProcess(), (DWORD
)sf
.AddrPC
.Offset
, &off
, &si
.sym
) && SymGetLineFromAddr(GetCurrentProcess(), (DWORD
)sf
.AddrPC
.Offset
, &off
, &li
))
673 char *del
= strrchr(li
.FileName
, '\\');
674 s_sprintf(t
)("%s - %s [%d]\n", si
.sym
.Name
, del
? del
+ 1 : li
.FileName
, li
.LineNumber
);
682 #define MAXFPSHISTORY 60
684 int fpspos
= 0, fpshistory
[MAXFPSHISTORY
];
686 void resetfpshistory()
688 loopi(MAXFPSHISTORY
) fpshistory
[i
] = 1;
692 void updatefpshistory(int millis
)
694 fpshistory
[fpspos
++] = max(1, min(1000, millis
));
695 if(fpspos
>=MAXFPSHISTORY
) fpspos
= 0;
698 void getfps(int &fps
, int &bestdiff
, int &worstdiff
)
700 int total
= fpshistory
[MAXFPSHISTORY
-1], best
= total
, worst
= total
;
701 loopi(MAXFPSHISTORY
-1)
703 int millis
= fpshistory
[i
];
705 if(millis
< best
) best
= millis
;
706 if(millis
> worst
) worst
= millis
;
709 fps
= (1000*MAXFPSHISTORY
)/total
;
710 bestdiff
= 1000/best
-fps
;
711 worstdiff
= fps
-1000/worst
;
714 void getfps_(int *raw
)
716 int fps
, bestdiff
, worstdiff
;
717 if(*raw
) fps
= 1000/fpshistory
[(fpspos
+MAXFPSHISTORY
-1)%MAXFPSHISTORY
];
718 else getfps(fps
, bestdiff
, worstdiff
);
722 COMMANDN(getfps
, getfps_
, "i");
724 bool inbetweenframes
= false;
726 static bool findarg(int argc
, char **argv
, const char *str
)
728 for(int i
= 1; i
<argc
; i
++) if(strstr(argv
[i
], str
)==argv
[i
]) return true;
732 static int clockrealbase
= 0, clockvirtbase
= 0;
733 static void clockreset() { clockrealbase
= SDL_GetTicks(); clockvirtbase
= totalmillis
; }
734 VARFP(clockerror
, 990000, 1000000, 1010000, clockreset());
735 VARFP(clockfix
, 0, 0, 1, clockreset());
737 int main(int argc
, char **argv
)
740 //atexit((void (__cdecl *)(void))_CrtDumpMemoryLeaks);
748 bool dedicated
= false;
749 char *load
= NULL
, *initscript
= NULL
;
751 #define log(s) puts("init: " s)
753 initing
= INIT_RESET
;
754 for(int i
= 1; i
<argc
; i
++)
756 if(argv
[i
][0]=='-') switch(argv
[i
][1])
758 case 'q': printf("Using home directory: %s\n", &argv
[i
][2]); sethomedir(&argv
[i
][2]); break;
759 case 'k': printf("Adding package directory: %s\n", &argv
[i
][2]); addpackagedir(&argv
[i
][2]); break;
760 case 'r': execfile(argv
[i
][2] ? &argv
[i
][2] : "init.cfg"); restoredinits
= true; break;
761 case 'd': dedicated
= true; break;
762 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;
763 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;
764 case 'z': depthbits
= atoi(&argv
[i
][2]); break;
765 case 'b': colorbits
= atoi(&argv
[i
][2]); break;
766 case 'a': fsaa
= atoi(&argv
[i
][2]); break;
767 case 'v': vsync
= atoi(&argv
[i
][2]); break;
768 case 't': fullscreen
= atoi(&argv
[i
][2]); break;
769 case 's': stencilbits
= atoi(&argv
[i
][2]); break;
772 extern int useshaders
, shaderprecision
;
773 int n
= atoi(&argv
[i
][2]);
774 useshaders
= n
? 1 : 0;
775 shaderprecision
= min(max(n
- 1, 0), 3);
780 char pkgdir
[] = "packages/";
781 load
= strstr(path(&argv
[i
][2]), path(pkgdir
));
782 if(load
) load
+= sizeof(pkgdir
)-1;
783 else load
= &argv
[i
][2];
786 case 'x': initscript
= &argv
[i
][2]; break;
787 default: if(!serveroption(argv
[i
])) gameargs
.add(argv
[i
]); break;
789 else gameargs
.add(argv
[i
]);
791 initing
= NOT_INITING
;
797 par
= SDL_INIT_NOPARACHUTE
;
799 SetEnvironmentVariable("SDL_DEBUG", "1");
804 //SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
807 if(SDL_Init(SDL_INIT_TIMER
|SDL_INIT_VIDEO
|SDL_INIT_AUDIO
|par
)<0) fatal("Unable to initialize SDL: %s", SDL_GetError());
810 if(enet_initialize()<0) fatal("Unable to initialise network module");
812 initserver(dedicated
); // never returns if dedicated
815 int usedcolorbits
= 0, useddepthbits
= 0, usedfsaa
= 0;
816 setupscreen(usedcolorbits
, useddepthbits
, usedfsaa
);
819 SDL_WM_SetCaption("sauerbraten engine", NULL
);
824 gl_checkextensions();
825 gl_init(scr_w
, scr_h
, usedcolorbits
, useddepthbits
, usedfsaa
);
826 notexture
= textureload("data/notexture.png");
827 if(!notexture
) fatal("could not find core textures");
830 persistidents
= false;
831 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.
832 if(!execfile("data/font.cfg")) fatal("cannot find font definitions");
833 if(!setfont("default")) fatal("no default font specified");
835 computescreen("initializing...");
836 inbetweenframes
= true;
844 camera1
= player
= cl
->iterdynents(0);
851 exec("data/keymap.cfg");
852 exec("data/stdedit.cfg");
853 exec("data/menus.cfg");
854 exec("data/sounds.cfg");
855 exec("data/brush.cfg");
856 execfile("mybrushes.cfg");
857 if(cl
->savedservers()) execfile(cl
->savedservers());
859 persistidents
= true;
862 if(!execfile(cl
->savedconfig())) exec(cl
->defaultconfig());
863 execfile(cl
->autoexec());
864 initing
= NOT_INITING
;
866 persistidents
= false;
869 s_strcpy(gamecfgname
, "data/game_");
870 s_strcat(gamecfgname
, cl
->gameident());
871 s_strcat(gamecfgname
, ".cfg");
874 persistidents
= true;
878 cc
->gameconnect(false);
879 //cc->changemap(load ? load : cl->defaultmap());
881 if(initscript
) execute(initscript
);
890 static int frames
= 0;
891 int millis
= SDL_GetTicks() - clockrealbase
;
892 if(clockfix
) millis
= int(millis
*(double(clockerror
)/1000000));
893 millis
+= clockvirtbase
;
894 if(millis
<totalmillis
) millis
= totalmillis
;
895 limitfps(millis
, totalmillis
);
896 int elapsed
= millis
-totalmillis
;
897 if(multiplayer(false)) curtime
= elapsed
;
900 static int timeerr
= 0;
901 int scaledtime
= elapsed
*gamespeed
+ timeerr
;
902 curtime
= scaledtime
/100;
903 timeerr
= scaledtime
%100;
904 if(curtime
>200) curtime
= 200;
905 if(paused
) curtime
= 0;
910 if(lastmillis
) cl
->updateworld(worldpos
, curtime
, lastmillis
);
914 lastmillis
+= curtime
;
915 totalmillis
= millis
;
917 checksleep(lastmillis
);
921 if(frames
) updatefpshistory(elapsed
);
924 // miscellaneous general game effects
930 inbetweenframes
= false;
931 if(frames
>2) gl_drawframe(screen
->w
, screen
->h
);
932 SDL_GL_SwapBuffers();
933 inbetweenframes
= true;
939 #if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__)
940 } __except(stackdumper(0, GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH
) { return 0; }