Subversion Repositories eduke32

Rev

Rev 8710 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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