diff options
Diffstat (limited to 'src/engine/main.cpp')
| -rw-r--r-- | src/engine/main.cpp | 2094 |
1 files changed, 1008 insertions, 1086 deletions
diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 499002f..fb32dfd 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -12,65 +12,59 @@ extern void cleargamma(); void cleanup() { - cleanupserver(); - SDL_ShowCursor(SDL_TRUE); - SDL_SetRelativeMouseMode(SDL_FALSE); - if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); - cleargamma(); - freeocta(worldroot); - extern void clear_command(); clear_command(); - extern void clear_console(); clear_console(); - extern void clear_mdls(); clear_mdls(); - extern void clear_sound(); clear_sound(); - closelogfile(); - #ifdef __APPLE__ - if(screen) SDL_SetWindowFullscreen(screen, 0); - #endif - SDL_Quit(); + cleanupserver(); + SDL_ShowCursor(SDL_TRUE); + SDL_SetRelativeMouseMode(SDL_FALSE); + if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); + cleargamma(); + freeocta(worldroot); + extern void clear_command(); clear_command(); + extern void clear_console(); clear_console(); + extern void clear_mdls(); clear_mdls(); + extern void clear_sound(); clear_sound(); + closelogfile(); + SDL_Quit(); } extern void writeinitcfg(); -void quit() // normal exit +void quit() // normal exit { - writeinitcfg(); - writeservercfg(); - abortconnect(); - disconnect(); - localdisconnect(); - writecfg(); - cleanup(); - exit(EXIT_SUCCESS); + writeinitcfg(); + writeservercfg(); + abortconnect(); + disconnect(); + localdisconnect(); + writecfg(); + cleanup(); + exit(EXIT_SUCCESS); } -void fatal(const char *s, ...) // failure exit +void fatal(const char *s, ...) // failure exit { - static int errors = 0; - errors++; - - if(errors <= 2) // print up to one extra recursive error - { - defvformatstring(msg,s,s); - logoutf("%s", msg); - - if(errors <= 1) // avoid recursion - { - if(SDL_WasInit(SDL_INIT_VIDEO)) - { - SDL_ShowCursor(SDL_TRUE); - SDL_SetRelativeMouseMode(SDL_FALSE); - if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); - cleargamma(); - #ifdef __APPLE__ - if(screen) SDL_SetWindowFullscreen(screen, 0); - #endif - } - SDL_Quit(); - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Cube 2: Sauerbraten fatal error", msg, NULL); - } - } - - exit(EXIT_FAILURE); + static int errors = 0; + errors++; + + if(errors <= 2) // print up to one extra recursive error + { + defvformatstring(msg,s,s); + logoutf("%s", msg); + + if(errors <= 1) // avoid recursion + { + if(SDL_WasInit(SDL_INIT_VIDEO)) + { + SDL_ShowCursor(SDL_TRUE); + SDL_SetRelativeMouseMode(SDL_FALSE); + if(screen) SDL_SetWindowGrab(screen, SDL_FALSE); + cleargamma(); + } + SDL_Quit(); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Cube 2: Sauerbraten fatal error", msg, NULL); + } + } + + exit(EXIT_FAILURE); } int curtime = 0, lastmillis = 1, elapsedtime = 0, totalmillis = 1; @@ -81,12 +75,12 @@ int initing = NOT_INITING; bool initwarning(const char *desc, int level, int type) { - if(initing < level) - { - addchange(desc, type); - return true; - } - return false; + if(initing < level) + { + addchange(desc, type); + return true; + } + return false; } VAR(desktopw, 1, 0, 0); @@ -108,36 +102,36 @@ VARF(fsaa, -1, -1, 16, initwarning("anti-aliasing")); void writeinitcfg() { - stream *f = openutf8file("init.cfg", "w"); - if(!f) return; - f->printf("// automatically written on exit, DO NOT MODIFY\n// modify settings in game\n"); - extern int fullscreen, fullscreendesktop; - f->printf("fullscreen %d\n", fullscreen); - f->printf("fullscreendesktop %d\n", fullscreendesktop); - f->printf("scr_w %d\n", scr_w); - f->printf("scr_h %d\n", scr_h); - f->printf("depthbits %d\n", depthbits); - f->printf("fsaa %d\n", fsaa); - extern int usesound, soundchans, soundfreq, soundbufferlen; - extern char *audiodriver; - f->printf("usesound %d\n", usesound); - f->printf("soundchans %d\n", soundchans); - f->printf("soundfreq %d\n", soundfreq); - f->printf("soundbufferlen %d\n", soundbufferlen); - if(audiodriver[0]) f->printf("audiodriver %s\n", escapestring(audiodriver)); - delete f; + stream *f = openutf8file("init.cfg", "w"); + if(!f) return; + f->printf("// automatically written on exit, DO NOT MODIFY\n// modify settings in game\n"); + extern int fullscreen, fullscreendesktop; + f->printf("fullscreen %d\n", fullscreen); + f->printf("fullscreendesktop %d\n", fullscreendesktop); + f->printf("scr_w %d\n", scr_w); + f->printf("scr_h %d\n", scr_h); + f->printf("depthbits %d\n", depthbits); + f->printf("fsaa %d\n", fsaa); + extern int usesound, soundchans, soundfreq, soundbufferlen; + extern char *audiodriver; + f->printf("usesound %d\n", usesound); + f->printf("soundchans %d\n", soundchans); + f->printf("soundfreq %d\n", soundfreq); + f->printf("soundbufferlen %d\n", soundbufferlen); + if(audiodriver[0]) f->printf("audiodriver %s\n", escapestring(audiodriver)); + delete f; } COMMAND(quit, ""); static void getbackgroundres(int &w, int &h) { - float wk = 1, hk = 1; - if(w < 1024) wk = 1024.0f/w; - if(h < 768) hk = 768.0f/h; - wk = hk = max(wk, hk); - w = int(ceil(w*wk)); - h = int(ceil(h*hk)); + float wk = 1, hk = 1; + if(w < 1024) wk = 1024.0f/w; + if(h < 768) hk = 768.0f/h; + wk = hk = max(wk, hk); + w = int(ceil(w*wk)); + h = int(ceil(h*hk)); } string backgroundcaption = ""; @@ -147,156 +141,156 @@ char *backgroundmapinfo = NULL; void setbackgroundinfo(const char *caption = NULL, Texture *mapshot = NULL, const char *mapname = NULL, const char *mapinfo = NULL) { - renderedframe = false; - copystring(backgroundcaption, caption ? caption : ""); - backgroundmapshot = mapshot; - copystring(backgroundmapname, mapname ? mapname : ""); - if(mapinfo != backgroundmapinfo) - { - DELETEA(backgroundmapinfo); - if(mapinfo) backgroundmapinfo = newstring(mapinfo); - } + renderedframe = false; + copystring(backgroundcaption, caption ? caption : ""); + backgroundmapshot = mapshot; + copystring(backgroundmapname, mapname ? mapname : ""); + if(mapinfo != backgroundmapinfo) + { + DELETEA(backgroundmapinfo); + if(mapinfo) backgroundmapinfo = newstring(mapinfo); + } } void restorebackground(bool force = false) { - if(renderedframe) - { - if(!force) return; - setbackgroundinfo(); - } - renderbackground(backgroundcaption[0] ? backgroundcaption : NULL, backgroundmapshot, backgroundmapname[0] ? backgroundmapname : NULL, backgroundmapinfo, true); + if(renderedframe) + { + if(!force) return; + setbackgroundinfo(); + } + renderbackground(backgroundcaption[0] ? backgroundcaption : NULL, backgroundmapshot, backgroundmapname[0] ? backgroundmapname : NULL, backgroundmapinfo, true); } void bgquad(float x, float y, float w, float h, float tx = 0, float ty = 0, float tw = 1, float th = 1) { - gle::begin(GL_TRIANGLE_STRIP); - gle::attribf(x, y); gle::attribf(tx, ty); - gle::attribf(x+w, y); gle::attribf(tx + tw, ty); - gle::attribf(x, y+h); gle::attribf(tx, ty + th); - gle::attribf(x+w, y+h); gle::attribf(tx + tw, ty + th); - gle::end(); + gle::begin(GL_TRIANGLE_STRIP); + gle::attribf(x, y); gle::attribf(tx, ty); + gle::attribf(x+w, y); gle::attribf(tx + tw, ty); + gle::attribf(x, y+h); gle::attribf(tx, ty + th); + gle::attribf(x+w, y+h); gle::attribf(tx + tw, ty + th); + gle::end(); } void renderbackground(const char *caption, Texture *mapshot, const char *mapname, const char *mapinfo, bool restore, bool force) { - if(!inbetweenframes && !force) return; - - if(!restore || force) stopsounds(); // stop sounds while loading - - int w = screenw, h = screenh; - if(forceaspect) w = int(ceil(h*forceaspect)); - getbackgroundres(w, h); - gettextres(w, h); - - static int lastupdate = -1, lastw = -1, lasth = -1; - static int numdecals = 0; - static struct decal { float x, y, size; int side; } decals[12]; - if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h) - { - lastupdate = lastmillis; - lastw = w; - lasth = h; - - numdecals = sizeof(decals)/sizeof(decals[0]); - numdecals = numdecals/3 + rnd((numdecals*2)/3 + 1); - float maxsize = min(w, h)/16.0f; - loopi(numdecals) - { - decal d = { rndscale(w), rndscale(h), maxsize/2 + rndscale(maxsize/2), rnd(2) }; - decals[i] = d; - } - } - else if(lastupdate != lastmillis) lastupdate = lastmillis; - - loopi(restore ? 1 : 3) - { - hudmatrix.ortho(0, w, h, 0, -1, 1); - resethudmatrix(); - - hudshader->set(); - gle::colorf(1, 1, 1); - - gle::defvertex(2); - gle::deftexcoord0(); - - settexture("background/daemex.png", 0); - bgquad(0, 0, screenw, screenh, 0, 0, 1, 1); - glEnable(GL_BLEND); - float lh = 0.5f*min(w, h), lw = lh*2, - lx = 0.5f*(w - lw), ly = 0.5f*(h*0.5f - lh); - settexture((maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize) >= 1024 && (screenw > 1280 || screenh > 800) ? "data/logo_1024.png" : "data/logo.png", 3); - bgquad(lx, ly, lw, lh); - if(caption) - { - int tw = text_width(caption); - float tsz = 0.04f*min(w, h)/FONTH, - tx = 0.5f*(w - tw*tsz), ty = h - 0.075f*1.5f*min(w, h) - 1.25f*FONTH*tsz; - pushhudmatrix(); - hudmatrix.translate(tx, ty, 0); - hudmatrix.scale(tsz, tsz, 1); - flushhudmatrix(); - draw_text(caption, 0, 0); - pophudmatrix(); - } - if(mapshot || mapname) - { - int infowidth = 12*FONTH; - float sz = 0.35f*min(w, h), msz = (0.75f*min(w, h) - sz)/(infowidth + FONTH), x = 0.5f*(w-sz), y = ly+lh - sz/15; - if(mapinfo) - { - int mw, mh; - text_bounds(mapinfo, mw, mh, infowidth); - x -= 0.5f*(mw*msz + FONTH*msz); - } - if(mapshot && mapshot!=notexture) - { - glBindTexture(GL_TEXTURE_2D, mapshot->id); - bgquad(x, y, sz, sz); - } - else - { - int qw, qh; - text_bounds("?", qw, qh); - float qsz = sz*0.5f/max(qw, qh); - pushhudmatrix(); - hudmatrix.translate(x + 0.5f*(sz - qw*qsz), y + 0.5f*(sz - qh*qsz), 0); - hudmatrix.scale(qsz, qsz, 1); - flushhudmatrix(); - draw_text("?", 0, 0); - pophudmatrix(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - settexture("data/mapshot_frame.png", 3); - bgquad(x, y, sz, sz); - if(mapname) - { - int tw = text_width(mapname); - float tsz = sz/(8*FONTH), - tx = 0.9f*sz - tw*tsz, ty = 0.9f*sz - FONTH*tsz; - if(tx < 0.1f*sz) { tsz = 0.1f*sz/tw; tx = 0.1f; } - pushhudmatrix(); - hudmatrix.translate(x+tx, y+ty, 0); - hudmatrix.scale(tsz, tsz, 1); - flushhudmatrix(); - draw_text(mapname, 0, 0); - pophudmatrix(); - } - if(mapinfo) - { - pushhudmatrix(); - hudmatrix.translate(x+sz+FONTH*msz, y, 0); - hudmatrix.scale(msz, msz, 1); - flushhudmatrix(); - draw_text(mapinfo, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, -1, infowidth); - pophudmatrix(); - } - } - glDisable(GL_BLEND); - if(!restore) swapbuffers(false); - } - - if(!restore) setbackgroundinfo(caption, mapshot, mapname, mapinfo); + if(!inbetweenframes && !force) return; + + if(!restore || force) stopsounds(); // stop sounds while loading + + int w = screenw, h = screenh; + if(forceaspect) w = int(ceil(h*forceaspect)); + getbackgroundres(w, h); + gettextres(w, h); + + static int lastupdate = -1, lastw = -1, lasth = -1; + static int numdecals = 0; + static struct decal { float x, y, size; int side; } decals[12]; + if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h) + { + lastupdate = lastmillis; + lastw = w; + lasth = h; + + numdecals = sizeof(decals)/sizeof(decals[0]); + numdecals = numdecals/3 + rnd((numdecals*2)/3 + 1); + float maxsize = min(w, h)/16.0f; + loopi(numdecals) + { + decal d = { rndscale(w), rndscale(h), maxsize/2 + rndscale(maxsize/2), rnd(2) }; + decals[i] = d; + } + } + else if(lastupdate != lastmillis) lastupdate = lastmillis; + + loopi(restore ? 1 : 3) + { + hudmatrix.ortho(0, w, h, 0, -1, 1); + resethudmatrix(); + + hudshader->set(); + gle::colorf(1, 1, 1); + + gle::defvertex(2); + gle::deftexcoord0(); + + settexture("background/daemex.png", 0); + bgquad(0, 0, screenw, screenh, 0, 0, 1, 1); + glEnable(GL_BLEND); + float lh = 0.5f*min(w, h), lw = lh*2, + lx = 0.5f*(w - lw), ly = 0.5f*(h*0.5f - lh); + settexture((maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize) >= 1024 && (screenw > 1280 || screenh > 800) ? "data/logo_1024.png" : "data/logo.png", 3); + bgquad(lx, ly, lw, lh); + if(caption) + { + int tw = text_width(caption); + float tsz = 0.04f*min(w, h)/FONTH, + tx = 0.5f*(w - tw*tsz), ty = h - 0.075f*1.5f*min(w, h) - 1.25f*FONTH*tsz; + pushhudmatrix(); + hudmatrix.translate(tx, ty, 0); + hudmatrix.scale(tsz, tsz, 1); + flushhudmatrix(); + draw_text(caption, 0, 0); + pophudmatrix(); + } + if(mapshot || mapname) + { + int infowidth = 12*FONTH; + float sz = 0.35f*min(w, h), msz = (0.75f*min(w, h) - sz)/(infowidth + FONTH), x = 0.5f*(w-sz), y = ly+lh - sz/15; + if(mapinfo) + { + int mw, mh; + text_bounds(mapinfo, mw, mh, infowidth); + x -= 0.5f*(mw*msz + FONTH*msz); + } + if(mapshot && mapshot!=notexture) + { + glBindTexture(GL_TEXTURE_2D, mapshot->id); + bgquad(x, y, sz, sz); + } + else + { + int qw, qh; + text_bounds("?", qw, qh); + float qsz = sz*0.5f/max(qw, qh); + pushhudmatrix(); + hudmatrix.translate(x + 0.5f*(sz - qw*qsz), y + 0.5f*(sz - qh*qsz), 0); + hudmatrix.scale(qsz, qsz, 1); + flushhudmatrix(); + draw_text("?", 0, 0); + pophudmatrix(); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + settexture("data/mapshot_frame.png", 3); + bgquad(x, y, sz, sz); + if(mapname) + { + int tw = text_width(mapname); + float tsz = sz/(8*FONTH), + tx = 0.9f*sz - tw*tsz, ty = 0.9f*sz - FONTH*tsz; + if(tx < 0.1f*sz) { tsz = 0.1f*sz/tw; tx = 0.1f; } + pushhudmatrix(); + hudmatrix.translate(x+tx, y+ty, 0); + hudmatrix.scale(tsz, tsz, 1); + flushhudmatrix(); + draw_text(mapname, 0, 0); + pophudmatrix(); + } + if(mapinfo) + { + pushhudmatrix(); + hudmatrix.translate(x+sz+FONTH*msz, y, 0); + hudmatrix.scale(msz, msz, 1); + flushhudmatrix(); + draw_text(mapinfo, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, -1, infowidth); + pophudmatrix(); + } + } + glDisable(GL_BLEND); + if(!restore) swapbuffers(false); + } + + if(!restore) setbackgroundinfo(caption, mapshot, mapname, mapinfo); } VAR(progressbackground, 0, 0, 1); @@ -305,108 +299,108 @@ float loadprogress = 0; void renderprogress(float bar, const char *text, GLuint tex, bool background) // also used during loading { - if(!inbetweenframes || drawtex) return; - - extern int menufps, maxfps; - int fps = menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; - if(fps) - { - static int lastprogress = 0; - int ticks = SDL_GetTicks(), diff = ticks - lastprogress; - if(bar > 0 && diff >= 0 && diff < (1000 + fps-1)/fps) return; - lastprogress = ticks; - } - - clientkeepalive(); // make sure our connection doesn't time out while loading maps etc. - - SDL_PumpEvents(); // keep the event queue awake to avoid 'beachball' cursor - - extern int mesa_swap_bug, curvsync; - bool forcebackground = progressbackground || (mesa_swap_bug && (curvsync || totalmillis==1)); - if(background || forcebackground) restorebackground(forcebackground); - - int w = screenw, h = screenh; - if(forceaspect) w = int(ceil(h*forceaspect)); - getbackgroundres(w, h); - gettextres(w, h); - - hudmatrix.ortho(0, w, h, 0, -1, 1); - resethudmatrix(); - - hudshader->set(); - gle::colorf(1, 1, 1); - - gle::defvertex(2); - gle::deftexcoord0(); - - float fh = 0.075f*min(w, h), fw = fh*10, - fx = renderedframe ? w - fw - fh/4 : 0.5f*(w - fw), - fy = renderedframe ? fh/4 : h - fh*1.5f, - fu1 = 0/512.0f, fu2 = 511/512.0f, - fv1 = 0/64.0f, fv2 = 52/64.0f; - settexture("data/loading_frame.png", 3); - bgquad(fx, fy, fw, fh, fu1, fv1, fu2-fu1, fv2-fv1); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - float bw = fw*(511 - 2*17)/511.0f, bh = fh*20/52.0f, - bx = fx + fw*17/511.0f, by = fy + fh*16/52.0f, - bv1 = 0/32.0f, bv2 = 20/32.0f, - su1 = 0/32.0f, su2 = 7/32.0f, sw = fw*7/511.0f, - eu1 = 23/32.0f, eu2 = 30/32.0f, ew = fw*7/511.0f, - mw = bw - sw - ew, - ex = bx+sw + max(mw*bar, fw*7/511.0f); - if(bar > 0) - { - settexture("data/loading_bar.png", 3); - gle::begin(GL_QUADS); - gle::attribf(bx, by); gle::attribf(su1, bv1); - gle::attribf(bx+sw, by); gle::attribf(su2, bv1); - gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); - gle::attribf(bx, by+bh); gle::attribf(su1, bv2); - - gle::attribf(bx+sw, by); gle::attribf(su2, bv1); - gle::attribf(ex, by); gle::attribf(eu1, bv1); - gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); - gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); - - gle::attribf(ex, by); gle::attribf(eu1, bv1); - gle::attribf(ex+ew, by); gle::attribf(eu2, bv1); - gle::attribf(ex+ew, by+bh); gle::attribf(eu2, bv2); - gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); - gle::end(); - } - - if(text) - { - int tw = text_width(text); - float tsz = bh*0.8f/FONTH; - if(tw*tsz > mw) tsz = mw/tw; - pushhudmatrix(); - hudmatrix.translate(bx+sw, by + (bh - FONTH*tsz)/2, 0); - hudmatrix.scale(tsz, tsz, 1); - flushhudmatrix(); - draw_text(text, 0, 0); - pophudmatrix(); - } - - glDisable(GL_BLEND); - - if(tex) - { - glBindTexture(GL_TEXTURE_2D, tex); - float sz = 0.35f*min(w, h), x = 0.5f*(w-sz), y = 0.5f*min(w, h) - sz/15; - bgquad(x, y, sz, sz); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - settexture("data/mapshot_frame.png", 3); - bgquad(x, y, sz, sz); - glDisable(GL_BLEND); - } - - swapbuffers(false); + if(!inbetweenframes || drawtex) return; + + extern int menufps, maxfps; + int fps = menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; + if(fps) + { + static int lastprogress = 0; + int ticks = SDL_GetTicks(), diff = ticks - lastprogress; + if(bar > 0 && diff >= 0 && diff < (1000 + fps-1)/fps) return; + lastprogress = ticks; + } + + clientkeepalive(); // make sure our connection doesn't time out while loading maps etc. + + SDL_PumpEvents(); // keep the event queue awake to avoid 'beachball' cursor + + extern int mesa_swap_bug, curvsync; + bool forcebackground = progressbackground || (mesa_swap_bug && (curvsync || totalmillis==1)); + if(background || forcebackground) restorebackground(forcebackground); + + int w = screenw, h = screenh; + if(forceaspect) w = int(ceil(h*forceaspect)); + getbackgroundres(w, h); + gettextres(w, h); + + hudmatrix.ortho(0, w, h, 0, -1, 1); + resethudmatrix(); + + hudshader->set(); + gle::colorf(1, 1, 1); + + gle::defvertex(2); + gle::deftexcoord0(); + + float fh = 0.075f*min(w, h), fw = fh*10, + fx = renderedframe ? w - fw - fh/4 : 0.5f*(w - fw), + fy = renderedframe ? fh/4 : h - fh*1.5f, + fu1 = 0/512.0f, fu2 = 511/512.0f, + fv1 = 0/64.0f, fv2 = 52/64.0f; + settexture("data/loading_frame.png", 3); + bgquad(fx, fy, fw, fh, fu1, fv1, fu2-fu1, fv2-fv1); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + float bw = fw*(511 - 2*17)/511.0f, bh = fh*20/52.0f, + bx = fx + fw*17/511.0f, by = fy + fh*16/52.0f, + bv1 = 0/32.0f, bv2 = 20/32.0f, + su1 = 0/32.0f, su2 = 7/32.0f, sw = fw*7/511.0f, + eu1 = 23/32.0f, eu2 = 30/32.0f, ew = fw*7/511.0f, + mw = bw - sw - ew, + ex = bx+sw + max(mw*bar, fw*7/511.0f); + if(bar > 0) + { + settexture("data/loading_bar.png", 3); + gle::begin(GL_QUADS); + gle::attribf(bx, by); gle::attribf(su1, bv1); + gle::attribf(bx+sw, by); gle::attribf(su2, bv1); + gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); + gle::attribf(bx, by+bh); gle::attribf(su1, bv2); + + gle::attribf(bx+sw, by); gle::attribf(su2, bv1); + gle::attribf(ex, by); gle::attribf(eu1, bv1); + gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); + gle::attribf(bx+sw, by+bh); gle::attribf(su2, bv2); + + gle::attribf(ex, by); gle::attribf(eu1, bv1); + gle::attribf(ex+ew, by); gle::attribf(eu2, bv1); + gle::attribf(ex+ew, by+bh); gle::attribf(eu2, bv2); + gle::attribf(ex, by+bh); gle::attribf(eu1, bv2); + gle::end(); + } + + if(text) + { + int tw = text_width(text); + float tsz = bh*0.8f/FONTH; + if(tw*tsz > mw) tsz = mw/tw; + pushhudmatrix(); + hudmatrix.translate(bx+sw, by + (bh - FONTH*tsz)/2, 0); + hudmatrix.scale(tsz, tsz, 1); + flushhudmatrix(); + draw_text(text, 0, 0); + pophudmatrix(); + } + + glDisable(GL_BLEND); + + if(tex) + { + glBindTexture(GL_TEXTURE_2D, tex); + float sz = 0.35f*min(w, h), x = 0.5f*(w-sz), y = 0.5f*min(w, h) - sz/15; + bgquad(x, y, sz, sz); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + settexture("data/mapshot_frame.png", 3); + bgquad(x, y, sz, sz); + glDisable(GL_BLEND); + } + + swapbuffers(false); } int keyrepeatmask = 0, textinputmask = 0; @@ -415,34 +409,29 @@ VAR(textinputfilter, 0, 5, 1000); void keyrepeat(bool on, int mask) { - if(on) keyrepeatmask |= mask; - else keyrepeatmask &= ~mask; + if(on) keyrepeatmask |= mask; + else keyrepeatmask &= ~mask; } void textinput(bool on, int mask) { - if(on) - { - if(!textinputmask) - { - SDL_StartTextInput(); - textinputtime = SDL_GetTicks(); - } - textinputmask |= mask; - } - else if(textinputmask) - { - textinputmask &= ~mask; - if(!textinputmask) SDL_StopTextInput(); - } + if(on) + { + if(!textinputmask) + { + SDL_StartTextInput(); + textinputtime = SDL_GetTicks(); + } + textinputmask |= mask; + } + else if(textinputmask) + { + textinputmask &= ~mask; + if(!textinputmask) SDL_StopTextInput(); + } } -#ifdef WIN32 -// SDL_WarpMouseInWindow behaves erratically on Windows, so force relative mouse instead. -VARN(relativemouse, userelativemouse, 1, 1, 0); -#else VARNP(relativemouse, userelativemouse, 0, 1, 1); -#endif bool shouldgrab = false, grabinput = false, minimized = false, canrelativemouse = true, relativemouse = false; @@ -453,54 +442,54 @@ VAR(sdl_xgrab_bug, 0, 0, 1); void inputgrab(bool on, bool delay = false) { #ifdef SDL_VIDEO_DRIVER_X11 - bool wasrelativemouse = relativemouse; + bool wasrelativemouse = relativemouse; #endif - if(on) - { - SDL_ShowCursor(SDL_FALSE); - if(canrelativemouse && userelativemouse) - { - if(SDL_SetRelativeMouseMode(SDL_TRUE) >= 0) - { - SDL_SetWindowGrab(screen, SDL_TRUE); - relativemouse = true; - } - else - { - SDL_SetWindowGrab(screen, SDL_FALSE); - canrelativemouse = false; - relativemouse = false; - } - } - } - else - { - SDL_ShowCursor(SDL_TRUE); - if(relativemouse) - { - SDL_SetWindowGrab(screen, SDL_FALSE); - SDL_SetRelativeMouseMode(SDL_FALSE); - relativemouse = false; - } - } - shouldgrab = delay; + if(on) + { + SDL_ShowCursor(SDL_FALSE); + if(canrelativemouse && userelativemouse) + { + if(SDL_SetRelativeMouseMode(SDL_TRUE) >= 0) + { + SDL_SetWindowGrab(screen, SDL_TRUE); + relativemouse = true; + } + else + { + SDL_SetWindowGrab(screen, SDL_FALSE); + canrelativemouse = false; + relativemouse = false; + } + } + } + else + { + SDL_ShowCursor(SDL_TRUE); + if(relativemouse) + { + SDL_SetWindowGrab(screen, SDL_FALSE); + SDL_SetRelativeMouseMode(SDL_FALSE); + relativemouse = false; + } + } + shouldgrab = delay; #ifdef SDL_VIDEO_DRIVER_X11 - if((relativemouse || wasrelativemouse) && sdl_xgrab_bug) - { - // Workaround for buggy SDL X11 pointer grabbing - union { SDL_SysWMinfo info; uchar buf[sizeof(SDL_SysWMinfo) + 128]; }; - SDL_GetVersion(&info.version); - if(SDL_GetWindowWMInfo(screen, &info) && info.subsystem == SDL_SYSWM_X11) - { - if(relativemouse) - { - uint mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; - XGrabPointer(info.info.x11.display, info.info.x11.window, True, mask, GrabModeAsync, GrabModeAsync, info.info.x11.window, None, CurrentTime); - } - else XUngrabPointer(info.info.x11.display, CurrentTime); - } - } + if((relativemouse || wasrelativemouse) && sdl_xgrab_bug) + { + // Workaround for buggy SDL X11 pointer grabbing + union { SDL_SysWMinfo info; uchar buf[sizeof(SDL_SysWMinfo) + 128]; }; + SDL_GetVersion(&info.version); + if(SDL_GetWindowWMInfo(screen, &info) && info.subsystem == SDL_SYSWM_X11) + { + if(relativemouse) + { + uint mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; + XGrabPointer(info.info.x11.display, info.info.x11.window, True, mask, GrabModeAsync, GrabModeAsync, info.info.x11.window, None, CurrentTime); + } + else XUngrabPointer(info.info.x11.display, CurrentTime); + } + } #endif } @@ -508,20 +497,20 @@ bool initwindowpos = false; void setfullscreen(bool enable) { - if(!screen) return; - //initwarning(enable ? "fullscreen" : "windowed"); - extern int fullscreendesktop; - SDL_SetWindowFullscreen(screen, enable ? (fullscreendesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0); - if(!enable) - { - SDL_SetWindowSize(screen, scr_w, scr_h); - if(initwindowpos) - { - int winx = SDL_WINDOWPOS_CENTERED, winy = SDL_WINDOWPOS_CENTERED; - SDL_SetWindowPosition(screen, winx, winy); - initwindowpos = false; - } - } + if(!screen) return; + //initwarning(enable ? "fullscreen" : "windowed"); + extern int fullscreendesktop; + SDL_SetWindowFullscreen(screen, enable ? (fullscreendesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0); + if(!enable) + { + SDL_SetWindowSize(screen, scr_w, scr_h); + if(initwindowpos) + { + int winx = SDL_WINDOWPOS_CENTERED, winy = SDL_WINDOWPOS_CENTERED; + SDL_SetWindowPosition(screen, winx, winy); + initwindowpos = false; + } + } } #ifdef _DEBUG @@ -532,76 +521,76 @@ VARF(fullscreen, 0, 1, 1, setfullscreen(fullscreen!=0)); void resetfullscreen() { - setfullscreen(false); - setfullscreen(true); + setfullscreen(false); + setfullscreen(true); } VARF(fullscreendesktop, 0, 0, 1, if(fullscreen) resetfullscreen()); void screenres(int w, int h) { - scr_w = clamp(w, SCR_MINW, SCR_MAXW); - scr_h = clamp(h, SCR_MINH, SCR_MAXH); - if(screen) - { - if(fullscreendesktop) - { - scr_w = min(scr_w, desktopw); - scr_h = min(scr_h, desktoph); - } - if(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN) - { - if(fullscreendesktop) gl_resize(); - else resetfullscreen(); - initwindowpos = true; - } - else - { - SDL_SetWindowSize(screen, scr_w, scr_h); - SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); - initwindowpos = false; - } - } - else - { - initwarning("screen resolution"); - } + scr_w = clamp(w, SCR_MINW, SCR_MAXW); + scr_h = clamp(h, SCR_MINH, SCR_MAXH); + if(screen) + { + if(fullscreendesktop) + { + scr_w = min(scr_w, desktopw); + scr_h = min(scr_h, desktoph); + } + if(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN) + { + if(fullscreendesktop) gl_resize(); + else resetfullscreen(); + initwindowpos = true; + } + else + { + SDL_SetWindowSize(screen, scr_w, scr_h); + SDL_SetWindowPosition(screen, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + initwindowpos = false; + } + } + else + { + initwarning("screen resolution"); + } } ICOMMAND(screenres, "ii", (int *w, int *h), screenres(*w, *h)); static void setgamma(int val) { - if(screen && SDL_SetWindowBrightness(screen, val/100.0f) < 0) conoutf(CON_ERROR, "Could not set gamma: %s", SDL_GetError()); + if(screen && SDL_SetWindowBrightness(screen, val/100.0f) < 0) conoutf(CON_ERROR, "Could not set gamma: %s", SDL_GetError()); } static int curgamma = 100; VARFNP(gamma, reqgamma, 30, 100, 300, { - if(initing || reqgamma == curgamma) return; - curgamma = reqgamma; - setgamma(curgamma); + if(initing || reqgamma == curgamma) return; + curgamma = reqgamma; + setgamma(curgamma); }); void restoregamma() { - if(initing || reqgamma == 100) return; - curgamma = reqgamma; - setgamma(curgamma); + if(initing || reqgamma == 100) return; + curgamma = reqgamma; + setgamma(curgamma); } void cleargamma() { - if(curgamma != 100 && screen) SDL_SetWindowBrightness(screen, 1.0f); + if(curgamma != 100 && screen) SDL_SetWindowBrightness(screen, 1.0f); } int curvsync = -1; void restorevsync() { - if(initing || !glcontext) return; - extern int vsync, vsynctear; - if(!SDL_GL_SetSwapInterval(vsync ? (vsynctear ? -1 : 1) : 0)) - curvsync = vsync; + if(initing || !glcontext) return; + extern int vsync, vsynctear; + if(!SDL_GL_SetSwapInterval(vsync ? (vsynctear ? -1 : 1) : 0)) + curvsync = vsync; } VARFP(vsync, 0, 0, 1, restorevsync()); @@ -609,168 +598,162 @@ VARFP(vsynctear, 0, 0, 1, { if(vsync) restorevsync(); }); void setupscreen() { - if(glcontext) - { - SDL_GL_DeleteContext(glcontext); - glcontext = NULL; - } - if(screen) - { - SDL_DestroyWindow(screen); - screen = NULL; - } - curvsync = -1; - - SDL_Rect desktop; - if(SDL_GetDisplayBounds(0, &desktop) < 0) fatal("failed querying desktop bounds: %s", SDL_GetError()); - desktopw = desktop.w; - desktoph = desktop.h; - - if(scr_h < 0) scr_h = fullscreen ? desktoph : SCR_DEFAULTH; - if(scr_w < 0) scr_w = (scr_h*desktopw)/desktoph; - scr_w = clamp(scr_w, SCR_MINW, SCR_MAXW); - scr_h = clamp(scr_h, SCR_MINH, SCR_MAXH); - if(fullscreendesktop) - { - scr_w = min(scr_w, desktopw); - scr_h = min(scr_h, desktoph); - } - - int winx = SDL_WINDOWPOS_UNDEFINED, winy = SDL_WINDOWPOS_UNDEFINED, winw = scr_w, winh = scr_h, flags = SDL_WINDOW_RESIZABLE; - if(fullscreen) - { - if(fullscreendesktop) - { - winw = desktopw; - winh = desktoph; - flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - } - else flags |= SDL_WINDOW_FULLSCREEN; - initwindowpos = true; - } - - SDL_GL_ResetAttributes(); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - #if !defined(WIN32) && !defined(__APPLE__) - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - #endif - static const int configs[] = - { - 0x3, /* try everything */ - 0x2, 0x1, /* try disabling one at a time */ - 0 /* try disabling everything */ - }; - int config = 0; - if(!depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - if(!fsaa) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); - } - loopi(sizeof(configs)/sizeof(configs[0])) - { - config = configs[i]; - if(!depthbits && config&1) continue; - if(fsaa<=0 && config&2) continue; - if(depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config&1 ? depthbits : 24); - if(fsaa>0) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, config&2 ? 1 : 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config&2 ? fsaa : 0); - } - screen = SDL_CreateWindow("Cube 2: Sauerbraten", winx, winy, winw, winh, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | flags); - if(!screen) continue; - - #ifdef __APPLE__ - static const int glversions[] = { 32, 20 }; - #else - static const int glversions[] = { 33, 32, 31, 30, 20 }; - #endif - loopj(sizeof(glversions)/sizeof(glversions[0])) - { - glcompat = glversions[j] <= 30 ? 1 : 0; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glversions[j] / 10); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glversions[j] % 10); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, glversions[j] >= 32 ? SDL_GL_CONTEXT_PROFILE_CORE : 0); - glcontext = SDL_GL_CreateContext(screen); - if(glcontext) break; - } - if(glcontext) break; - } - if(!screen) fatal("failed to create OpenGL window: %s", SDL_GetError()); - else if(!glcontext) fatal("failed to create OpenGL context: %s", SDL_GetError()); - else - { - if(depthbits && (config&1)==0) conoutf(CON_WARN, "%d bit z-buffer not supported - disabling", depthbits); - if(fsaa>0 && (config&2)==0) conoutf(CON_WARN, "%dx anti-aliasing not supported - disabling", fsaa); - } - - SDL_SetWindowMinimumSize(screen, SCR_MINW, SCR_MINH); - SDL_SetWindowMaximumSize(screen, SCR_MAXW, SCR_MAXH); - - SDL_GetWindowSize(screen, &screenw, &screenh); + if(glcontext) + { + SDL_GL_DeleteContext(glcontext); + glcontext = NULL; + } + if(screen) + { + SDL_DestroyWindow(screen); + screen = NULL; + } + curvsync = -1; + + SDL_Rect desktop; + if(SDL_GetDisplayBounds(0, &desktop) < 0) fatal("failed querying desktop bounds: %s", SDL_GetError()); + desktopw = desktop.w; + desktoph = desktop.h; + + if(scr_h < 0) scr_h = fullscreen ? desktoph : SCR_DEFAULTH; + if(scr_w < 0) scr_w = (scr_h*desktopw)/desktoph; + scr_w = clamp(scr_w, SCR_MINW, SCR_MAXW); + scr_h = clamp(scr_h, SCR_MINH, SCR_MAXH); + if(fullscreendesktop) + { + scr_w = min(scr_w, desktopw); + scr_h = min(scr_h, desktoph); + } + + int winx = SDL_WINDOWPOS_UNDEFINED, winy = SDL_WINDOWPOS_UNDEFINED, winw = scr_w, winh = scr_h, flags = SDL_WINDOW_RESIZABLE; + if(fullscreen) + { + if(fullscreendesktop) + { + winw = desktopw; + winh = desktoph; + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } + else flags |= SDL_WINDOW_FULLSCREEN; + initwindowpos = true; + } + + SDL_GL_ResetAttributes(); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + static const int configs[] = + { + 0x3, /* try everything */ + 0x2, 0x1, /* try disabling one at a time */ + 0 /* try disabling everything */ + }; + int config = 0; + if(!depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + if(!fsaa) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + } + loopi(sizeof(configs)/sizeof(configs[0])) + { + config = configs[i]; + if(!depthbits && config&1) continue; + if(fsaa<=0 && config&2) continue; + if(depthbits) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config&1 ? depthbits : 24); + if(fsaa>0) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, config&2 ? 1 : 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config&2 ? fsaa : 0); + } + screen = SDL_CreateWindow("Cube 2: Sauerbraten", winx, winy, winw, winh, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | flags); + if(!screen) continue; + + static const int glversions[] = { 33, 32, 31, 30, 20 }; + loopj(sizeof(glversions)/sizeof(glversions[0])) + { + glcompat = glversions[j] <= 30 ? 1 : 0; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glversions[j] / 10); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glversions[j] % 10); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, glversions[j] >= 32 ? SDL_GL_CONTEXT_PROFILE_CORE : 0); + glcontext = SDL_GL_CreateContext(screen); + if(glcontext) break; + } + if(glcontext) break; + } + if(!screen) fatal("failed to create OpenGL window: %s", SDL_GetError()); + else if(!glcontext) fatal("failed to create OpenGL context: %s", SDL_GetError()); + else + { + if(depthbits && (config&1)==0) conoutf(CON_WARN, "%d bit z-buffer not supported - disabling", depthbits); + if(fsaa>0 && (config&2)==0) conoutf(CON_WARN, "%dx anti-aliasing not supported - disabling", fsaa); + } + + SDL_SetWindowMinimumSize(screen, SCR_MINW, SCR_MINH); + SDL_SetWindowMaximumSize(screen, SCR_MAXW, SCR_MAXH); + + SDL_GetWindowSize(screen, &screenw, &screenh); } void resetgl() { - clearchanges(CHANGE_GFX); - - renderbackground("resetting OpenGL"); - - extern void cleanupva(); - extern void cleanupparticles(); - extern void cleanupdecals(); - extern void cleanupsky(); - extern void cleanupmodels(); - extern void cleanupprefabs(); - extern void cleanuplightmaps(); - extern void cleanupblendmap(); - extern void cleanshadowmap(); - extern void cleanreflections(); - extern void cleanupglare(); - extern void cleanupdepthfx(); - cleanupva(); - cleanupparticles(); - cleanupdecals(); - cleanupsky(); - cleanupmodels(); - cleanupprefabs(); - cleanuptextures(); - cleanuplightmaps(); - cleanupblendmap(); - cleanshadowmap(); - cleanreflections(); - cleanupglare(); - cleanupdepthfx(); - cleanupshaders(); - cleanupgl(); - - setupscreen(); - inputgrab(grabinput); - gl_init(); - - inbetweenframes = false; - if(!reloadtexture(*notexture) || - !reloadtexture("data/logo.png") || - !reloadtexture("data/logo_1024.png") || - !reloadtexture("data/background.png") || - !reloadtexture("data/background_detail.png") || - !reloadtexture("data/background_decal.png") || - !reloadtexture("data/mapshot_frame.png") || - !reloadtexture("data/loading_frame.png") || - !reloadtexture("data/loading_bar.png")) - fatal("failed to reload core texture"); - reloadfonts(); - inbetweenframes = true; - renderbackground("initializing..."); - restoregamma(); - restorevsync(); - reloadshaders(); - reloadtextures(); - initlights(); - allchanged(true); + clearchanges(CHANGE_GFX); + + renderbackground("resetting OpenGL"); + + extern void cleanupva(); + extern void cleanupparticles(); + extern void cleanupdecals(); + extern void cleanupsky(); + extern void cleanupmodels(); + extern void cleanupprefabs(); + extern void cleanuplightmaps(); + extern void cleanupblendmap(); + extern void cleanshadowmap(); + extern void cleanreflections(); + extern void cleanupglare(); + extern void cleanupdepthfx(); + cleanupva(); + cleanupparticles(); + cleanupdecals(); + cleanupsky(); + cleanupmodels(); + cleanupprefabs(); + cleanuptextures(); + cleanuplightmaps(); + cleanupblendmap(); + cleanshadowmap(); + cleanreflections(); + cleanupglare(); + cleanupdepthfx(); + cleanupshaders(); + cleanupgl(); + + setupscreen(); + inputgrab(grabinput); + gl_init(); + + inbetweenframes = false; + if(!reloadtexture(*notexture) || + !reloadtexture("data/logo.png") || + !reloadtexture("data/logo_1024.png") || + !reloadtexture("data/background.png") || + !reloadtexture("data/background_detail.png") || + !reloadtexture("data/background_decal.png") || + !reloadtexture("data/mapshot_frame.png") || + !reloadtexture("data/loading_frame.png") || + !reloadtexture("data/loading_bar.png")) + fatal("failed to reload core texture"); + reloadfonts(); + inbetweenframes = true; + renderbackground("initializing..."); + restoregamma(); + restorevsync(); + reloadshaders(); + reloadtextures(); + initlights(); + allchanged(true); } COMMAND(resetgl, ""); @@ -779,233 +762,229 @@ static queue<SDL_Event, 32> events; static inline bool filterevent(const SDL_Event &event) { - switch(event.type) - { - case SDL_MOUSEMOTION: - if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { - if(event.motion.x == screenw / 2 && event.motion.y == screenh / 2) - return false; // ignore any motion events generated by SDL_WarpMouse - #ifdef __APPLE__ - if(event.motion.y == 0) - return false; // let mac users drag windows via the title bar - #endif - } - break; - } - return true; + switch(event.type) + { + case SDL_MOUSEMOTION: + if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) + { + if(event.motion.x == screenw / 2 && event.motion.y == screenh / 2) + return false; // ignore any motion events generated by SDL_WarpMouse + } + break; + } + return true; } template <int SIZE> static inline bool pumpevents(queue<SDL_Event, SIZE> &events) { - while(events.empty()) - { - SDL_PumpEvents(); - databuf<SDL_Event> buf = events.reserve(events.capacity()); - int n = SDL_PeepEvents(buf.getbuf(), buf.remaining(), SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); - if(n <= 0) return false; - loopi(n) if(filterevent(buf.buf[i])) buf.put(buf.buf[i]); - events.addbuf(buf); - } - return true; + while(events.empty()) + { + SDL_PumpEvents(); + databuf<SDL_Event> buf = events.reserve(events.capacity()); + int n = SDL_PeepEvents(buf.getbuf(), buf.remaining(), SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); + if(n <= 0) return false; + loopi(n) if(filterevent(buf.buf[i])) buf.put(buf.buf[i]); + events.addbuf(buf); + } + return true; } static int interceptkeysym = 0; static int interceptevents(void *data, SDL_Event *event) { - switch(event->type) - { - case SDL_MOUSEMOTION: return 0; - case SDL_KEYDOWN: - if(event->key.keysym.sym == interceptkeysym) - { - interceptkeysym = -interceptkeysym; - return 0; - } - break; - } - return 1; + switch(event->type) + { + case SDL_MOUSEMOTION: return 0; + case SDL_KEYDOWN: + if(event->key.keysym.sym == interceptkeysym) + { + interceptkeysym = -interceptkeysym; + return 0; + } + break; + } + return 1; } static void clearinterceptkey() { - SDL_DelEventWatch(interceptevents, NULL); - interceptkeysym = 0; + SDL_DelEventWatch(interceptevents, NULL); + interceptkeysym = 0; } bool interceptkey(int sym) { - if(!interceptkeysym) - { - interceptkeysym = sym; - SDL_FilterEvents(interceptevents, NULL); - if(interceptkeysym < 0) - { - interceptkeysym = 0; - return true; - } - SDL_AddEventWatch(interceptevents, NULL); - } - else if(abs(interceptkeysym) != sym) interceptkeysym = sym; - SDL_PumpEvents(); - if(interceptkeysym < 0) - { - clearinterceptkey(); - interceptkeysym = sym; - SDL_FilterEvents(interceptevents, NULL); - interceptkeysym = 0; - return true; - } - return false; + if(!interceptkeysym) + { + interceptkeysym = sym; + SDL_FilterEvents(interceptevents, NULL); + if(interceptkeysym < 0) + { + interceptkeysym = 0; + return true; + } + SDL_AddEventWatch(interceptevents, NULL); + } + else if(abs(interceptkeysym) != sym) interceptkeysym = sym; + SDL_PumpEvents(); + if(interceptkeysym < 0) + { + clearinterceptkey(); + interceptkeysym = sym; + SDL_FilterEvents(interceptevents, NULL); + interceptkeysym = 0; + return true; + } + return false; } static void ignoremousemotion() { - SDL_PumpEvents(); - SDL_FlushEvent(SDL_MOUSEMOTION); + SDL_PumpEvents(); + SDL_FlushEvent(SDL_MOUSEMOTION); } static void resetmousemotion() { - if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { - SDL_WarpMouseInWindow(screen, screenw / 2, screenh / 2); - } + if(grabinput && !relativemouse && !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) + { + SDL_WarpMouseInWindow(screen, screenw / 2, screenh / 2); + } } static void checkmousemotion(int &dx, int &dy) { - while(pumpevents(events)) - { - SDL_Event &event = events.removing(); - if(event.type != SDL_MOUSEMOTION) return; - dx += event.motion.xrel; - dy += event.motion.yrel; - events.remove(); - } + while(pumpevents(events)) + { + SDL_Event &event = events.removing(); + if(event.type != SDL_MOUSEMOTION) return; + dx += event.motion.xrel; + dy += event.motion.yrel; + events.remove(); + } } void checkinput() { - if(interceptkeysym) clearinterceptkey(); - //int lasttype = 0, lastbut = 0; - bool mousemoved = false; - int focused = 0; - while(pumpevents(events)) - { - SDL_Event &event = events.remove(); - - if(focused && event.type!=SDL_WINDOWEVENT) { if(grabinput != (focused>0)) inputgrab(grabinput = focused>0, shouldgrab); focused = 0; } - - switch(event.type) - { - case SDL_QUIT: - quit(); - return; - - case SDL_TEXTINPUT: - if(textinputmask && int(event.text.timestamp-textinputtime) >= textinputfilter) - { - uchar buf[SDL_TEXTINPUTEVENT_TEXT_SIZE+1]; - size_t len = decodeutf8(buf, sizeof(buf)-1, (const uchar *)event.text.text, strlen(event.text.text)); - if(len > 0) { buf[len] = '\0'; processtextinput((const char *)buf, len); } - } - break; - - case SDL_KEYDOWN: - case SDL_KEYUP: - if(keyrepeatmask || !event.key.repeat) - processkey(event.key.keysym.sym, event.key.state==SDL_PRESSED, event.key.keysym.mod | SDL_GetModState()); - break; - - case SDL_WINDOWEVENT: - switch(event.window.event) - { - case SDL_WINDOWEVENT_CLOSE: - quit(); - break; - - case SDL_WINDOWEVENT_FOCUS_GAINED: - shouldgrab = true; - break; - case SDL_WINDOWEVENT_ENTER: - shouldgrab = false; - focused = 1; - break; - - case SDL_WINDOWEVENT_LEAVE: - case SDL_WINDOWEVENT_FOCUS_LOST: - shouldgrab = false; - focused = -1; - break; - - case SDL_WINDOWEVENT_MINIMIZED: - minimized = true; - break; - - case SDL_WINDOWEVENT_MAXIMIZED: - case SDL_WINDOWEVENT_RESTORED: - minimized = false; - break; - - case SDL_WINDOWEVENT_RESIZED: - break; - - case SDL_WINDOWEVENT_SIZE_CHANGED: - { - SDL_GetWindowSize(screen, &screenw, &screenh); - if(!fullscreendesktop || !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) - { - scr_w = clamp(screenw, SCR_MINW, SCR_MAXW); - scr_h = clamp(screenh, SCR_MINH, SCR_MAXH); - } - gl_resize(); - break; - } - } - break; - - case SDL_MOUSEMOTION: - if(grabinput) - { - int dx = event.motion.xrel, dy = event.motion.yrel; - checkmousemotion(dx, dy); - if(!g3d_movecursor(dx, dy)) mousemove(dx, dy); - mousemoved = true; - } - else if(shouldgrab) inputgrab(grabinput = true); - break; - - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - //if(lasttype==event.type && lastbut==event.button.button) break; // why?? get event twice without it - switch(event.button.button) - { - case SDL_BUTTON_LEFT: processkey(-1, event.button.state==SDL_PRESSED); break; - case SDL_BUTTON_MIDDLE: processkey(-2, event.button.state==SDL_PRESSED); break; - case SDL_BUTTON_RIGHT: processkey(-3, event.button.state==SDL_PRESSED); break; - case SDL_BUTTON_X1: processkey(-6, event.button.state==SDL_PRESSED); break; - case SDL_BUTTON_X2: processkey(-7, event.button.state==SDL_PRESSED); break; - } - //lasttype = event.type; - //lastbut = event.button.button; - break; - - case SDL_MOUSEWHEEL: - if(event.wheel.y > 0) { processkey(-4, true); processkey(-4, false); } - else if(event.wheel.y < 0) { processkey(-5, true); processkey(-5, false); } - break; - } - } - if(focused) { if(grabinput != (focused>0)) inputgrab(grabinput = focused>0, shouldgrab); focused = 0; } - if(mousemoved) resetmousemotion(); + if(interceptkeysym) clearinterceptkey(); + //int lasttype = 0, lastbut = 0; + bool mousemoved = false; + int focused = 0; + while(pumpevents(events)) + { + SDL_Event &event = events.remove(); + + if(focused && event.type!=SDL_WINDOWEVENT) { if(grabinput != (focused>0)) inputgrab(grabinput = focused>0, shouldgrab); focused = 0; } + + switch(event.type) + { + case SDL_QUIT: + quit(); + return; + + case SDL_TEXTINPUT: + if(textinputmask && int(event.text.timestamp-textinputtime) >= textinputfilter) + { + uchar buf[SDL_TEXTINPUTEVENT_TEXT_SIZE+1]; + size_t len = decodeutf8(buf, sizeof(buf)-1, (const uchar *)event.text.text, strlen(event.text.text)); + if(len > 0) { buf[len] = '\0'; processtextinput((const char *)buf, len); } + } + break; + + case SDL_KEYDOWN: + case SDL_KEYUP: + if(keyrepeatmask || !event.key.repeat) + processkey(event.key.keysym.sym, event.key.state==SDL_PRESSED, event.key.keysym.mod | SDL_GetModState()); + break; + + case SDL_WINDOWEVENT: + switch(event.window.event) + { + case SDL_WINDOWEVENT_CLOSE: + quit(); + break; + + case SDL_WINDOWEVENT_FOCUS_GAINED: + shouldgrab = true; + break; + case SDL_WINDOWEVENT_ENTER: + shouldgrab = false; + focused = 1; + break; + + case SDL_WINDOWEVENT_LEAVE: + case SDL_WINDOWEVENT_FOCUS_LOST: + shouldgrab = false; + focused = -1; + break; + + case SDL_WINDOWEVENT_MINIMIZED: + minimized = true; + break; + + case SDL_WINDOWEVENT_MAXIMIZED: + case SDL_WINDOWEVENT_RESTORED: + minimized = false; + break; + + case SDL_WINDOWEVENT_RESIZED: + break; + + case SDL_WINDOWEVENT_SIZE_CHANGED: + { + SDL_GetWindowSize(screen, &screenw, &screenh); + if(!fullscreendesktop || !(SDL_GetWindowFlags(screen) & SDL_WINDOW_FULLSCREEN)) + { + scr_w = clamp(screenw, SCR_MINW, SCR_MAXW); + scr_h = clamp(screenh, SCR_MINH, SCR_MAXH); + } + gl_resize(); + break; + } + } + break; + + case SDL_MOUSEMOTION: + if(grabinput) + { + int dx = event.motion.xrel, dy = event.motion.yrel; + checkmousemotion(dx, dy); + if(!g3d_movecursor(dx, dy)) mousemove(dx, dy); + mousemoved = true; + } + else if(shouldgrab) inputgrab(grabinput = true); + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + //if(lasttype==event.type && lastbut==event.button.button) break; // why?? get event twice without it + switch(event.button.button) + { + case SDL_BUTTON_LEFT: processkey(-1, event.button.state==SDL_PRESSED); break; + case SDL_BUTTON_MIDDLE: processkey(-2, event.button.state==SDL_PRESSED); break; + case SDL_BUTTON_RIGHT: processkey(-3, event.button.state==SDL_PRESSED); break; + case SDL_BUTTON_X1: processkey(-6, event.button.state==SDL_PRESSED); break; + case SDL_BUTTON_X2: processkey(-7, event.button.state==SDL_PRESSED); break; + } + //lasttype = event.type; + //lastbut = event.button.button; + break; + + case SDL_MOUSEWHEEL: + if(event.wheel.y > 0) { processkey(-4, true); processkey(-4, false); } + else if(event.wheel.y < 0) { processkey(-5, true); processkey(-5, false); } + break; + } + } + if(focused) { if(grabinput != (focused>0)) inputgrab(grabinput = focused>0, shouldgrab); focused = 0; } + if(mousemoved) resetmousemotion(); } void swapbuffers(bool overlay) { - gle::disable(); - SDL_GL_SwapWindow(screen); + gle::disable(); + SDL_GL_SwapWindow(screen); } VAR(menufps, 0, 60, 1000); @@ -1013,68 +992,26 @@ VARP(maxfps, 0, 200, 1000); void limitfps(int &millis, int curmillis) { - int limit = (mainmenu || minimized) && menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; - if(!limit) return; - static int fpserror = 0; - int delay = 1000/limit - (millis-curmillis); - if(delay < 0) fpserror = 0; - else - { - fpserror += 1000%limit; - if(fpserror >= limit) - { - ++delay; - fpserror -= limit; - } - if(delay > 0) - { - SDL_Delay(delay); - millis += delay; - } - } -} - -#if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__) -void stackdumper(unsigned int type, EXCEPTION_POINTERS *ep) -{ - if(!ep) fatal("unknown type"); - EXCEPTION_RECORD *er = ep->ExceptionRecord; - CONTEXT *context = ep->ContextRecord; - char out[512]; - formatstring(out, "Cube 2: Sauerbraten Win32 Exception: 0x%x [0x%x]\n\n", er->ExceptionCode, er->ExceptionCode==EXCEPTION_ACCESS_VIOLATION ? er->ExceptionInformation[1] : -1); - SymInitialize(GetCurrentProcess(), NULL, TRUE); -#ifdef _AMD64_ - STACKFRAME64 sf = {{context->Rip, 0, AddrModeFlat}, {}, {context->Rbp, 0, AddrModeFlat}, {context->Rsp, 0, AddrModeFlat}, 0}; - while(::StackWalk64(IMAGE_FILE_MACHINE_AMD64, GetCurrentProcess(), GetCurrentThread(), &sf, context, NULL, ::SymFunctionTableAccess, ::SymGetModuleBase, NULL)) + int limit = (mainmenu || minimized) && menufps ? (maxfps ? min(maxfps, menufps) : menufps) : maxfps; + if(!limit) return; + static int fpserror = 0; + int delay = 1000/limit - (millis-curmillis); + if(delay < 0) fpserror = 0; + else { - union { IMAGEHLP_SYMBOL64 sym; char symext[sizeof(IMAGEHLP_SYMBOL64) + sizeof(string)]; }; - sym.SizeOfStruct = sizeof(sym); - sym.MaxNameLength = sizeof(symext) - sizeof(sym); - IMAGEHLP_LINE64 line; - line.SizeOfStruct = sizeof(line); - DWORD64 symoff; - DWORD lineoff; - if(SymGetSymFromAddr64(GetCurrentProcess(), sf.AddrPC.Offset, &symoff, &sym) && SymGetLineFromAddr64(GetCurrentProcess(), sf.AddrPC.Offset, &lineoff, &line)) -#else - STACKFRAME sf = {{context->Eip, 0, AddrModeFlat}, {}, {context->Ebp, 0, AddrModeFlat}, {context->Esp, 0, AddrModeFlat}, 0}; - while(::StackWalk(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &sf, context, NULL, ::SymFunctionTableAccess, ::SymGetModuleBase, NULL)) - { - union { IMAGEHLP_SYMBOL sym; char symext[sizeof(IMAGEHLP_SYMBOL) + sizeof(string)]; }; - sym.SizeOfStruct = sizeof(sym); - sym.MaxNameLength = sizeof(symext) - sizeof(sym); - IMAGEHLP_LINE line; - line.SizeOfStruct = sizeof(line); - DWORD symoff, lineoff; - if(SymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, &symoff, &sym) && SymGetLineFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, &lineoff, &line)) -#endif - { - char *del = strrchr(line.FileName, '\\'); - concformatstring(out, "%s - %s [%d]\n", sym.Name, del ? del + 1 : line.FileName, line.LineNumber); - } - } - fatal(out); + fpserror += 1000%limit; + if(fpserror >= limit) + { + ++delay; + fpserror -= limit; + } + if(delay > 0) + { + SDL_Delay(delay); + millis += delay; + } + } } -#endif #define MAXFPSHISTORY 60 @@ -1082,38 +1019,38 @@ int fpspos = 0, fpshistory[MAXFPSHISTORY]; void resetfpshistory() { - loopi(MAXFPSHISTORY) fpshistory[i] = 1; - fpspos = 0; + loopi(MAXFPSHISTORY) fpshistory[i] = 1; + fpspos = 0; } void updatefpshistory(int millis) { - fpshistory[fpspos++] = max(1, min(1000, millis)); - if(fpspos>=MAXFPSHISTORY) fpspos = 0; + fpshistory[fpspos++] = max(1, min(1000, millis)); + if(fpspos>=MAXFPSHISTORY) fpspos = 0; } void getfps(int &fps, int &bestdiff, int &worstdiff) { - int total = fpshistory[MAXFPSHISTORY-1], best = total, worst = total; - loopi(MAXFPSHISTORY-1) - { - int millis = fpshistory[i]; - total += millis; - if(millis < best) best = millis; - if(millis > worst) worst = millis; - } - - fps = (1000*MAXFPSHISTORY)/total; - bestdiff = 1000/best-fps; - worstdiff = fps-1000/worst; + int total = fpshistory[MAXFPSHISTORY-1], best = total, worst = total; + loopi(MAXFPSHISTORY-1) + { + int millis = fpshistory[i]; + total += millis; + if(millis < best) best = millis; + if(millis > worst) worst = millis; + } + + fps = (1000*MAXFPSHISTORY)/total; + bestdiff = 1000/best-fps; + worstdiff = fps-1000/worst; } void getfps_(int *raw) { - int fps, bestdiff, worstdiff; - if(*raw) fps = 1000/fpshistory[(fpspos+MAXFPSHISTORY-1)%MAXFPSHISTORY]; - else getfps(fps, bestdiff, worstdiff); - intret(fps); + int fps, bestdiff, worstdiff; + if(*raw) fps = 1000/fpshistory[(fpspos+MAXFPSHISTORY-1)%MAXFPSHISTORY]; + else getfps(fps, bestdiff, worstdiff); + intret(fps); } COMMANDN(getfps, getfps_, "i"); @@ -1122,8 +1059,8 @@ bool inbetweenframes = false, renderedframe = true; static bool findarg(int argc, char **argv, const char *str) { - for(int i = 1; i<argc; i++) if(strstr(argv[i], str)==argv[i]) return true; - return false; + for(int i = 1; i<argc; i++) if(strstr(argv[i], str)==argv[i]) return true; + return false; } static int clockrealbase = 0, clockvirtbase = 0; @@ -1133,239 +1070,224 @@ VARFP(clockfix, 0, 0, 1, clockreset()); int getclockmillis() { - int millis = SDL_GetTicks() - clockrealbase; - if(clockfix) millis = int(millis*(double(clockerror)/1000000)); - millis += clockvirtbase; - return max(millis, totalmillis); + int millis = SDL_GetTicks() - clockrealbase; + if(clockfix) millis = int(millis*(double(clockerror)/1000000)); + millis += clockvirtbase; + return max(millis, totalmillis); } VAR(numcpus, 1, 1, 16); int main(int argc, char **argv) { - #ifdef WIN32 - //atexit((void (__cdecl *)(void))_CrtDumpMemoryLeaks); - #ifndef _DEBUG - #ifndef __GNUC__ - __try { - #endif - #endif - #endif - - setlogfile(NULL); - - int dedicated = 0; - char *load = NULL, *initscript = NULL; - - initing = INIT_RESET; - // set home dir first - for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'q') { sethomedir(&argv[i][2]); break; } - // set log after home dir, but before anything else - for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'g') - { - const char *file = argv[i][2] ? &argv[i][2] : "log.txt"; - setlogfile(file); - logoutf("Setting log file: %s", file); - break; - } - execfile("init.cfg", false); - for(int i = 1; i<argc; i++) - { - if(argv[i][0]=='-') switch(argv[i][1]) - { - case 'q': if(homedir[0]) logoutf("Using home directory: %s", homedir); break; - case 'r': /* compat, ignore */ break; - case 'k': - { - const char *dir = addpackagedir(&argv[i][2]); - if(dir) logoutf("Adding package directory: %s", dir); - break; - } - case 'g': break; - case 'd': dedicated = atoi(&argv[i][2]); if(dedicated<=0) dedicated = 2; break; - case 'w': scr_w = clamp(atoi(&argv[i][2]), SCR_MINW, SCR_MAXW); if(!findarg(argc, argv, "-h")) scr_h = -1; break; - case 'h': scr_h = clamp(atoi(&argv[i][2]), SCR_MINH, SCR_MAXH); if(!findarg(argc, argv, "-w")) scr_w = -1; break; - case 'z': depthbits = atoi(&argv[i][2]); break; - case 'b': /* compat, ignore */ break; - case 'a': fsaa = atoi(&argv[i][2]); break; - case 'v': /* compat, ignore */ break; - case 't': fullscreen = atoi(&argv[i][2]); break; - case 's': /* compat, ignore */ break; - case 'f': /* compat, ignore */ break; - case 'l': - { - char pkgdir[] = "packages/"; - load = strstr(path(&argv[i][2]), path(pkgdir)); - if(load) load += sizeof(pkgdir)-1; - else load = &argv[i][2]; - break; - } - case 'x': initscript = &argv[i][2]; break; - default: if(!serveroption(argv[i])) gameargs.add(argv[i]); break; - } - else gameargs.add(argv[i]); - } - initing = NOT_INITING; - - numcpus = clamp(SDL_GetCPUCount(), 1, 16); - - if(dedicated <= 1) - { - logoutf("init: sdl"); - - if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_AUDIO)<0) fatal("Unable to initialize SDL: %s", SDL_GetError()); + setlogfile(NULL); + + int dedicated = 0; + char *load = NULL, *initscript = NULL; + + initing = INIT_RESET; + // set home dir first + for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'q') { sethomedir(&argv[i][2]); break; } + // set log after home dir, but before anything else + for(int i = 1; i<argc; i++) if(argv[i][0]=='-' && argv[i][1] == 'g') + { + const char *file = argv[i][2] ? &argv[i][2] : "log.txt"; + setlogfile(file); + logoutf("Setting log file: %s", file); + break; + } + execfile("init.cfg", false); + for(int i = 1; i<argc; i++) + { + if(argv[i][0]=='-') switch(argv[i][1]) + { + case 'q': if(homedir[0]) logoutf("Using home directory: %s", homedir); break; + case 'r': /* compat, ignore */ break; + case 'k': + { + const char *dir = addpackagedir(&argv[i][2]); + if(dir) logoutf("Adding package directory: %s", dir); + break; + } + case 'g': break; + case 'd': dedicated = atoi(&argv[i][2]); if(dedicated<=0) dedicated = 2; break; + case 'w': scr_w = clamp(atoi(&argv[i][2]), SCR_MINW, SCR_MAXW); if(!findarg(argc, argv, "-h")) scr_h = -1; break; + case 'h': scr_h = clamp(atoi(&argv[i][2]), SCR_MINH, SCR_MAXH); if(!findarg(argc, argv, "-w")) scr_w = -1; break; + case 'z': depthbits = atoi(&argv[i][2]); break; + case 'b': /* compat, ignore */ break; + case 'a': fsaa = atoi(&argv[i][2]); break; + case 'v': /* compat, ignore */ break; + case 't': fullscreen = atoi(&argv[i][2]); break; + case 's': /* compat, ignore */ break; + case 'f': /* compat, ignore */ break; + case 'l': + { + char pkgdir[] = "packages/"; + load = strstr(path(&argv[i][2]), path(pkgdir)); + if(load) load += sizeof(pkgdir)-1; + else load = &argv[i][2]; + break; + } + case 'x': initscript = &argv[i][2]; break; + default: if(!serveroption(argv[i])) gameargs.add(argv[i]); break; + } + else gameargs.add(argv[i]); + } + initing = NOT_INITING; + + numcpus = clamp(SDL_GetCPUCount(), 1, 16); + + if(dedicated <= 1) + { + logoutf("init: sdl"); + + if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_AUDIO)<0) fatal("Unable to initialize SDL: %s", SDL_GetError()); #ifdef SDL_VIDEO_DRIVER_X11 - SDL_version version; - SDL_GetVersion(&version); - if (SDL_VERSIONNUM(version.major, version.minor, version.patch) <= SDL_VERSIONNUM(2, 0, 12)) - sdl_xgrab_bug = 1; + SDL_version version; + SDL_GetVersion(&version); + if (SDL_VERSIONNUM(version.major, version.minor, version.patch) <= SDL_VERSIONNUM(2, 0, 12)) + sdl_xgrab_bug = 1; #endif - } - - logoutf("init: net"); - if(enet_initialize()<0) fatal("Unable to initialise network module"); - atexit(enet_deinitialize); - enet_time_set(0); - - logoutf("init: game"); - game::parseoptions(gameargs); - initserver(dedicated>0, dedicated>1); // never returns if dedicated - ASSERT(dedicated <= 1); - game::initclient(); - - logoutf("init: video"); - SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "0"); - #if !defined(WIN32) && !defined(__APPLE__) - SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); - #endif - setupscreen(); - SDL_ShowCursor(SDL_FALSE); - SDL_StopTextInput(); // workaround for spurious text-input events getting sent on first text input toggle? - - logoutf("init: gl"); - gl_checkextensions(); - gl_init(); - notexture = textureload("packages/textures/texture_error.png"); - if(!notexture) fatal("could not find core textures"); - - logoutf("init: console"); - if(!execfile("data/stdlib.cfg", false)) 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. - if(!execfile("packages/fonts/default.cfg", false)) fatal("cannot find font definitions"); - if(!setfont("default")) fatal("no default font specified"); - - inbetweenframes = true; - renderbackground("initializing..."); - - logoutf("init: world"); - camera1 = player = game::iterdynents(0); - emptymap(0, true, NULL, false); - - logoutf("init: sound"); - initsound(); - - logoutf("init: cfg"); - initing = INIT_LOAD; - execfile("data/keymap.cfg"); - execfile("data/stdedit.cfg"); - execfile("data/sounds.cfg"); - execfile("data/menus.cfg"); - execfile("data/heightmap.cfg"); - execfile("data/brushes.cfg"); - execfile("data/game.cfg"); - execfile("data/custom_maps_menu.cfg"); - if(game::savedservers()) execfile(game::savedservers(), false); - - identflags |= IDF_PERSIST; - - if(!execfile(game::savedconfig(), false)) - { - execfile(game::defaultconfig()); - writecfg(game::restoreconfig()); - } - execfile(game::autoexec(), false); - - identflags &= ~IDF_PERSIST; - - initing = INIT_GAME; - game::loadconfigs(); - - initing = NOT_INITING; - - logoutf("init: render"); - restoregamma(); - restorevsync(); - loadshaders(); - initparticles(); - initdecals(); - - identflags |= IDF_PERSIST; - - logoutf("init: mainloop"); - - if(execfile("once.cfg", false)) remove(findfile("once.cfg", "rb")); - - if(load) - { - logoutf("init: localconnect"); - //localconnect(); - game::changemap(load); - } - - if(initscript) execute(initscript); - - resetfpshistory(); - - inputgrab(grabinput = true); - ignoremousemotion(); - - for(;;) - { - static int frames = 0; - int millis = getclockmillis(); - limitfps(millis, totalmillis); - elapsedtime = millis - totalmillis; - static int timeerr = 0; - int scaledtime = game::scaletime(elapsedtime) + timeerr; - curtime = scaledtime/100; - timeerr = scaledtime%100; - if(!multiplayer(false) && curtime>200) curtime = 200; - if(game::ispaused()) curtime = 0; - lastmillis += curtime; - totalmillis = millis; - updatetime(); + } + + logoutf("init: net"); + if(enet_initialize()<0) fatal("Unable to initialise network module"); + atexit(enet_deinitialize); + enet_time_set(0); + + logoutf("init: game"); + game::parseoptions(gameargs); + initserver(dedicated>0, dedicated>1); // never returns if dedicated + ASSERT(dedicated <= 1); + game::initclient(); + + logoutf("init: video"); + SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "0"); + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); + setupscreen(); + SDL_ShowCursor(SDL_FALSE); + SDL_StopTextInput(); // workaround for spurious text-input events getting sent on first text input toggle? + + logoutf("init: gl"); + gl_checkextensions(); + gl_init(); + notexture = textureload("packages/textures/texture_error.png"); + if(!notexture) fatal("could not find core textures"); + + logoutf("init: console"); + if(!execfile("data/stdlib.cfg", false)) 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. + if(!execfile("packages/fonts/default.cfg", false)) fatal("cannot find font definitions"); + if(!setfont("default")) fatal("no default font specified"); + + inbetweenframes = true; + renderbackground("initializing..."); + + logoutf("init: world"); + camera1 = player = game::iterdynents(0); + emptymap(0, true, NULL, false); + + logoutf("init: sound"); + initsound(); + + logoutf("init: cfg"); + initing = INIT_LOAD; + execfile("data/keymap.cfg"); + execfile("data/stdedit.cfg"); + execfile("data/sounds.cfg"); + execfile("data/menus.cfg"); + execfile("data/heightmap.cfg"); + execfile("data/brushes.cfg"); + execfile("data/game.cfg"); + execfile("data/custom_maps_menu.cfg"); + if(game::savedservers()) execfile(game::savedservers(), false); + + identflags |= IDF_PERSIST; + + if(!execfile(game::savedconfig(), false)) + { + execfile(game::defaultconfig()); + writecfg(game::restoreconfig()); + } + execfile(game::autoexec(), false); + + identflags &= ~IDF_PERSIST; + + initing = INIT_GAME; + game::loadconfigs(); + + initing = NOT_INITING; + + logoutf("init: render"); + restoregamma(); + restorevsync(); + loadshaders(); + initparticles(); + initdecals(); + + identflags |= IDF_PERSIST; - checkinput(); - menuprocess(); - tryedit(); + logoutf("init: mainloop"); + + if(execfile("once.cfg", false)) remove(findfile("once.cfg", "rb")); + + if(load) + { + logoutf("init: localconnect"); + //localconnect(); + game::changemap(load); + } + + if(initscript) execute(initscript); + + resetfpshistory(); + + inputgrab(grabinput = true); + ignoremousemotion(); + + for(;;) + { + static int frames = 0; + int millis = getclockmillis(); + limitfps(millis, totalmillis); + elapsedtime = millis - totalmillis; + static int timeerr = 0; + int scaledtime = game::scaletime(elapsedtime) + timeerr; + curtime = scaledtime/100; + timeerr = scaledtime%100; + if(!multiplayer(false) && curtime>200) curtime = 200; + if(game::ispaused()) curtime = 0; + lastmillis += curtime; + totalmillis = millis; + updatetime(); - if(lastmillis) game::updateworld(); + checkinput(); + menuprocess(); + tryedit(); - checksleep(lastmillis); + if(lastmillis) game::updateworld(); - serverslice(false, 0); + checksleep(lastmillis); - if(frames) updatefpshistory(elapsedtime); - frames++; + serverslice(false, 0); - // miscellaneous general game effects - recomputecamera(); - updateparticles(); - updatesounds(); + if(frames) updatefpshistory(elapsedtime); + frames++; - if(minimized) continue; + // miscellaneous general game effects + recomputecamera(); + updateparticles(); + updatesounds(); - inbetweenframes = false; - if(mainmenu) gl_drawmainmenu(); - else gl_drawframe(); - swapbuffers(); - renderedframe = inbetweenframes = true; - } + if(minimized) continue; - ASSERT(0); - return EXIT_FAILURE; + inbetweenframes = false; + if(mainmenu) gl_drawmainmenu(); + else gl_drawframe(); + swapbuffers(); + renderedframe = inbetweenframes = true; + } - #if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__) - } __except(stackdumper(0, GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) { return 0; } - #endif + ASSERT(0); + return EXIT_FAILURE; } |
