1 #include "baselayer.h"
2
3 #include "a.h"
4 #include "build.h"
5 #include "cache1d.h"
6 #include "communityapi.h"
7 #include "compat.h"
8 #include "osd.h"
9 #include "polymost.h"
10 #include "renderlayer.h"
11
12 // video
13 #ifdef _WIN32
14 #include "winbits.h"
15 extern "C"
16 {
17 __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0x00000001;
18 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
19 }
20 #endif // _WIN32
21
22 int32_t g_borderless=2;
23
24 // input
25 char inputdevices = 0;
26
27 char keystatus[NUMKEYS];
28 char g_keyFIFO[KEYFIFOSIZ];
29 char g_keyAsciiFIFO[KEYFIFOSIZ];
30 uint8_t g_keyFIFOpos;
31 uint8_t g_keyFIFOend;
32 uint8_t g_keyAsciiPos;
33 uint8_t g_keyAsciiEnd;
34 char g_keyRemapTable[NUMKEYS];
35 char g_keyNameTable[NUMKEYS][24];
36
37 int32_t r_maxfps = -1;
38 int32_t r_maxfpsoffset;
39 uint64_t g_frameDelay;
40
41 void (*keypresscallback)(int32_t, int32_t);
42
keySetCallback(void (* callback)(int32_t,int32_t))43 void keySetCallback(void (*callback)(int32_t, int32_t)) { keypresscallback = callback; }
44
keyGetState(int32_t key)45 int32_t keyGetState(int32_t key) { return keystatus[g_keyRemapTable[key]]; }
46
keySetState(int32_t key,int32_t state)47 void keySetState(int32_t key, int32_t state)
48 {
49 keystatus[g_keyRemapTable[key]] = state;
50
51 if (state)
52 {
53 g_keyFIFO[g_keyFIFOend] = g_keyRemapTable[key];
54 g_keyFIFO[(g_keyFIFOend+1)&(KEYFIFOSIZ-1)] = state;
55 g_keyFIFOend = ((g_keyFIFOend+2)&(KEYFIFOSIZ-1));
56 }
57 }
58
keyGetScan(void)59 char keyGetScan(void)
60 {
61 if (g_keyFIFOpos == g_keyFIFOend)
62 return 0;
63
64 char const c = g_keyFIFO[g_keyFIFOpos];
65 g_keyFIFOpos = ((g_keyFIFOpos + 2) & (KEYFIFOSIZ - 1));
66
67 return c;
68 }
69
keyFlushScans(void)70 void keyFlushScans(void)
71 {
72 Bmemset(&g_keyFIFO,0,sizeof(g_keyFIFO));
73 g_keyFIFOpos = g_keyFIFOend = 0;
74 }
75
76 //
77 // character-based input functions
78 //
keyGetChar(void)79 char keyGetChar(void)
80 {
81 if (g_keyAsciiPos == g_keyAsciiEnd)
82 return 0;
83
84 char const c = g_keyAsciiFIFO[g_keyAsciiPos];
85 g_keyAsciiPos = ((g_keyAsciiPos + 1) & (KEYFIFOSIZ - 1));
86
87 return c;
88 }
89
keyFlushChars(void)90 void keyFlushChars(void)
91 {
92 Bmemset(&g_keyAsciiFIFO,0,sizeof(g_keyAsciiFIFO));
93 g_keyAsciiPos = g_keyAsciiEnd = 0;
94 }
95
keyGetName(int32_t num)96 const char *keyGetName(int32_t num) { return ((unsigned)num >= NUMKEYS) ? NULL : g_keyNameTable[num]; }
97
98 vec2_t g_mousePos;
99 vec2_t g_mouseAbs;
100 int32_t g_mouseBits;
101 uint8_t g_mouseClickState;
102
103 bool g_mouseEnabled;
104 bool g_mouseGrabbed;
105 bool g_mouseInsideWindow = 1;
106 bool g_mouseLockedToWindow = 1;
107
108 void (*g_mouseCallback)(int32_t, int32_t);
mouseSetCallback(void (* callback)(int32_t,int32_t))109 void mouseSetCallback(void(*callback)(int32_t, int32_t)) { g_mouseCallback = callback; }
110
mouseAdvanceClickState(void)111 int32_t mouseAdvanceClickState(void)
112 {
113 switch (g_mouseClickState)
114 {
115 case MOUSE_PRESSED: g_mouseClickState = MOUSE_HELD; return 1;
116 case MOUSE_RELEASED: g_mouseClickState = MOUSE_IDLE; return 1;
117 case MOUSE_HELD: return 1;
118 }
119 return 0;
120 }
121
mouseReadPos(int32_t * x,int32_t * y)122 void mouseReadPos(int32_t *x, int32_t *y)
123 {
124 if (!g_mouseEnabled || !g_mouseGrabbed || !appactive)
125 {
126 *x = *y = 0;
127 return;
128 }
129
130 *x = g_mousePos.x;
131 *y = g_mousePos.y;
132 g_mousePos.x = g_mousePos.y = 0;
133 }
134
mouseReadAbs(vec2_t * const pResult,vec2_t const * const pInput)135 int32_t mouseReadAbs(vec2_t * const pResult, vec2_t const * const pInput)
136 {
137 if (!g_mouseEnabled || !appactive || !g_mouseInsideWindow || (osd && osd->flags & OSD_CAPTURE))
138 return 0;
139
140 int32_t const xwidth = max(scale(240<<16, xdim, ydim), 320<<16);
141
142 pResult->x = scale(pInput->x, xwidth, xres) - ((xwidth>>1) - (320<<15));
143 pResult->y = scale(pInput->y, 200<<16, yres);
144
145 pResult->y = divscale16(pResult->y - (200<<15), rotatesprite_yxaspect) + (200<<15) - rotatesprite_y_offset;
146
147 return 1;
148 }
149
mouseReadButtons(void)150 int32_t mouseReadButtons(void)
151 {
152 return (!g_mouseEnabled || !appactive || !g_mouseInsideWindow || (osd && osd->flags & OSD_CAPTURE)) ? 0 : g_mouseBits;
153 }
154
155 controllerinput_t joystick;
156
joySetCallback(void (* callback)(int32_t,int32_t))157 void joySetCallback(void (*callback)(int32_t, int32_t)) { joystick.pCallback = callback; }
joyReadButtons(int32_t * pResult)158 void joyReadButtons(int32_t *pResult) { *pResult = appactive ? joystick.bits : 0; }
159
160 #if defined __linux || defined EDUKE32_BSD || defined __APPLE__
161 # include <sys/mman.h>
162 #endif
163
164 #if !defined(NOASM) && !defined(GEKKO) && !defined(__ANDROID__)
165 #ifdef __cplusplus
166 extern "C" {
167 #endif
168 extern intptr_t dep_begin, dep_end;
169 #ifdef __cplusplus
170 }
171 #endif
172 #endif
173
174 #if !defined(NOASM) && !defined(GEKKO) && !defined(__ANDROID__)
nx_unprotect(intptr_t beg,intptr_t end,int prot)175 static int32_t nx_unprotect(intptr_t beg, intptr_t end, int prot)
176 {
177 # if defined _WIN32
178 # define B_PROT_RW PAGE_READWRITE
179 # define B_PROT_RX PAGE_EXECUTE_READ
180 # define B_PROT_RWX PAGE_EXECUTE_READWRITE
181
182 DWORD oldprot;
183
184 if (!VirtualProtect((LPVOID) beg, (SIZE_T)end - (SIZE_T)beg, prot, &oldprot))
185 {
186 initprintf("VirtualProtect() error! Crashing in 3... 2... 1...\n");
187 return 1;
188 }
189 # elif defined __linux || defined EDUKE32_BSD || defined __APPLE__
190 # define B_PROT_RW (PROT_READ|PROT_WRITE)
191 # define B_PROT_RX (PROT_READ|PROT_EXEC)
192 # define B_PROT_RWX (PROT_READ|PROT_WRITE|PROT_EXEC)
193
194 int32_t pagesize;
195 size_t dep_begin_page;
196 pagesize = sysconf(_SC_PAGE_SIZE);
197 if (pagesize == -1)
198 {
199 initprintf("Error getting system page size\n");
200 return 1;
201 }
202 dep_begin_page = ((size_t)beg) & ~(pagesize-1);
203 if (mprotect((void *) dep_begin_page, (size_t)end - dep_begin_page, prot) < 0)
204 {
205 initprintf("Error making code writeable (errno=%d)\n", errno);
206 return 1;
207 }
208 # else
209 # error "Don't know how to unprotect the self-modifying assembly on this platform!"
210 # endif
211
212 return 0;
213 }
214 #endif
215
216
217 // Calculate ylookup[] and call setvlinebpl()
calc_ylookup(int32_t bpl,int32_t lastyidx)218 void calc_ylookup(int32_t bpl, int32_t lastyidx)
219 {
220 int32_t i, j=0;
221 static int32_t ylookupsiz;
222
223 Bassert(lastyidx <= MAXYDIM);
224
225 lastyidx++;
226
227 if (lastyidx > ylookupsiz)
228 {
229 Xaligned_free(ylookup);
230
231 ylookup = (intptr_t *)Xaligned_alloc(16, lastyidx * sizeof(intptr_t));
232 ylookupsiz = lastyidx;
233 }
234
235 for (i=0; i<=lastyidx-4; i+=4)
236 {
237 ylookup[i] = j;
238 ylookup[i + 1] = j + bpl;
239 ylookup[i + 2] = j + (bpl << 1);
240 ylookup[i + 3] = j + (bpl * 3);
241 j += (bpl << 2);
242 }
243
244 for (; i<lastyidx; i++)
245 {
246 ylookup[i] = j;
247 j += bpl;
248 }
249
250 setvlinebpl(bpl);
251 }
252
253
makeasmwriteable(void)254 void makeasmwriteable(void)
255 {
256 #if !defined(NOASM) && !defined(GEKKO) && !defined(__ANDROID__)
257 nx_unprotect((intptr_t)&dep_begin, (intptr_t)&dep_end, B_PROT_RWX);
258 #endif
259 }
260
261 int32_t vsync=0;
262 int32_t r_finishbeforeswap=0;
263 int32_t r_glfinish=0;
264 int32_t g_logFlushWindow = 1;
265
266 #ifdef USE_OPENGL
267 struct glinfo_t glinfo =
268 {
269 "Unknown", // vendor
270 "Unknown", // renderer
271 "0.0.0", // version
272 "", // extensions
273
274 1.0, // max anisotropy
275 0, // structure filled
276 0, // supported extensions
277 };
278
fill_glinfo(void)279 void fill_glinfo(void)
280 {
281 glinfo.extensions = (const char *)glGetString(GL_EXTENSIONS);
282 glinfo.renderer = (const char *)glGetString(GL_RENDERER);
283 glinfo.vendor = (const char *)glGetString(GL_VENDOR);
284 glinfo.version = (const char *)glGetString(GL_VERSION);
285
286 #ifdef POLYMER
287 if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc."))
288 {
289 pr_ati_fboworkaround = 1;
290 initprintf("Enabling ATI FBO color attachment workaround.\n");
291
292 if (Bstrstr(glinfo.renderer, "Radeon X1"))
293 {
294 pr_ati_nodepthoffset = 1;
295 initprintf("Enabling ATI R520 polygon offset workaround.\n");
296 }
297 # ifdef __APPLE__
298 // See bug description at http://lists.apple.com/archives/mac-opengl/2005/Oct/msg00169.html
299 if (!Bstrncmp(glinfo.renderer, "ATI Radeon 9600", 15))
300 {
301 pr_ati_textureformat_one = 1;
302 initprintf("Enabling ATI Radeon 9600 texture format workaround.\n");
303 }
304 # endif
305 }
306 #endif // defined POLYMER
307
308 // process the extensions string and flag stuff we recognize
309 glinfo.depthtex = !!Bstrstr(glinfo.extensions, "GL_ARB_depth_texture");
310 glinfo.fbos = !!Bstrstr(glinfo.extensions, "GL_EXT_framebuffer_object") || !!Bstrstr(glinfo.extensions, "GL_OES_framebuffer_object");
311 glinfo.shadow = !!Bstrstr(glinfo.extensions, "GL_ARB_shadow");
312 glinfo.texnpot = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_non_power_of_two") || !!Bstrstr(glinfo.extensions, "GL_OES_texture_npot");
313
314 #if !defined EDUKE32_GLES
315 glinfo.bgra = !!Bstrstr(glinfo.extensions, "GL_EXT_bgra");
316 glinfo.bufferstorage = !!Bstrstr(glinfo.extensions, "GL_ARB_buffer_storage");
317 glinfo.clamptoedge = !!Bstrstr(glinfo.extensions, "GL_EXT_texture_edge_clamp") || !!Bstrstr(glinfo.extensions, "GL_SGIS_texture_edge_clamp");
318 glinfo.debugoutput = !!Bstrstr(glinfo.extensions, "GL_ARB_debug_output");
319 glinfo.depthclamp = !!Bstrstr(glinfo.extensions, "GL_ARB_depth_clamp");
320 glinfo.glsl = !!Bstrstr(glinfo.extensions, "GL_ARB_shader_objects");
321 glinfo.multitex = !!Bstrstr(glinfo.extensions, "GL_ARB_multitexture");
322 glinfo.occlusionqueries = !!Bstrstr(glinfo.extensions, "GL_ARB_occlusion_query");
323 glinfo.rect = !!Bstrstr(glinfo.extensions, "GL_NV_texture_rectangle") || !!Bstrstr(glinfo.extensions, "GL_EXT_texture_rectangle");
324 glinfo.sync = !!Bstrstr(glinfo.extensions, "GL_ARB_sync");
325 glinfo.texcompr = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_compression") && Bstrcmp(glinfo.vendor, "ATI Technologies Inc.");
326 glinfo.vbos = !!Bstrstr(glinfo.extensions, "GL_ARB_vertex_buffer_object");
327 glinfo.vsync = !!Bstrstr(glinfo.extensions, "WGL_EXT_swap_control") || !!Bstrstr(glinfo.extensions, "GLX_EXT_swap_control");
328
329 # ifdef DYNAMIC_GLEXT
330 if (glinfo.texcompr && (!glCompressedTexImage2D || !glGetCompressedTexImage))
331 {
332 // lacking the necessary extensions to do this
333 initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
334 glinfo.texcompr = 0;
335 }
336 # endif
337 #else
338 // don't bother checking because ETC2 et al. are not listed in extensions anyway
339 glinfo.texcompr = 1; // !!Bstrstr(glinfo.extensions, "GL_OES_compressed_ETC1_RGB8_texture");
340 #endif
341
342 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glinfo.maxanisotropy);
343
344 if (!glinfo.filled)
345 {
346 int32_t oldbpp = bpp;
347 bpp = 32;
348 osdcmd_glinfo(NULL);
349 glinfo.filled = 1;
350 bpp = oldbpp;
351 }
352 }
353
354 // Used to register the game's / editor's osdcmd_vidmode() functions here.
355 int32_t (*baselayer_osdcmd_vidmode_func)(osdcmdptr_t parm);
356
osdfunc_setrendermode(osdcmdptr_t parm)357 static int osdfunc_setrendermode(osdcmdptr_t parm)
358 {
359 if (parm->numparms != 1)
360 return OSDCMD_SHOWHELP;
361
362 int32_t m = Bstrtol(parm->parms[0], NULL, 10);
363
364 if (m != REND_CLASSIC && m != REND_POLYMOST && m != REND_POLYMER)
365 return OSDCMD_SHOWHELP;
366
367 if ((m==REND_CLASSIC) != (bpp==8) && baselayer_osdcmd_vidmode_func)
368 {
369 // Mismatch between video mode and requested renderer, do auto switch.
370 osdfuncparm_t parm;
371 char arg[4];
372
373 const char *ptrptr[1];
374 ptrptr[0] = arg;
375
376 Bmemset(&parm, 0, sizeof(parm));
377
378 if (m==REND_CLASSIC)
379 Bmemcpy(&arg, "8", 2);
380 else
381 Bmemcpy(&arg, "32", 3);
382
383 // CAUTION: we assume that the osdcmd_vidmode function doesn't use any
384 // other member!
385 parm.numparms = 1;
386 parm.parms = ptrptr;
387
388 baselayer_osdcmd_vidmode_func(&parm);
389 }
390
391 videoSetRenderMode(m);
392
393 char const *renderer = "other";
394
395 switch (videoGetRenderMode())
396 {
397 case REND_CLASSIC:
398 #ifdef NOASM
399 renderer = "classic software (C)";
400 #else
401 renderer = "classic software (ASM)";
402 #endif
403 break;
404 case REND_POLYMOST:
405 renderer = "polygonal OpenGL";
406 break;
407 #ifdef POLYMER
408 case REND_POLYMER:
409 renderer = "great justice (Polymer)";
410 break;
411 #endif
412 }
413
414 OSD_Printf("Rendering method changed to %s\n", renderer);
415
416 return OSDCMD_OK;
417 }
418
419 #ifdef DEBUGGINGAIDS
osdcmd_hicsetpalettetint(osdcmdptr_t parm)420 static int osdcmd_hicsetpalettetint(osdcmdptr_t parm)
421 {
422 int32_t parms[8];
423
424 if (parm->numparms < 1 || (int32_t)ARRAY_SIZE(parms) < parm->numparms) return OSDCMD_SHOWHELP;
425
426 size_t i;
427 for (i = 0; (int32_t)i < parm->numparms; ++i)
428 parms[i] = Batol(parm->parms[i]);
429 for (; i < ARRAY_SIZE(parms); ++i)
430 parms[i] = 0;
431
432 // order is intentional
433 hicsetpalettetint(parms[0],parms[1],parms[2],parms[3],parms[5],parms[6],parms[7],parms[4]);
434
435 return OSDCMD_OK;
436 }
437 #endif
438
osdcmd_glinfo(osdcmdptr_t UNUSED (parm))439 int osdcmd_glinfo(osdcmdptr_t UNUSED(parm))
440 {
441 UNREFERENCED_CONST_PARAMETER(parm);
442
443 if (bpp == 8)
444 {
445 initprintf("glinfo: not in OpenGL mode!\n");
446 return OSDCMD_OK;
447 }
448
449 initprintf("OpenGL information\n %s %s %s\n",
450 glinfo.vendor, glinfo.renderer, glinfo.version);
451
452 if (!glinfo.filled)
453 return OSDCMD_OK;
454
455 char const *s[] = { "supported", "not supported" };
456
457 #define SUPPORTED(x) (x ? s[0] : s[1])
458
459 initprintf(" BGRA textures: %s\n", SUPPORTED(glinfo.bgra));
460 initprintf(" Clamp-to-edge: %s\n", SUPPORTED(glinfo.clamptoedge));
461 initprintf(" Framebuffer objects: %s\n", SUPPORTED(glinfo.fbos));
462 initprintf(" Multi-texturing: %s\n", SUPPORTED(glinfo.multitex));
463 initprintf(" Non-power-of-2 textures: %s\n", SUPPORTED(glinfo.texnpot));
464 #ifndef EDUKE32_GLES
465 initprintf(" Buffer storage: %s\n", SUPPORTED(glinfo.bufferstorage));
466 initprintf(" Debug output: %s\n", SUPPORTED(glinfo.debugoutput));
467 initprintf(" Depth textures: %s\n", SUPPORTED(glinfo.depthtex));
468 initprintf(" GLSL: %s\n", SUPPORTED(glinfo.glsl));
469 initprintf(" Occlusion queries: %s\n", SUPPORTED(glinfo.occlusionqueries));
470 initprintf(" Rectangle textures: %s\n", SUPPORTED(glinfo.rect));
471 initprintf(" Shadow textures: %s\n", SUPPORTED(glinfo.shadow));
472 initprintf(" Sync: %s\n", SUPPORTED(glinfo.sync));
473 initprintf(" Texture compression: %s\n", SUPPORTED(glinfo.texcompr));
474 initprintf(" Vertex buffer objects: %s\n", SUPPORTED(glinfo.vbos));
475 #endif
476 initprintf(" Maximum anisotropy: %.1f%s\n", glinfo.maxanisotropy, glinfo.maxanisotropy > 1.0 ? "" : " (no anisotropic filtering)");
477
478 #undef SUPPORTED
479
480 initprintf(" Extensions:\n%s", glinfo.extensions);
481
482 return OSDCMD_OK;
483 }
484 #endif
485
osdcmd_cvar_set_baselayer(osdcmdptr_t parm)486 static int osdcmd_cvar_set_baselayer(osdcmdptr_t parm)
487 {
488 int32_t r = osdcmd_cvar_set(parm);
489
490 if (r != OSDCMD_OK) return r;
491
492 if (!Bstrcasecmp(parm->name, "vid_gamma") || !Bstrcasecmp(parm->name, "vid_brightness") || !Bstrcasecmp(parm->name, "vid_contrast"))
493 {
494 videoSetPalette(GAMMA_CALC,0,0);
495 return r;
496 }
497 else if (!Bstrcasecmp(parm->name, "r_maxfps") || !Bstrcasecmp(parm->name, "r_maxfpsoffset"))
498 {
499 if (r_maxfps > 0) r_maxfps = clamp(r_maxfps, 30, 1000);
500 g_frameDelay = calcFrameDelay(r_maxfps, r_maxfpsoffset);
501 }
502 return r;
503 }
504
baselayer_init(void)505 int32_t baselayer_init(void)
506 {
507 #ifdef _WIN32
508 // on Windows, don't save the "r_screenaspect" cvar because the physical screen size is
509 // determined at startup
510 # define SCREENASPECT_CVAR_TYPE (CVAR_UINT|CVAR_NOSAVE)
511 #else
512 # define SCREENASPECT_CVAR_TYPE (CVAR_UINT)
513 #endif
514 static osdcvardata_t cvars_engine[] =
515 {
516 { "lz4compressionlevel","adjust LZ4 compression level used for savegames",(void *) &lz4CompressionLevel, CVAR_INT, 1, 32 },
517 { "r_borderless", "borderless windowed mode: 0: never 1: always 2: if resolution matches desktop", (void *) &r_borderless, CVAR_INT|CVAR_RESTARTVID, 0, 2 },
518 { "r_displayindex","index of output display",(void *)&r_displayindex, CVAR_INT|CVAR_RESTARTVID, 0, 10 },
519 { "r_usenewaspect","enable/disable new screen aspect ratio determination code",(void *) &r_usenewaspect, CVAR_BOOL, 0, 1 },
520 { "r_screenaspect","if using r_usenewaspect and in fullscreen, screen aspect ratio in the form XXYY, e.g. 1609 for 16:9",
521 (void *) &r_screenxy, SCREENASPECT_CVAR_TYPE, 0, 9999 },
522 { "r_fpgrouscan","use floating-point numbers for slope rendering",(void *) &r_fpgrouscan, CVAR_BOOL, 0, 1 },
523 { "r_novoxmips","turn off/on the use of mipmaps when rendering 8-bit voxels",(void *) &novoxmips, CVAR_BOOL, 0, 1 },
524 { "r_voxels","enable/disable automatic sprite->voxel rendering",(void *) &usevoxels, CVAR_BOOL, 0, 1 },
525 { "r_maxfps", "limit the frame rate", (void *)&r_maxfps, CVAR_INT | CVAR_FUNCPTR, -1, 1000 },
526 { "r_maxfpsoffset", "menu-controlled offset for r_maxfps", (void *)&r_maxfpsoffset, CVAR_INT | CVAR_FUNCPTR, -10, 10 },
527 #ifdef YAX_ENABLE
528 { "r_tror_nomaskpass", "enable/disable additional pass in TROR software rendering", (void *)&r_tror_nomaskpass, CVAR_BOOL, 0, 1 },
529 #endif
530 { "r_windowpositioning", "enable/disable window position memory", (void *) &windowpos, CVAR_BOOL, 0, 1 },
531 { "vid_gamma","adjusts gamma component of gamma ramp",(void *) &g_videoGamma, CVAR_FLOAT|CVAR_FUNCPTR, 0, 10 },
532 { "vid_contrast","adjusts contrast component of gamma ramp",(void *) &g_videoContrast, CVAR_FLOAT|CVAR_FUNCPTR, 0, 10 },
533 { "vid_brightness","adjusts brightness component of gamma ramp",(void *) &g_videoBrightness, CVAR_FLOAT|CVAR_FUNCPTR, -10, 10 },
534 #ifdef DEBUGGINGAIDS
535 { "debug1","debug counter",(void *) &debug1, CVAR_FLOAT, -100000, 100000 },
536 { "debug2","debug counter",(void *) &debug2, CVAR_FLOAT, -100000, 100000 },
537 #endif
538 #ifdef DEBUG_MASK_DRAWING
539 { "debug_maskdrawmode", "Show mask draw orders", (void *)&g_maskDrawMode, CVAR_BOOL, 0, 1 },
540 #endif
541 };
542
543 for (auto & i : cvars_engine)
544 OSD_RegisterCvar(&i, (i.flags & CVAR_FUNCPTR) ? osdcmd_cvar_set_baselayer : osdcmd_cvar_set);
545
546 #ifdef USE_OPENGL
547 OSD_RegisterFunction("setrendermode","setrendermode <number>: sets the engine's rendering mode.\n"
548 "Mode numbers are:\n"
549 " 0 - Classic Build software\n"
550 " 3 - Polygonal OpenGL\n"
551 #ifdef POLYMER
552 " 4 - Great justice renderer (Polymer)\n"
553 #endif
554 ,
555 osdfunc_setrendermode);
556
557 # ifdef DEBUGGINGAIDS
558 OSD_RegisterFunction("hicsetpalettetint","hicsetpalettetint: sets palette tinting values",osdcmd_hicsetpalettetint);
559 # endif
560
561 OSD_RegisterFunction("glinfo","glinfo: shows OpenGL information about the current OpenGL mode",osdcmd_glinfo);
562
563 polymost_initosdfuncs();
564 #endif
565
566 for (native_t i = 0; i < NUMKEYS; i++) g_keyRemapTable[i] = i;
567
568 return 0;
569 }
570
maybe_redirect_outputs(void)571 void maybe_redirect_outputs(void)
572 {
573 #if !(defined __APPLE__ && defined __BIG_ENDIAN__) && !defined(__DragonFly__)
574 char *argp;
575
576 // pipe standard outputs to files
577 if ((argp = Bgetenv("EDUKE32_LOGSTDOUT")) == NULL || Bstrcasecmp(argp, "TRUE"))
578 return;
579
580 FILE *fp = freopen("stdout.txt", "w", stdout);
581
582 if (!fp)
583 fp = fopen("stdout.txt", "w");
584
585 if (fp)
586 {
587 setvbuf(fp, 0, _IONBF, 0);
588 *stdout = *fp;
589 *stderr = *fp;
590 }
591 #endif
592 }
593
engineFPSLimit(void)594 int engineFPSLimit(void)
595 {
596 if (!r_maxfps)
597 return true;
598
599 g_frameDelay = calcFrameDelay(r_maxfps, r_maxfpsoffset);
600
601 uint64_t frameTicks;
602 static uint64_t nextFrameTicks;
603 static uint64_t frameDelay;
604
605 if (g_frameDelay != frameDelay)
606 {
607 nextFrameTicks = timerGetPerformanceCounter() + g_frameDelay;
608 frameDelay = g_frameDelay;
609 }
610 handleevents();
611 frameTicks = timerGetPerformanceCounter();
612
613 if (nextFrameTicks - frameTicks > g_frameDelay)
614 {
615 while (nextFrameTicks - frameTicks > g_frameDelay)
616 nextFrameTicks += g_frameDelay;
617
618 return true;
619 }
620
621 return false;
622 }
623