Subversion Repositories eduke32

Rev

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

Rev 8728 Rev 8762
1
// SDL interface layer for the Build Engine
1
// SDL interface layer for the Build Engine
2
// Use SDL 1.2 or 2.0 from http://www.libsdl.org
2
// Use SDL 1.2 or 2.0 from http://www.libsdl.org
3
3
4
#include <signal.h>
4
#include <signal.h>
5
5
6
#include "a.h"
6
#include "a.h"
7
#include "build.h"
7
#include "build.h"
8
#include "cache1d.h"
8
#include "cache1d.h"
9
#include "compat.h"
9
#include "compat.h"
10
#include "build_cpuid.h"
10
#include "build_cpuid.h"
11
#include "engine_priv.h"
11
#include "engine_priv.h"
12
#include "osd.h"
12
#include "osd.h"
13
#include "palette.h"
13
#include "palette.h"
14
#include "renderlayer.h"
14
#include "renderlayer.h"
15
#include "sdl_inc.h"
15
#include "sdl_inc.h"
16
#include "softsurface.h"
16
#include "softsurface.h"
17
17
18
#ifdef USE_OPENGL
18
#ifdef USE_OPENGL
19
# include "glad/glad.h"
19
# include "glad/glad.h"
20
# include "glbuild.h"
20
# include "glbuild.h"
21
# include "glsurface.h"
21
# include "glsurface.h"
22
#endif
22
#endif
23
23
24
#if defined HAVE_GTK2
24
#if defined HAVE_GTK2
25
# include "gtkbits.h"
25
# include "gtkbits.h"
26
#endif
26
#endif
27
27
28
#ifdef __ANDROID__
28
#ifdef __ANDROID__
29
# include <android/log.h>
29
# include <android/log.h>
30
#elif defined __APPLE__
30
#elif defined __APPLE__
31
# include "osxbits.h"
31
# include "osxbits.h"
32
# include <mach/mach.h>
32
# include <mach/mach.h>
33
# include <mach/mach_time.h>
33
# include <mach/mach_time.h>
34
#elif defined GEKKO
34
#elif defined GEKKO
35
# include "wiibits.h"
35
# include "wiibits.h"
36
# include <ogc/lwp.h>
36
# include <ogc/lwp.h>
37
# include <ogc/lwp_watchdog.h>
37
# include <ogc/lwp_watchdog.h>
38
#elif defined _WIN32
38
#elif defined _WIN32
39
# include "winbits.h"
39
# include "winbits.h"
40
#endif
40
#endif
41
41
42
#include "vfs.h"
42
#include "vfs.h"
43
#include "communityapi.h"
43
#include "communityapi.h"
44
44
45
#if SDL_MAJOR_VERSION != 1
45
#if SDL_MAJOR_VERSION != 1
46
static SDL_version linked;
46
static SDL_version linked;
47
#else
47
#else
48
#define SDL_JoystickNameForIndex(x) SDL_JoystickName(x)
48
#define SDL_JoystickNameForIndex(x) SDL_JoystickName(x)
49
#endif
49
#endif
50
50
51
#if !defined STARTUP_SETUP_WINDOW
51
#if !defined STARTUP_SETUP_WINDOW
52
int32_t startwin_open(void) { return 0; }
52
int32_t startwin_open(void) { return 0; }
53
int32_t startwin_close(void) { return 0; }
53
int32_t startwin_close(void) { return 0; }
54
int32_t startwin_puts(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
54
int32_t startwin_puts(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
55
int32_t startwin_idle(void *s) { UNREFERENCED_PARAMETER(s); return 0; }
55
int32_t startwin_idle(void *s) { UNREFERENCED_PARAMETER(s); return 0; }
56
int32_t startwin_settitle(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
56
int32_t startwin_settitle(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
57
int32_t startwin_run(void) { return 0; }
57
int32_t startwin_run(void) { return 0; }
58
#endif
58
#endif
59
59
60
/// These can be useful for debugging sometimes...
60
/// These can be useful for debugging sometimes...
61
//#define SDL_WM_GrabInput(x) SDL_WM_GrabInput(SDL_GRAB_OFF)
61
//#define SDL_WM_GrabInput(x) SDL_WM_GrabInput(SDL_GRAB_OFF)
62
//#define SDL_ShowCursor(x) SDL_ShowCursor(SDL_ENABLE)
62
//#define SDL_ShowCursor(x) SDL_ShowCursor(SDL_ENABLE)
63
63
64
#define SURFACE_FLAGS   (SDL_SWSURFACE|SDL_HWPALETTE|SDL_HWACCEL)
64
#define SURFACE_FLAGS   (SDL_SWSURFACE|SDL_HWPALETTE|SDL_HWACCEL)
65
65
66
// undefine to restrict windowed resolutions to conventional sizes
66
// undefine to restrict windowed resolutions to conventional sizes
67
#define ANY_WINDOWED_SIZE
67
#define ANY_WINDOWED_SIZE
68
68
69
// fix for mousewheel
69
// fix for mousewheel
70
int32_t inputchecked = 0;
70
int32_t inputchecked = 0;
71
71
72
char quitevent=0, appactive=1, novideo=0;
72
char quitevent=0, appactive=1, novideo=0;
73
73
74
// video
74
// video
75
static SDL_Surface *sdl_surface/*=NULL*/;
75
static SDL_Surface *sdl_surface/*=NULL*/;
76
76
77
#if SDL_MAJOR_VERSION==2
77
#if SDL_MAJOR_VERSION==2
78
static SDL_Window *sdl_window=NULL;
78
static SDL_Window *sdl_window=NULL;
79
static SDL_GLContext sdl_context=NULL;
79
static SDL_GLContext sdl_context=NULL;
80
#endif
80
#endif
81
81
82
int32_t xres=-1, yres=-1, bpp=0, fullscreen=0, bytesperline;
82
int32_t xres=-1, yres=-1, bpp=0, fullscreen=0, bytesperline;
83
double refreshfreq = 59.0;
83
double refreshfreq = 59.0;
84
intptr_t frameplace=0;
84
intptr_t frameplace=0;
85
int32_t lockcount=0;
85
int32_t lockcount=0;
86
char modechange=1;
86
char modechange=1;
87
char offscreenrendering=0;
87
char offscreenrendering=0;
88
char videomodereset = 0;
88
char videomodereset = 0;
89
int32_t nofog=0;
89
int32_t nofog=0;
90
#ifndef EDUKE32_GLES
90
#ifndef EDUKE32_GLES
91
static uint16_t sysgamma[3][256];
91
static uint16_t sysgamma[3][256];
92
#endif
92
#endif
93
#ifdef USE_OPENGL
93
#ifdef USE_OPENGL
94
// OpenGL stuff
94
// OpenGL stuff
95
char nogl=0;
95
char nogl=0;
96
#endif
96
#endif
97
static int32_t vsync_renderlayer;
97
static int32_t vsync_renderlayer;
98
int32_t maxrefreshfreq=0;
98
int32_t maxrefreshfreq=0;
99
// last gamma, contrast, brightness
99
// last gamma, contrast, brightness
100
static float lastvidgcb[3];
100
static float lastvidgcb[3];
101
101
102
//#define KEY_PRINT_DEBUG
102
//#define KEY_PRINT_DEBUG
103
103
104
#include "sdlkeytrans.cpp"
104
#include "sdlkeytrans.cpp"
105
105
106
static SDL_Surface *appicon = NULL;
106
static SDL_Surface *appicon = NULL;
107
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
107
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
108
static SDL_Surface *loadappicon(void);
108
static SDL_Surface *loadappicon(void);
109
#endif
109
#endif
110
110
111
static mutex_t m_initprintf;
111
static mutex_t m_initprintf;
112
112
113
// Joystick dead and saturation zones
113
// Joystick dead and saturation zones
114
uint16_t joydead[9], joysatur[9];
114
uint16_t joydead[9], joysatur[9];
115
115
116
#ifdef _WIN32
116
#ifdef _WIN32
117
# if SDL_MAJOR_VERSION != 1
117
# if SDL_MAJOR_VERSION != 1
118
//
118
//
119
// win_gethwnd() -- gets the window handle
119
// win_gethwnd() -- gets the window handle
120
//
120
//
121
HWND win_gethwnd(void)
121
HWND win_gethwnd(void)
122
{
122
{
123
    struct SDL_SysWMinfo wmInfo;
123
    struct SDL_SysWMinfo wmInfo;
124
    SDL_VERSION(&wmInfo.version);
124
    SDL_VERSION(&wmInfo.version);
125
125
126
    if (SDL_GetWindowWMInfo(sdl_window, &wmInfo) != SDL_TRUE)
126
    if (SDL_GetWindowWMInfo(sdl_window, &wmInfo) != SDL_TRUE)
127
        return 0;
127
        return 0;
128
128
129
    if (wmInfo.subsystem == SDL_SYSWM_WINDOWS)
129
    if (wmInfo.subsystem == SDL_SYSWM_WINDOWS)
130
        return wmInfo.info.win.window;
130
        return wmInfo.info.win.window;
131
131
132
    initprintf("win_gethwnd: Unknown WM subsystem?!\n");
132
    initprintf("win_gethwnd: Unknown WM subsystem?!\n");
133
133
134
    return 0;
134
    return 0;
135
}
135
}
136
# endif
136
# endif
137
//
137
//
138
// win_gethinstance() -- gets the application instance
138
// win_gethinstance() -- gets the application instance
139
//
139
//
140
HINSTANCE win_gethinstance(void)
140
HINSTANCE win_gethinstance(void)
141
{
141
{
142
    return (HINSTANCE)GetModuleHandle(NULL);
142
    return (HINSTANCE)GetModuleHandle(NULL);
143
}
143
}
144
#endif
144
#endif
145
145
146
146
147
int32_t wm_msgbox(const char *name, const char *fmt, ...)
147
int32_t wm_msgbox(const char *name, const char *fmt, ...)
148
{
148
{
149
    char buf[2048];
149
    char buf[2048];
150
    va_list va;
150
    va_list va;
151
151
152
    UNREFERENCED_PARAMETER(name);
152
    UNREFERENCED_PARAMETER(name);
153
153
154
    va_start(va,fmt);
154
    va_start(va,fmt);
155
    vsnprintf(buf,sizeof(buf),fmt,va);
155
    Bvsnprintf(buf,sizeof(buf),fmt,va);
156
    va_end(va);
156
    va_end(va);
157
157
158
#if defined EDUKE32_OSX
158
#if defined EDUKE32_OSX
159
    return osx_msgbox(name, buf);
159
    return osx_msgbox(name, buf);
160
#elif defined _WIN32
160
#elif defined _WIN32
161
    MessageBox(win_gethwnd(),buf,name,MB_OK|MB_TASKMODAL);
161
    MessageBox(win_gethwnd(),buf,name,MB_OK|MB_TASKMODAL);
162
    return 0;
162
    return 0;
163
#elif defined EDUKE32_TOUCH_DEVICES
163
#elif defined EDUKE32_TOUCH_DEVICES
164
    initprintf("wm_msgbox called. Message: %s: %s",name,buf);
164
    initprintf("wm_msgbox called. Message: %s: %s",name,buf);
165
    return 0;
165
    return 0;
166
#elif defined GEKKO
166
#elif defined GEKKO
167
    puts(buf);
167
    puts(buf);
168
    return 0;
168
    return 0;
169
#else
169
#else
170
# if defined HAVE_GTK2
170
# if defined HAVE_GTK2
171
    if (gtkbuild_msgbox(name, buf) >= 0)
171
    if (gtkbuild_msgbox(name, buf) >= 0)
172
        return 0;
172
        return 0;
173
# endif
173
# endif
174
# if SDL_MAJOR_VERSION > 1
174
# if SDL_MAJOR_VERSION > 1
175
#  if !defined _WIN32
175
#  if !defined _WIN32
176
    // Replace all tab chars with spaces because the hand-rolled SDL message
176
    // Replace all tab chars with spaces because the hand-rolled SDL message
177
    // box diplays the former as N/L instead of whitespace.
177
    // box diplays the former as N/L instead of whitespace.
178
    for (size_t i=0; i<sizeof(buf); i++)
178
    for (size_t i=0; i<sizeof(buf); i++)
179
        if (buf[i] == '\t')
179
        if (buf[i] == '\t')
180
            buf[i] = ' ';
180
            buf[i] = ' ';
181
#  endif
181
#  endif
182
    return SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, name, buf, NULL);
182
    return SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, name, buf, NULL);
183
# else
183
# else
184
    puts(buf);
184
    puts(buf);
185
    puts("   (press Return or Enter to continue)");
185
    puts("   (press Return or Enter to continue)");
186
    getchar();
186
    getchar();
187
187
188
    return 0;
188
    return 0;
189
# endif
189
# endif
190
#endif
190
#endif
191
}
191
}
192
192
193
int32_t wm_ynbox(const char *name, const char *fmt, ...)
193
int32_t wm_ynbox(const char *name, const char *fmt, ...)
194
{
194
{
195
    char buf[2048];
195
    char buf[2048];
196
    va_list va;
196
    va_list va;
197
197
198
    UNREFERENCED_PARAMETER(name);
198
    UNREFERENCED_PARAMETER(name);
199
199
200
    va_start(va,fmt);
200
    va_start(va,fmt);
201
    vsnprintf(buf,sizeof(buf),fmt,va);
201
    Bvsnprintf(buf,sizeof(buf),fmt,va);
202
    va_end(va);
202
    va_end(va);
203
203
204
#if defined EDUKE32_OSX
204
#if defined EDUKE32_OSX
205
    return osx_ynbox(name, buf);
205
    return osx_ynbox(name, buf);
206
#elif defined _WIN32
206
#elif defined _WIN32
207
    return (MessageBox(win_gethwnd(),buf,name,MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL) == IDYES);
207
    return (MessageBox(win_gethwnd(),buf,name,MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL) == IDYES);
208
#elif defined EDUKE32_TOUCH_DEVICES
208
#elif defined EDUKE32_TOUCH_DEVICES
209
    initprintf("wm_ynbox called, this is bad! Message: %s: %s",name,buf);
209
    initprintf("wm_ynbox called, this is bad! Message: %s: %s",name,buf);
210
    initprintf("Returning false..");
210
    initprintf("Returning false..");
211
    return 0;
211
    return 0;
212
#elif defined GEKKO
212
#elif defined GEKKO
213
    puts(buf);
213
    puts(buf);
214
    puts("Assuming yes...");
214
    puts("Assuming yes...");
215
    return 1;
215
    return 1;
216
#else
216
#else
217
# if defined HAVE_GTK2
217
# if defined HAVE_GTK2
218
    int ret = gtkbuild_ynbox(name, buf);
218
    int ret = gtkbuild_ynbox(name, buf);
219
    if (ret >= 0)
219
    if (ret >= 0)
220
        return ret;
220
        return ret;
221
# endif
221
# endif
222
# if SDL_MAJOR_VERSION > 1
222
# if SDL_MAJOR_VERSION > 1
223
    int r = -1;
223
    int r = -1;
224
224
225
    const SDL_MessageBoxButtonData buttons[] = {
225
    const SDL_MessageBoxButtonData buttons[] = {
226
        {
226
        {
227
            SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
227
            SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
228
            0,
228
            0,
229
            "No"
229
            "No"
230
        },{
230
        },{
231
            SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
231
            SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
232
            1,
232
            1,
233
            "Yes"
233
            "Yes"
234
        },
234
        },
235
    };
235
    };
236
236
237
    SDL_MessageBoxData data = {
237
    SDL_MessageBoxData data = {
238
        SDL_MESSAGEBOX_INFORMATION,
238
        SDL_MESSAGEBOX_INFORMATION,
239
        NULL, /* no parent window */
239
        NULL, /* no parent window */
240
        name,
240
        name,
241
        buf,
241
        buf,
242
        2,
242
        2,
243
        buttons,
243
        buttons,
244
        NULL /* Default color scheme */
244
        NULL /* Default color scheme */
245
    };
245
    };
246
246
247
    SDL_ShowMessageBox(&data, &r);
247
    SDL_ShowMessageBox(&data, &r);
248
248
249
    return r;
249
    return r;
250
# else
250
# else
251
    char c;
251
    char c;
252
252
253
    puts(buf);
253
    puts(buf);
254
    puts("   (type 'Y' or 'N', and press Return or Enter to continue)");
254
    puts("   (type 'Y' or 'N', and press Return or Enter to continue)");
255
    do c = getchar(); while (c != 'Y' && c != 'y' && c != 'N' && c != 'n');
255
    do c = getchar(); while (c != 'Y' && c != 'y' && c != 'N' && c != 'n');
256
    return c == 'Y' || c == 'y';
256
    return c == 'Y' || c == 'y';
257
# endif
257
# endif
258
#endif
258
#endif
259
}
259
}
260
260
261
void wm_setapptitle(const char *name)
261
void wm_setapptitle(const char *name)
262
{
262
{
263
#ifndef EDUKE32_TOUCH_DEVICES
263
#ifndef EDUKE32_TOUCH_DEVICES
264
    if (name != apptitle)
264
    if (name != apptitle)
265
        Bstrncpyz(apptitle, name, sizeof(apptitle));
265
        Bstrncpyz(apptitle, name, sizeof(apptitle));
266
266
267
#if !defined(__APPLE__)
267
#if !defined(__APPLE__)
268
    if (!appicon)
268
    if (!appicon)
269
        appicon = loadappicon();
269
        appicon = loadappicon();
270
#endif
270
#endif
271
271
272
#if SDL_MAJOR_VERSION == 1
272
#if SDL_MAJOR_VERSION == 1
273
    SDL_WM_SetCaption(apptitle, NULL);
273
    SDL_WM_SetCaption(apptitle, NULL);
274
274
275
    if (appicon && sdl_surface)
275
    if (appicon && sdl_surface)
276
        SDL_WM_SetIcon(appicon, 0);
276
        SDL_WM_SetIcon(appicon, 0);
277
#else
277
#else
278
    if (sdl_window)
278
    if (sdl_window)
279
    {
279
    {
280
        SDL_SetWindowTitle(sdl_window, apptitle);
280
        SDL_SetWindowTitle(sdl_window, apptitle);
281
281
282
        if (appicon)
282
        if (appicon)
283
        {
283
        {
284
#if defined _WIN32
284
#if defined _WIN32
285
        if (!EDUKE32_SDL_LINKED_PREREQ(linked, 2, 0, 5))
285
        if (!EDUKE32_SDL_LINKED_PREREQ(linked, 2, 0, 5))
286
#endif
286
#endif
287
            SDL_SetWindowIcon(sdl_window, appicon);
287
            SDL_SetWindowIcon(sdl_window, appicon);
288
        }
288
        }
289
    }
289
    }
290
#endif
290
#endif
291
291
292
    startwin_settitle(apptitle);
292
    startwin_settitle(apptitle);
293
#else
293
#else
294
    UNREFERENCED_PARAMETER(name);
294
    UNREFERENCED_PARAMETER(name);
295
#endif
295
#endif
296
}
296
}
297
297
298
//
298
//
299
//
299
//
300
// ---------------------------------------
300
// ---------------------------------------
301
//
301
//
302
// System
302
// System
303
//
303
//
304
// ---------------------------------------
304
// ---------------------------------------
305
//
305
//
306
//
306
//
307
307
308
/* XXX: libexecinfo could be used on systems without gnu libc. */
308
/* XXX: libexecinfo could be used on systems without gnu libc. */
309
#if !defined _WIN32 && defined __GNUC__ && !defined __OpenBSD__ && !(defined __APPLE__ && defined __BIG_ENDIAN__) && !defined GEKKO && !defined EDUKE32_TOUCH_DEVICES && !defined __OPENDINGUX__
309
#if !defined _WIN32 && defined __GNUC__ && !defined __OpenBSD__ && !(defined __APPLE__ && defined __BIG_ENDIAN__) && !defined GEKKO && !defined EDUKE32_TOUCH_DEVICES && !defined __OPENDINGUX__
310
# define PRINTSTACKONSEGV 1
310
# define PRINTSTACKONSEGV 1
311
# include <execinfo.h>
311
# include <execinfo.h>
312
#endif
312
#endif
313
313
314
static inline char grabmouse_low(char a);
314
static inline char grabmouse_low(char a);
315
315
316
#ifndef __ANDROID__
316
#ifndef __ANDROID__
317
static void attach_debugger_here(void)
317
static void attach_debugger_here(void)
318
{
318
{
319
#ifdef DEBUGGINGAIDS
319
#ifdef DEBUGGINGAIDS
320
    debug_break();
320
    debug_break();
321
#endif
321
#endif
322
}
322
}
323
323
324
static void sighandler(int signum)
324
static void sighandler(int signum)
325
{
325
{
326
    UNREFERENCED_PARAMETER(signum);
326
    UNREFERENCED_PARAMETER(signum);
327
    //    if (signum==SIGSEGV)
327
    //    if (signum==SIGSEGV)
328
    {
328
    {
329
        grabmouse_low(0);
329
        grabmouse_low(0);
330
#if PRINTSTACKONSEGV
330
#if PRINTSTACKONSEGV
331
        {
331
        {
332
            void *addr[32];
332
            void *addr[32];
333
            int32_t errfd = fileno(stderr);
333
            int32_t errfd = fileno(stderr);
334
            int32_t n=backtrace(addr, ARRAY_SIZE(addr));
334
            int32_t n=backtrace(addr, ARRAY_SIZE(addr));
335
            backtrace_symbols_fd(addr, n, errfd);
335
            backtrace_symbols_fd(addr, n, errfd);
336
        }
336
        }
337
        // This is useful for attaching the debugger post-mortem. For those pesky
337
        // This is useful for attaching the debugger post-mortem. For those pesky
338
        // cases where the program runs through happily when inspected from the start.
338
        // cases where the program runs through happily when inspected from the start.
339
        //        usleep(15000000);
339
        //        usleep(15000000);
340
#endif
340
#endif
341
        attach_debugger_here();
341
        attach_debugger_here();
342
        app_crashhandler();
342
        app_crashhandler();
343
        Bexit(EXIT_FAILURE);
343
        Bexit(EXIT_FAILURE);
344
    }
344
    }
345
}
345
}
346
#endif
346
#endif
347
347
348
#ifdef __ANDROID__
348
#ifdef __ANDROID__
349
int mobile_halted = 0;
349
int mobile_halted = 0;
350
#ifdef __cplusplus
350
#ifdef __cplusplus
351
extern "C"
351
extern "C"
352
{
352
{
353
#endif
353
#endif
354
void G_Shutdown(void);
354
void G_Shutdown(void);
355
#ifdef __cplusplus
355
#ifdef __cplusplus
356
}
356
}
357
#endif
357
#endif
358
358
359
int sdlayer_mobilefilter(void *userdata, SDL_Event *event)
359
int sdlayer_mobilefilter(void *userdata, SDL_Event *event)
360
{
360
{
361
    switch (event->type)
361
    switch (event->type)
362
    {
362
    {
363
        case SDL_APP_TERMINATING:
363
        case SDL_APP_TERMINATING:
364
            // yes, this calls into the game, ugh
364
            // yes, this calls into the game, ugh
365
            if (mobile_halted == 1)
365
            if (mobile_halted == 1)
366
                G_Shutdown();
366
                G_Shutdown();
367
367
368
            mobile_halted = 1;
368
            mobile_halted = 1;
369
            return 0;
369
            return 0;
370
        case SDL_APP_LOWMEMORY:
370
        case SDL_APP_LOWMEMORY:
371
            gltexinvalidatetype(INVALIDATE_ALL);
371
            gltexinvalidatetype(INVALIDATE_ALL);
372
            return 0;
372
            return 0;
373
        case SDL_APP_WILLENTERBACKGROUND:
373
        case SDL_APP_WILLENTERBACKGROUND:
374
            mobile_halted = 1;
374
            mobile_halted = 1;
375
            return 0;
375
            return 0;
376
        case SDL_APP_DIDENTERBACKGROUND:
376
        case SDL_APP_DIDENTERBACKGROUND:
377
            gltexinvalidatetype(INVALIDATE_ALL);
377
            gltexinvalidatetype(INVALIDATE_ALL);
378
            // tear down video?
378
            // tear down video?
379
            return 0;
379
            return 0;
380
        case SDL_APP_WILLENTERFOREGROUND:
380
        case SDL_APP_WILLENTERFOREGROUND:
381
            // restore video?
381
            // restore video?
382
            return 0;
382
            return 0;
383
        case SDL_APP_DIDENTERFOREGROUND:
383
        case SDL_APP_DIDENTERFOREGROUND:
384
            mobile_halted = 0;
384
            mobile_halted = 0;
385
            return 0;
385
            return 0;
386
        default:
386
        default:
387
            return 1;//!halt;
387
            return 1;//!halt;
388
    }
388
    }
389
389
390
    UNREFERENCED_PARAMETER(userdata);
390
    UNREFERENCED_PARAMETER(userdata);
391
}
391
}
392
392
393
# include <setjmp.h>
393
# include <setjmp.h>
394
static jmp_buf eduke32_exit_jmp_buf;
394
static jmp_buf eduke32_exit_jmp_buf;
395
static int eduke32_return_value;
395
static int eduke32_return_value;
396
396
397
void eduke32_exit_return(int retval)
397
void eduke32_exit_return(int retval)
398
{
398
{
399
    eduke32_return_value = retval;
399
    eduke32_return_value = retval;
400
    longjmp(eduke32_exit_jmp_buf, 1);
400
    longjmp(eduke32_exit_jmp_buf, 1);
401
    EDUKE32_UNREACHABLE_SECTION(return);
401
    EDUKE32_UNREACHABLE_SECTION(return);
402
}
402
}
403
#endif
403
#endif
404
404
405
void sdlayer_sethints()
405
void sdlayer_sethints()
406
{
406
{
407
#if defined _WIN32
407
#if defined _WIN32
408
    // Thread naming interferes with debugging using MinGW-w64's GDB.
408
    // Thread naming interferes with debugging using MinGW-w64's GDB.
409
#if defined SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING
409
#if defined SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING
410
    SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
410
    SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
411
#endif
411
#endif
412
#if defined SDL_HINT_XINPUT_ENABLED
412
#if defined SDL_HINT_XINPUT_ENABLED
413
    if (!Bgetenv("EDUKE32_NO_XINPUT"))
413
    if (!Bgetenv("EDUKE32_NO_XINPUT"))
414
        SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "0");
414
        SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "0");
415
#endif
415
#endif
416
#endif
416
#endif
417
417
418
#if defined SDL_HINT_NO_SIGNAL_HANDLERS
418
#if defined SDL_HINT_NO_SIGNAL_HANDLERS
419
    SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
419
    SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
420
#endif
420
#endif
421
#if defined SDL_HINT_VIDEO_HIGHDPI_DISABLED
421
#if defined SDL_HINT_VIDEO_HIGHDPI_DISABLED
422
    SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
422
    SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
423
#endif
423
#endif
424
#if defined SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
424
#if defined SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
425
    SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "0");
425
    SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "0");
426
#endif
426
#endif
427
#if defined SDL_HINT_AUDIO_RESAMPLING_MODE
427
#if defined SDL_HINT_AUDIO_RESAMPLING_MODE
428
    SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "3");
428
    SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "3");
429
#endif
429
#endif
430
}
430
}
431
431
432
#ifdef _WIN32
432
#ifdef _WIN32
433
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
433
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
434
#elif defined __ANDROID__
434
#elif defined __ANDROID__
435
# ifdef __cplusplus
435
# ifdef __cplusplus
436
extern "C" int eduke32_android_main(int argc, char const *argv[]);
436
extern "C" int eduke32_android_main(int argc, char const *argv[]);
437
# endif
437
# endif
438
int eduke32_android_main(int argc, char const *argv[])
438
int eduke32_android_main(int argc, char const *argv[])
439
#elif defined GEKKO
439
#elif defined GEKKO
440
int SDL_main(int argc, char *argv[])
440
int SDL_main(int argc, char *argv[])
441
#else
441
#else
442
int main(int argc, char *argv[])
442
int main(int argc, char *argv[])
443
#endif
443
#endif
444
{
444
{
445
#ifdef __ANDROID__
445
#ifdef __ANDROID__
446
    if (setjmp(eduke32_exit_jmp_buf))
446
    if (setjmp(eduke32_exit_jmp_buf))
447
    {
447
    {
448
        return eduke32_return_value;
448
        return eduke32_return_value;
449
    }
449
    }
450
#endif
450
#endif
451
451
452
    sdlayer_sethints();
452
    sdlayer_sethints();
453
453
454
#ifdef USE_OPENGL
454
#ifdef USE_OPENGL
455
    char *argp;
455
    char *argp;
456
456
457
    if ((argp = Bgetenv("EDUKE32_NO_OPENGL_FOG")) != NULL)
457
    if ((argp = Bgetenv("EDUKE32_NO_OPENGL_FOG")) != NULL)
458
        nofog = Batol(argp);
458
        nofog = Batol(argp);
459
459
460
#if defined __linux__ || defined EDUKE32_BSD
460
#if defined __linux__ || defined EDUKE32_BSD
461
    if (!Bgetenv("EDUKE32_NO_GL_THREADED_OPTIMIZATIONS"))
461
    if (!Bgetenv("EDUKE32_NO_GL_THREADED_OPTIMIZATIONS"))
462
    {
462
    {
463
        if (!Bgetenv("EDUKE32_NO_NVIDIA_THREADED_OPTIMIZATIONS"))
463
        if (!Bgetenv("EDUKE32_NO_NVIDIA_THREADED_OPTIMIZATIONS"))
464
            setenv("__GL_THREADED_OPTIMIZATIONS", "1", 0);
464
            setenv("__GL_THREADED_OPTIMIZATIONS", "1", 0);
465
465
466
        if (!Bgetenv("EDUKE32_NO_MESA_THREADED_OPTIMIZATIONS"))
466
        if (!Bgetenv("EDUKE32_NO_MESA_THREADED_OPTIMIZATIONS"))
467
            setenv("mesa_glthread", "true", 0);
467
            setenv("mesa_glthread", "true", 0);
468
    }
468
    }
469
#endif
469
#endif
470
#endif
470
#endif
471
471
472
    buildkeytranslationtable();
472
    buildkeytranslationtable();
473
473
474
#ifndef __ANDROID__
474
#ifndef __ANDROID__
475
    signal(SIGSEGV, sighandler);
475
    signal(SIGSEGV, sighandler);
476
    signal(SIGILL, sighandler);  /* clang -fcatch-undefined-behavior uses an ill. insn */
476
    signal(SIGILL, sighandler);  /* clang -fcatch-undefined-behavior uses an ill. insn */
477
    signal(SIGABRT, sighandler);
477
    signal(SIGABRT, sighandler);
478
    signal(SIGFPE, sighandler);
478
    signal(SIGFPE, sighandler);
479
#else
479
#else
480
    SDL_SetEventFilter(sdlayer_mobilefilter, NULL);
480
    SDL_SetEventFilter(sdlayer_mobilefilter, NULL);
481
#endif
481
#endif
482
482
483
#ifdef _WIN32
483
#ifdef _WIN32
484
    UNREFERENCED_PARAMETER(hInst);
484
    UNREFERENCED_PARAMETER(hInst);
485
    UNREFERENCED_PARAMETER(hPrevInst);
485
    UNREFERENCED_PARAMETER(hPrevInst);
486
    UNREFERENCED_PARAMETER(lpCmdLine);
486
    UNREFERENCED_PARAMETER(lpCmdLine);
487
    UNREFERENCED_PARAMETER(nCmdShow);
487
    UNREFERENCED_PARAMETER(nCmdShow);
488
488
489
    if (windowsPreInit())
489
    if (windowsPreInit())
490
        return -1;
490
        return -1;
491
491
492
#elif defined(GEKKO)
492
#elif defined(GEKKO)
493
    wii_open();
493
    wii_open();
494
#elif defined(HAVE_GTK2)
494
#elif defined(HAVE_GTK2)
495
    // Pre-initialize SDL video system in order to make sure XInitThreads() is called
495
    // Pre-initialize SDL video system in order to make sure XInitThreads() is called
496
    // before GTK starts talking to X11.
496
    // before GTK starts talking to X11.
497
    if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO)
497
    if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO)
498
        SDL_InitSubSystem(SDL_INIT_VIDEO);
498
        SDL_InitSubSystem(SDL_INIT_VIDEO);
499
499
500
    gtkbuild_init(&argc, &argv);
500
    gtkbuild_init(&argc, &argv);
501
#endif
501
#endif
502
502
503
#ifdef EDUKE32_OSX
503
#ifdef EDUKE32_OSX
504
    osx_preopen();
504
    osx_preopen();
505
#endif
505
#endif
506
    startwin_open();
506
    startwin_open();
507
#ifdef EDUKE32_OSX
507
#ifdef EDUKE32_OSX
508
    osx_postopen();
508
    osx_postopen();
509
#endif
509
#endif
510
    maybe_redirect_outputs();
510
    maybe_redirect_outputs();
511
511
512
#ifdef _WIN32
512
#ifdef _WIN32
513
    char *argvbuf;
513
    char *argvbuf;
514
    int buildargc = windowsGetCommandLine(&argvbuf);
514
    int buildargc = windowsGetCommandLine(&argvbuf);
515
    const char **buildargv = (const char **) Xmalloc(sizeof(char *)*(buildargc+1));
515
    const char **buildargv = (const char **) Xmalloc(sizeof(char *)*(buildargc+1));
516
    char *wp = argvbuf;
516
    char *wp = argvbuf;
517
517
518
    for (bssize_t i=0; i<buildargc; i++, wp++)
518
    for (bssize_t i=0; i<buildargc; i++, wp++)
519
    {
519
    {
520
        buildargv[i] = wp;
520
        buildargv[i] = wp;
521
        while (*wp) wp++;
521
        while (*wp) wp++;
522
    }
522
    }
523
    buildargv[buildargc] = NULL;
523
    buildargv[buildargc] = NULL;
524
524
525
#ifdef USE_PHYSFS
525
#ifdef USE_PHYSFS
526
    PHYSFS_init(buildargv[0]);
526
    PHYSFS_init(buildargv[0]);
527
    PHYSFS_setWriteDir(PHYSFS_getBaseDir());
527
    PHYSFS_setWriteDir(PHYSFS_getBaseDir());
528
#endif
528
#endif
529
    int const r = app_main(buildargc, (const char **)buildargv);
529
    int const r = app_main(buildargc, (const char **)buildargv);
530
#else
530
#else
531
#ifdef USE_PHYSFS
531
#ifdef USE_PHYSFS
532
    int pfsi = PHYSFS_init(argv[0]);
532
    int pfsi = PHYSFS_init(argv[0]);
533
    assert(pfsi != 0);
533
    assert(pfsi != 0);
534
    PHYSFS_setWriteDir(PHYSFS_getUserDir());
534
    PHYSFS_setWriteDir(PHYSFS_getUserDir());
535
#endif
535
#endif
536
    int const r = app_main(argc, (char const * const *)argv);
536
    int const r = app_main(argc, (char const * const *)argv);
537
#endif
537
#endif
538
538
539
    startwin_close();
539
    startwin_close();
540
540
541
#if defined(HAVE_GTK2)
541
#if defined(HAVE_GTK2)
542
    gtkbuild_exit(r);
542
    gtkbuild_exit(r);
543
#endif
543
#endif
544
544
545
    return r;
545
    return r;
546
}
546
}
547
547
548
548
549
#if SDL_MAJOR_VERSION != 1
549
#if SDL_MAJOR_VERSION != 1
550
static int sdlayer_getswapinterval(int const syncMode)
550
static int sdlayer_getswapinterval(int const syncMode)
551
{
551
{
552
    static int intervals[] = { -1, 0, 1, 0};
552
    static int intervals[] = { -1, 0, 1, 0};
553
    Bassert((unsigned)(syncMode + 1) < ARRAY_SIZE(intervals));
553
    Bassert((unsigned)(syncMode + 1) < ARRAY_SIZE(intervals));
554
    return intervals[syncMode + 1];
554
    return intervals[syncMode + 1];
555
}
555
}
556
556
557
static int sdlayer_checkvsync(int checkSync)
557
static int sdlayer_checkvsync(int checkSync)
558
{
558
{
559
    int const actualSync = SDL_GL_GetSwapInterval();
559
    int const actualSync = SDL_GL_GetSwapInterval();
560
    if (actualSync != sdlayer_getswapinterval(checkSync))
560
    if (actualSync != sdlayer_getswapinterval(checkSync))
561
    {
561
    {
562
        OSD_Printf("debug: GL driver forcing SwapInterval %d!\n", actualSync);
562
        OSD_Printf("debug: GL driver forcing SwapInterval %d!\n", actualSync);
563
        checkSync = actualSync;
563
        checkSync = actualSync;
564
    }
564
    }
565
    return checkSync;
565
    return checkSync;
566
}
566
}
567
567
568
int32_t videoSetVsync(int32_t newSync)
568
int32_t videoSetVsync(int32_t newSync)
569
{
569
{
570
    if (vsync_renderlayer == newSync)
570
    if (vsync_renderlayer == newSync)
571
        return newSync;
571
        return newSync;
572
572
573
#ifdef USE_OPENGL
573
#ifdef USE_OPENGL
574
    if (sdl_context)
574
    if (sdl_context)
575
    {
575
    {
576
        int result = SDL_GL_SetSwapInterval(sdlayer_getswapinterval(newSync));
576
        int result = SDL_GL_SetSwapInterval(sdlayer_getswapinterval(newSync));
577
577
578
        if (result == -1)
578
        if (result == -1)
579
        {
579
        {
580
            if (newSync == -1)
580
            if (newSync == -1)
581
            {
581
            {
582
                OSD_Printf("debug: GL driver rejected SwapInterval %d!\n", sdlayer_getswapinterval(newSync));
582
                OSD_Printf("debug: GL driver rejected SwapInterval %d!\n", sdlayer_getswapinterval(newSync));
583
583
584
                newSync = 1;
584
                newSync = 1;
585
                result  = SDL_GL_SetSwapInterval(sdlayer_getswapinterval(newSync));
585
                result  = SDL_GL_SetSwapInterval(sdlayer_getswapinterval(newSync));
586
            }
586
            }
587
587
588
            if (result == -1)
588
            if (result == -1)
589
            {
589
            {
590
                OSD_Printf("debug: GL driver rejected SwapInterval %d!\n", sdlayer_getswapinterval(newSync));
590
                OSD_Printf("debug: GL driver rejected SwapInterval %d!\n", sdlayer_getswapinterval(newSync));
591
                newSync = 0;
591
                newSync = 0;
592
            }
592
            }
593
        }
593
        }
594
594
595
        vsync_renderlayer = sdlayer_checkvsync(newSync);
595
        vsync_renderlayer = sdlayer_checkvsync(newSync);
596
    }
596
    }
597
    else
597
    else
598
#endif
598
#endif
599
    {
599
    {
600
        vsync_renderlayer = newSync;
600
        vsync_renderlayer = newSync;
601
601
602
        videoResetMode();
602
        videoResetMode();
603
603
604
        if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
604
        if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
605
            OSD_Printf("restartvid: Reset failed...\n");
605
            OSD_Printf("restartvid: Reset failed...\n");
606
    }
606
    }
607
607
608
    return newSync;
608
    return newSync;
609
}
609
}
610
#endif
610
#endif
611
611
612
int32_t sdlayer_checkversion(void);
612
int32_t sdlayer_checkversion(void);
613
#if SDL_MAJOR_VERSION != 1
613
#if SDL_MAJOR_VERSION != 1
614
int32_t sdlayer_checkversion(void)
614
int32_t sdlayer_checkversion(void)
615
{
615
{
616
    SDL_version compiled;
616
    SDL_version compiled;
617
617
618
    SDL_GetVersion(&linked);
618
    SDL_GetVersion(&linked);
619
    SDL_VERSION(&compiled);
619
    SDL_VERSION(&compiled);
620
620
621
    if (!Bmemcmp(&compiled, &linked, sizeof(SDL_version)))
621
    if (!Bmemcmp(&compiled, &linked, sizeof(SDL_version)))
622
        initprintf("Initializing SDL %d.%d.%d\n",
622
        initprintf("Initializing SDL %d.%d.%d\n",
623
            compiled.major, compiled.minor, compiled.patch);
623
            compiled.major, compiled.minor, compiled.patch);
624
    else
624
    else
625
    initprintf("Initializing SDL %d.%d.%d"
625
    initprintf("Initializing SDL %d.%d.%d"
626
               " (built against SDL version %d.%d.%d)\n",
626
               " (built against SDL version %d.%d.%d)\n",
627
               linked.major, linked.minor, linked.patch, compiled.major, compiled.minor, compiled.patch);
627
               linked.major, linked.minor, linked.patch, compiled.major, compiled.minor, compiled.patch);
628
628
629
    if (SDL_VERSIONNUM(linked.major, linked.minor, linked.patch) < SDL2_REQUIREDVERSION)
629
    if (SDL_VERSIONNUM(linked.major, linked.minor, linked.patch) < SDL2_REQUIREDVERSION)
630
    {
630
    {
631
        /*reject running under SDL versions older than what is stated in sdl_inc.h */
631
        /*reject running under SDL versions older than what is stated in sdl_inc.h */
632
        initprintf("You need at least v%d.%d.%d of SDL to run this game\n",SDL2_MIN_X,SDL2_MIN_Y,SDL2_MIN_Z);
632
        initprintf("You need at least v%d.%d.%d of SDL to run this game\n",SDL2_MIN_X,SDL2_MIN_Y,SDL2_MIN_Z);
633
        return -1;
633
        return -1;
634
    }
634
    }
635
635
636
    return 0;
636
    return 0;
637
}
637
}
638
638
639
//
639
//
640
// initsystem() -- init SDL systems
640
// initsystem() -- init SDL systems
641
//
641
//
642
int32_t initsystem(void)
642
int32_t initsystem(void)
643
{
643
{
644
    mutex_init(&m_initprintf);
644
    mutex_init(&m_initprintf);
645
645
646
#ifdef _WIN32
646
#ifdef _WIN32
647
    windowsPlatformInit();
647
    windowsPlatformInit();
648
#endif
648
#endif
649
    sysReadCPUID();
649
    sysReadCPUID();
650
650
651
    if (sdlayer_checkversion())
651
    if (sdlayer_checkversion())
652
        return -1;
652
        return -1;
653
653
654
    int32_t err = 0;
654
    int32_t err = 0;
655
655
656
    if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO)
656
    if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO)
657
        err = SDL_InitSubSystem(SDL_INIT_VIDEO);
657
        err = SDL_InitSubSystem(SDL_INIT_VIDEO);
658
658
659
    if (err)
659
    if (err)
660
    {
660
    {
661
        initprintf("SDL initialization failed! (%s)\nNon-interactive mode enabled.  This is probably not what you want.\n", SDL_GetError());
661
        initprintf("SDL initialization failed! (%s)\nNon-interactive mode enabled.  This is probably not what you want.\n", SDL_GetError());
662
        novideo = 1;
662
        novideo = 1;
663
#ifdef USE_OPENGL
663
#ifdef USE_OPENGL
664
        nogl = 1;
664
        nogl = 1;
665
#endif
665
#endif
666
    }
666
    }
667
667
668
#if SDL_MAJOR_VERSION > 1
668
#if SDL_MAJOR_VERSION > 1
669
    SDL_StopTextInput();
669
    SDL_StopTextInput();
670
    SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
670
    SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
671
#endif
671
#endif
672
672
673
    atexit(uninitsystem);
673
    atexit(uninitsystem);
674
674
675
    timerInit(CLOCKTICKSPERSECOND);
675
    timerInit(CLOCKTICKSPERSECOND);
676
676
677
    frameplace = 0;
677
    frameplace = 0;
678
    lockcount = 0;
678
    lockcount = 0;
679
679
680
    if (!novideo)
680
    if (!novideo)
681
    {
681
    {
682
#ifdef USE_OPENGL
682
#ifdef USE_OPENGL
683
        if (SDL_GL_LoadLibrary(0))
683
        if (SDL_GL_LoadLibrary(0))
684
        {
684
        {
685
            initprintf("Failed loading OpenGL Driver.  GL modes will be unavailable. Error: %s\n", SDL_GetError());
685
            initprintf("Failed loading OpenGL Driver.  GL modes will be unavailable. Error: %s\n", SDL_GetError());
686
            nogl = 1;
686
            nogl = 1;
687
        }
687
        }
688
#ifdef POLYMER
688
#ifdef POLYMER
689
        if (loadglulibrary(getenv("BUILD_GLULIB")))
689
        if (loadglulibrary(getenv("BUILD_GLULIB")))
690
        {
690
        {
691
            initprintf("Failed loading GLU.  GL modes will be unavailable.\n");
691
            initprintf("Failed loading GLU.  GL modes will be unavailable.\n");
692
            nogl = 1;
692
            nogl = 1;
693
        }
693
        }
694
#endif
694
#endif
695
#endif
695
#endif
696
696
697
#ifndef _WIN32
697
#ifndef _WIN32
698
        const char *drvname = SDL_GetVideoDriver(0);
698
        const char *drvname = SDL_GetVideoDriver(0);
699
699
700
        if (drvname)
700
        if (drvname)
701
            initprintf("Using \"%s\" video driver\n", drvname);
701
            initprintf("Using \"%s\" video driver\n", drvname);
702
#endif
702
#endif
703
        wm_setapptitle(apptitle);
703
        wm_setapptitle(apptitle);
704
    }
704
    }
705
705
706
    return 0;
706
    return 0;
707
}
707
}
708
#endif
708
#endif
709
709
710
710
711
//
711
//
712
// uninitsystem() -- uninit SDL systems
712
// uninitsystem() -- uninit SDL systems
713
//
713
//
714
void uninitsystem(void)
714
void uninitsystem(void)
715
{
715
{
716
    uninitinput();
716
    uninitinput();
717
    timerUninit();
717
    timerUninit();
718
718
719
    if (appicon)
719
    if (appicon)
720
    {
720
    {
721
        SDL_FreeSurface(appicon);
721
        SDL_FreeSurface(appicon);
722
        appicon = NULL;
722
        appicon = NULL;
723
    }
723
    }
724
724
725
#ifdef _WIN32
725
#ifdef _WIN32
726
    windowsPlatformCleanup();
726
    windowsPlatformCleanup();
727
#endif
727
#endif
728
728
729
    SDL_Quit();
729
    SDL_Quit();
730
730
731
#ifdef USE_OPENGL
731
#ifdef USE_OPENGL
732
# if SDL_MAJOR_VERSION!=1
732
# if SDL_MAJOR_VERSION!=1
733
    SDL_GL_UnloadLibrary();
733
    SDL_GL_UnloadLibrary();
734
# endif
734
# endif
735
# ifdef POLYMER
735
# ifdef POLYMER
736
    unloadglulibrary();
736
    unloadglulibrary();
737
# endif
737
# endif
738
#endif
738
#endif
739
}
739
}
740
740
741
741
742
//
742
//
743
// system_getcvars() -- propagate any cvars that are read post-initialization
743
// system_getcvars() -- propagate any cvars that are read post-initialization
744
//
744
//
745
void system_getcvars(void)
745
void system_getcvars(void)
746
{
746
{
747
# ifdef _WIN32
747
# ifdef _WIN32
748
    windowsDwmSetupComposition(false);
748
    windowsDwmSetupComposition(false);
749
# endif
749
# endif
750
750
751
    vsync = videoSetVsync(vsync);
751
    vsync = videoSetVsync(vsync);
752
}
752
}
753
753
754
//
754
//
755
// initprintf() -- prints a formatted string to the initialization window
755
// initprintf() -- prints a formatted string to the initialization window
756
//
756
//
757
void initprintf(const char *f, ...)
757
void initprintf(const char *f, ...)
758
{
758
{
759
    va_list va;
759
    va_list va;
760
    char buf[2048];
760
    char buf[2048];
761
761
762
    va_start(va, f);
762
    va_start(va, f);
763
    Bvsnprintf(buf, sizeof(buf), f, va);
763
    Bvsnprintf(buf, sizeof(buf), f, va);
764
    va_end(va);
764
    va_end(va);
765
765
766
    osdstrings.append(Xstrdup(buf));
766
    osdstrings.append(Xstrdup(buf));
767
    initputs(buf);
767
    initputs(buf);
768
}
768
}
769
769
770
770
771
//
771
//
772
// initputs() -- prints a string to the initialization window
772
// initputs() -- prints a string to the initialization window
773
//
773
//
774
void initputs(const char *buf)
774
void initputs(const char *buf)
775
{
775
{
776
    static char dabuf[2048];
776
    static char dabuf[2048];
777
777
778
#ifdef __ANDROID__
778
#ifdef __ANDROID__
779
    __android_log_print(ANDROID_LOG_INFO,"DUKE", "%s",buf);
779
    __android_log_print(ANDROID_LOG_INFO,"DUKE", "%s",buf);
780
#endif
780
#endif
781
    OSD_Puts(buf);
781
    OSD_Puts(buf);
782
//    Bprintf("%s", buf);
782
//    Bprintf("%s", buf);
783
783
784
    mutex_lock(&m_initprintf);
784
    mutex_lock(&m_initprintf);
785
    if (Bstrlen(dabuf) + Bstrlen(buf) > 1022)
785
    if (Bstrlen(dabuf) + Bstrlen(buf) > 1022)
786
    {
786
    {
787
        startwin_puts(dabuf);
787
        startwin_puts(dabuf);
788
        Bmemset(dabuf, 0, sizeof(dabuf));
788
        Bmemset(dabuf, 0, sizeof(dabuf));
789
    }
789
    }
790
790
791
    Bstrcat(dabuf,buf);
791
    Bstrcat(dabuf,buf);
792
792
793
    if (g_logFlushWindow || Bstrlen(dabuf) > 768)
793
    if (g_logFlushWindow || Bstrlen(dabuf) > 768)
794
    {
794
    {
795
        startwin_puts(dabuf);
795
        startwin_puts(dabuf);
796
#ifndef _WIN32
796
#ifndef _WIN32
797
        startwin_idle(NULL);
797
        startwin_idle(NULL);
798
#else
798
#else
799
        if (sdl_window)
799
        if (sdl_window)
800
            handleevents();
800
            handleevents();
801
#endif
801
#endif
802
        Bmemset(dabuf, 0, sizeof(dabuf));
802
        Bmemset(dabuf, 0, sizeof(dabuf));
803
    }
803
    }
804
    mutex_unlock(&m_initprintf);
804
    mutex_unlock(&m_initprintf);
805
}
805
}
806
806
807
//
807
//
808
// debugprintf() -- prints a formatted debug string to stderr
808
// debugprintf() -- prints a formatted debug string to stderr
809
//
809
//
810
void debugprintf(const char *f, ...)
810
void debugprintf(const char *f, ...)
811
{
811
{
812
#if defined DEBUGGINGAIDS && !(defined __APPLE__ && defined __BIG_ENDIAN__)
812
#if defined DEBUGGINGAIDS && !(defined __APPLE__ && defined __BIG_ENDIAN__)
813
    va_list va;
813
    va_list va;
814
814
815
    va_start(va,f);
815
    va_start(va,f);
816
    Bvfprintf(stderr, f, va);
816
    Bvfprintf(stderr, f, va);
817
    va_end(va);
817
    va_end(va);
818
#else
818
#else
819
    UNREFERENCED_PARAMETER(f);
819
    UNREFERENCED_PARAMETER(f);
820
#endif
820
#endif
821
}
821
}
822
822
823
823
824
//
824
//
825
//
825
//
826
// ---------------------------------------
826
// ---------------------------------------
827
//
827
//
828
// All things Input
828
// All things Input
829
//
829
//
830
// ---------------------------------------
830
// ---------------------------------------
831
//
831
//
832
//
832
//
833
833
834
// static int32_t joyblast=0;
834
// static int32_t joyblast=0;
835
static SDL_Joystick *joydev = NULL;
835
static SDL_Joystick *joydev = NULL;
836
#if SDL_MAJOR_VERSION >= 2
836
#if SDL_MAJOR_VERSION >= 2
837
static SDL_GameController *controller = NULL;
837
static SDL_GameController *controller = NULL;
838
838
839
static void LoadSDLControllerDB()
839
static void LoadSDLControllerDB()
840
{
840
{
841
    buildvfs_kfd fh = kopen4load("gamecontrollerdb.txt", 0);
841
    buildvfs_kfd fh = kopen4load("gamecontrollerdb.txt", 0);
842
    if (fh == buildvfs_kfd_invalid)
842
    if (fh == buildvfs_kfd_invalid)
843
        return;
843
        return;
844
844
845
    int const flen = kfilelength(fh);
845
    int const flen = kfilelength(fh);
846
    if (flen <= 0)
846
    if (flen <= 0)
847
    {
847
    {
848
        kclose(fh);
848
        kclose(fh);
849
        return;
849
        return;
850
    }
850
    }
851
851
852
    char * dbuf = (char *)Xaligned_alloc(16, flen + 1);
852
    char * dbuf = (char *)Xaligned_alloc(16, flen + 1);
853
    if (!dbuf)
853
    if (!dbuf)
854
    {
854
    {
855
        kclose(fh);
855
        kclose(fh);
856
        return;
856
        return;
857
    }
857
    }
858
858
859
    if (kread_and_test(fh, dbuf, flen))
859
    if (kread_and_test(fh, dbuf, flen))
860
    {
860
    {
861
        Xaligned_free(dbuf);
861
        Xaligned_free(dbuf);
862
        kclose(fh);
862
        kclose(fh);
863
        return;
863
        return;
864
    }
864
    }
865
865
866
    dbuf[flen] = '\0';
866
    dbuf[flen] = '\0';
867
    kclose(fh);
867
    kclose(fh);
868
868
869
    SDL_RWops * rwops = SDL_RWFromConstMem(dbuf, flen);
869
    SDL_RWops * rwops = SDL_RWFromConstMem(dbuf, flen);
870
    if (!rwops)
870
    if (!rwops)
871
    {
871
    {
872
        Xaligned_free(dbuf);
872
        Xaligned_free(dbuf);
873
        return;
873
        return;
874
    }
874
    }
875
875
876
    int i = SDL_GameControllerAddMappingsFromRW(rwops, 1);
876
    int i = SDL_GameControllerAddMappingsFromRW(rwops, 1);
877
877
878
    if (i == -1)
878
    if (i == -1)
879
        buildprintf("Failed loading game controller database: %s\n", SDL_GetError());
879
        buildprintf("Failed loading game controller database: %s\n", SDL_GetError());
880
    else
880
    else
881
        buildputs("Loaded game controller database\n");
881
        buildputs("Loaded game controller database\n");
882
882
883
    Xaligned_free(dbuf);
883
    Xaligned_free(dbuf);
884
}
884
}
885
#endif
885
#endif
886
886
887
void joyScanDevices()
887
void joyScanDevices()
888
{
888
{
889
    inputdevices &= ~4;
889
    inputdevices &= ~4;
890
890
891
#if SDL_MAJOR_VERSION >= 2
891
#if SDL_MAJOR_VERSION >= 2
892
    if (controller)
892
    if (controller)
893
    {
893
    {
894
        SDL_GameControllerClose(controller);
894
        SDL_GameControllerClose(controller);
895
        controller = nullptr;
895
        controller = nullptr;
896
    }
896
    }
897
#endif
897
#endif
898
    if (joydev)
898
    if (joydev)
899
    {
899
    {
900
        SDL_JoystickClose(joydev);
900
        SDL_JoystickClose(joydev);
901
        joydev = nullptr;
901
        joydev = nullptr;
902
    }
902
    }
903
903
904
    int numjoysticks = SDL_NumJoysticks();
904
    int numjoysticks = SDL_NumJoysticks();
905
    if (numjoysticks < 1)
905
    if (numjoysticks < 1)
906
    {
906
    {
907
        buildputs("No game controllers found\n");
907
        buildputs("No game controllers found\n");
908
    }
908
    }
909
    else
909
    else
910
    {
910
    {
911
        buildputs("Game controllers:\n");
911
        buildputs("Game controllers:\n");
912
        for (int i = 0; i < numjoysticks; i++)
912
        for (int i = 0; i < numjoysticks; i++)
913
        {
913
        {
914
            const char * name;
914
            const char * name;
915
#if SDL_MAJOR_VERSION >= 2
915
#if SDL_MAJOR_VERSION >= 2
916
            if (SDL_IsGameController(i))
916
            if (SDL_IsGameController(i))
917
                name = SDL_GameControllerNameForIndex(i);
917
                name = SDL_GameControllerNameForIndex(i);
918
            else
918
            else
919
#endif
919
#endif
920
                name = SDL_JoystickNameForIndex(i);
920
                name = SDL_JoystickNameForIndex(i);
921
921
922
            buildprintf("  %d. %s\n", i+1, name);
922
            buildprintf("  %d. %s\n", i+1, name);
923
        }
923
        }
924
924
925
#if SDL_MAJOR_VERSION >= 2
925
#if SDL_MAJOR_VERSION >= 2
926
        for (int i = 0; i < numjoysticks; i++)
926
        for (int i = 0; i < numjoysticks; i++)
927
        {
927
        {
928
            if ((controller = SDL_GameControllerOpen(i)))
928
            if ((controller = SDL_GameControllerOpen(i)))
929
            {
929
            {
930
                buildprintf("Using controller %s\n", SDL_GameControllerName(controller));
930
                buildprintf("Using controller %s\n", SDL_GameControllerName(controller));
931
931
932
                joystick.numAxes    = SDL_CONTROLLER_AXIS_MAX;
932
                joystick.numAxes    = SDL_CONTROLLER_AXIS_MAX;
933
                joystick.numBalls   = 0;
933
                joystick.numBalls   = 0;
934
                joystick.numButtons = SDL_CONTROLLER_BUTTON_MAX;
934
                joystick.numButtons = SDL_CONTROLLER_BUTTON_MAX;
935
                joystick.numHats    = 0;
935
                joystick.numHats    = 0;
936
936
937
                joystick.isGameController = 1;
937
                joystick.isGameController = 1;
938
938
939
                Xfree(joystick.pAxis);
939
                Xfree(joystick.pAxis);
940
                joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t));
940
                joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t));
941
                Xfree(joystick.pHat);
941
                Xfree(joystick.pHat);
942
                joystick.pHat = nullptr;
942
                joystick.pHat = nullptr;
943
943
944
                inputdevices |= 4;
944
                inputdevices |= 4;
945
945
946
                return;
946
                return;
947
            }
947
            }
948
        }
948
        }
949
#endif
949
#endif
950
950
951
        for (int i = 0; i < numjoysticks; i++)
951
        for (int i = 0; i < numjoysticks; i++)
952
        {
952
        {
953
            if ((joydev = SDL_JoystickOpen(i)))
953
            if ((joydev = SDL_JoystickOpen(i)))
954
            {
954
            {
955
                buildprintf("Using joystick %s\n", SDL_JoystickNameForIndex(i));
955
                buildprintf("Using joystick %s\n", SDL_JoystickNameForIndex(i));
956
956
957
                // KEEPINSYNC duke3d/src/gamedefs.h, mact/include/_control.h
957
                // KEEPINSYNC duke3d/src/gamedefs.h, mact/include/_control.h
958
                joystick.numAxes    = min(9, SDL_JoystickNumAxes(joydev));
958
                joystick.numAxes    = min(9, SDL_JoystickNumAxes(joydev));
959
                joystick.numBalls   = SDL_JoystickNumBalls(joydev);
959
                joystick.numBalls   = SDL_JoystickNumBalls(joydev);
960
                joystick.numButtons = min(32, SDL_JoystickNumButtons(joydev));
960
                joystick.numButtons = min(32, SDL_JoystickNumButtons(joydev));
961
                joystick.numHats    = min((36 - joystick.numButtons) / 4, SDL_JoystickNumHats(joydev));
961
                joystick.numHats    = min((36 - joystick.numButtons) / 4, SDL_JoystickNumHats(joydev));
962
962
963
                joystick.isGameController = 0;
963
                joystick.isGameController = 0;
964
964
965
                buildprint("Joystick ", i+1, " has ", joystick.numAxes, " axes, ", joystick.numButtons, " buttons, ");
965
                buildprint("Joystick ", i+1, " has ", joystick.numAxes, " axes, ", joystick.numButtons, " buttons, ");
966
                if (joystick.numHats) buildprint(joystick.numHats); else buildprint("no");
966
                if (joystick.numHats) buildprint(joystick.numHats); else buildprint("no");
967
                buildprint(" hats, and ");
967
                buildprint(" hats, and ");
968
                if (joystick.numBalls) buildprint(joystick.numBalls); else buildprint("no");
968
                if (joystick.numBalls) buildprint(joystick.numBalls); else buildprint("no");
969
                buildprint(" balls.\n");
969
                buildprint(" balls.\n");
970
970
971
                Xfree(joystick.pAxis);
971
                Xfree(joystick.pAxis);
972
                joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t));
972
                joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t));
973
973
974
                Xfree(joystick.pHat);
974
                Xfree(joystick.pHat);
975
                if (joystick.numHats)
975
                if (joystick.numHats)
976
                    joystick.pHat = (int32_t *)Xcalloc(joystick.numHats, sizeof(int32_t));
976
                    joystick.pHat = (int32_t *)Xcalloc(joystick.numHats, sizeof(int32_t));
977
                else
977
                else
978
                    joystick.pHat = nullptr;
978
                    joystick.pHat = nullptr;
979
979
980
                for (int j = 0; j < joystick.numHats; j++)
980
                for (int j = 0; j < joystick.numHats; j++)
981
                    joystick.pHat[j] = -1; // center
981
                    joystick.pHat[j] = -1; // center
982
982
983
                SDL_JoystickEventState(SDL_ENABLE);
983
                SDL_JoystickEventState(SDL_ENABLE);
984
                inputdevices |= 4;
984
                inputdevices |= 4;
985
985
986
                return;
986
                return;
987
            }
987
            }
988
        }
988
        }
989
989
990
        buildputs("No controllers are usable\n");
990
        buildputs("No controllers are usable\n");
991
    }
991
    }
992
}
992
}
993
993
994
//
994
//
995
// initinput() -- init input system
995
// initinput() -- init input system
996
//
996
//
997
int32_t initinput(void)
997
int32_t initinput(void)
998
{
998
{
999
    int32_t i;
999
    int32_t i;
1000
1000
1001
#if defined EDUKE32_OSX
1001
#if defined EDUKE32_OSX
1002
    // force OS X to operate in >1 button mouse mode so that LMB isn't adulterated
1002
    // force OS X to operate in >1 button mouse mode so that LMB isn't adulterated
1003
    if (!getenv("SDL_HAS3BUTTONMOUSE"))
1003
    if (!getenv("SDL_HAS3BUTTONMOUSE"))
1004
    {
1004
    {
1005
        static char sdl_has3buttonmouse[] = "SDL_HAS3BUTTONMOUSE=1";
1005
        static char sdl_has3buttonmouse[] = "SDL_HAS3BUTTONMOUSE=1";
1006
        putenv(sdl_has3buttonmouse);
1006
        putenv(sdl_has3buttonmouse);
1007
    }
1007
    }
1008
#endif
1008
#endif
1009
1009
1010
    inputdevices = 1 | 2;  // keyboard (1) and mouse (2)
1010
    inputdevices = 1 | 2;  // keyboard (1) and mouse (2)
1011
    g_mouseGrabbed = 0;
1011
    g_mouseGrabbed = 0;
1012
1012
1013
    memset(g_keyNameTable, 0, sizeof(g_keyNameTable));
1013
    memset(g_keyNameTable, 0, sizeof(g_keyNameTable));
1014
1014
1015
#if SDL_MAJOR_VERSION == 1
1015
#if SDL_MAJOR_VERSION == 1
1016
#define SDL_SCANCODE_TO_KEYCODE(x) (SDLKey)(x)
1016
#define SDL_SCANCODE_TO_KEYCODE(x) (SDLKey)(x)
1017
#define SDL_NUM_SCANCODES SDLK_LAST
1017
#define SDL_NUM_SCANCODES SDLK_LAST
1018
    if (SDL_EnableKeyRepeat(250, 30))
1018
    if (SDL_EnableKeyRepeat(250, 30))
1019
        initprintf("Error enabling keyboard repeat.\n");
1019
        initprintf("Error enabling keyboard repeat.\n");
1020
    SDL_EnableUNICODE(1);  // let's hope this doesn't hit us too hard
1020
    SDL_EnableUNICODE(1);  // let's hope this doesn't hit us too hard
1021
#endif
1021
#endif
1022
1022
1023
    for (i = SDL_NUM_SCANCODES - 1; i >= 0; i--)
1023
    for (i = SDL_NUM_SCANCODES - 1; i >= 0; i--)
1024
    {
1024
    {
1025
        if (!keytranslation[i])
1025
        if (!keytranslation[i])
1026
            continue;
1026
            continue;
1027
1027
1028
        Bstrncpyz(g_keyNameTable[keytranslation[i]], SDL_GetKeyName(SDL_SCANCODE_TO_KEYCODE(i)), sizeof(g_keyNameTable[0]));
1028
        Bstrncpyz(g_keyNameTable[keytranslation[i]], SDL_GetKeyName(SDL_SCANCODE_TO_KEYCODE(i)), sizeof(g_keyNameTable[0]));
1029
    }
1029
    }
1030
1030
1031
#if SDL_MAJOR_VERSION >= 2
1031
#if SDL_MAJOR_VERSION >= 2
1032
    if (!SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER))
1032
    if (!SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER))
1033
#else
1033
#else
1034
    if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
1034
    if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
1035
#endif
1035
#endif
1036
    {
1036
    {
1037
#if SDL_MAJOR_VERSION >= 2
1037
#if SDL_MAJOR_VERSION >= 2
1038
        LoadSDLControllerDB();
1038
        LoadSDLControllerDB();
1039
#endif
1039
#endif
1040
1040
1041
        joyScanDevices();
1041
        joyScanDevices();
1042
    }
1042
    }
1043
1043
1044
    return 0;
1044
    return 0;
1045
}
1045
}
1046
1046
1047
//
1047
//
1048
// uninitinput() -- uninit input system
1048
// uninitinput() -- uninit input system
1049
//
1049
//
1050
void uninitinput(void)
1050
void uninitinput(void)
1051
{
1051
{
1052
    mouseUninit();
1052
    mouseUninit();
1053
1053
1054
#if SDL_MAJOR_VERSION >= 2
1054
#if SDL_MAJOR_VERSION >= 2
1055
    if (controller)
1055
    if (controller)
1056
    {
1056
    {
1057
        SDL_GameControllerClose(controller);
1057
        SDL_GameControllerClose(controller);
1058
        controller = NULL;
1058
        controller = NULL;
1059
    }
1059
    }
1060
#endif
1060
#endif
1061
1061
1062
    if (joydev)
1062
    if (joydev)
1063
    {
1063
    {
1064
        SDL_JoystickClose(joydev);
1064
        SDL_JoystickClose(joydev);
1065
        joydev = NULL;
1065
        joydev = NULL;
1066
    }
1066
    }
1067
}
1067
}
1068
1068
1069
#ifndef GEKKO
1069
#ifndef GEKKO
1070
const char *joyGetName(int32_t what, int32_t num)
1070
const char *joyGetName(int32_t what, int32_t num)
1071
{
1071
{
1072
    static char tmp[64];
1072
    static char tmp[64];
1073
1073
1074
    switch (what)
1074
    switch (what)
1075
    {
1075
    {
1076
        case 0:  // axis
1076
        case 0:  // axis
1077
            if ((unsigned)num > (unsigned)joystick.numAxes)
1077
            if ((unsigned)num > (unsigned)joystick.numAxes)
1078
                return NULL;
1078
                return NULL;
1079
1079
1080
#if SDL_MAJOR_VERSION >= 2
1080
#if SDL_MAJOR_VERSION >= 2
1081
            if (controller)
1081
            if (controller)
1082
            {
1082
            {
1083
# if 0
1083
# if 0
1084
                // Use this if SDL's provided strings ever become user-friendly.
1084
                // Use this if SDL's provided strings ever become user-friendly.
1085
                return SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)num);
1085
                return SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)num);
1086
# else
1086
# else
1087
                static char const * axisStrings[] =
1087
                static char const * axisStrings[] =
1088
                {
1088
                {
1089
                    "Left Stick X-Axis",
1089
                    "Left Stick X-Axis",
1090
                    "Left Stick Y-Axis",
1090
                    "Left Stick Y-Axis",
1091
                    "Right Stick X-Axis",
1091
                    "Right Stick X-Axis",
1092
                    "Right Stick Y-Axis",
1092
                    "Right Stick Y-Axis",
1093
                    "Left Trigger",
1093
                    "Left Trigger",
1094
                    "Right Trigger",
1094
                    "Right Trigger",
1095
                    NULL
1095
                    NULL
1096
                };
1096
                };
1097
                return axisStrings[num];
1097
                return axisStrings[num];
1098
# endif
1098
# endif
1099
            }
1099
            }
1100
#endif
1100
#endif
1101
1101
1102
            Bsprintf(tmp, "Axis %d", num);
1102
            Bsprintf(tmp, "Axis %d", num);
1103
            return (char *)tmp;
1103
            return (char *)tmp;
1104
1104
1105
        case 1:  // button
1105
        case 1:  // button
1106
            if ((unsigned)num > (unsigned)joystick.numButtons)
1106
            if ((unsigned)num > (unsigned)joystick.numButtons)
1107
                return NULL;
1107
                return NULL;
1108
1108
1109
#if SDL_MAJOR_VERSION >= 2
1109
#if SDL_MAJOR_VERSION >= 2
1110
            if (controller)
1110
            if (controller)
1111
            {
1111
            {
1112
# if 0
1112
# if 0
1113
                // See above.
1113
                // See above.
1114
                return SDL_GameControllerGetStringForButton((SDL_GameControllerButton)num);
1114
                return SDL_GameControllerGetStringForButton((SDL_GameControllerButton)num);
1115
# else
1115
# else
1116
                static char const * buttonStrings[] =
1116
                static char const * buttonStrings[] =
1117
                {
1117
                {
1118
                    "A",
1118
                    "A",
1119
                    "B",
1119
                    "B",
1120
                    "X",
1120
                    "X",
1121
                    "Y",
1121
                    "Y",
1122
                    "Back",
1122
                    "Back",
1123
                    "Guide",
1123
                    "Guide",
1124
                    "Start",
1124
                    "Start",
1125
                    "Left Stick",
1125
                    "Left Stick",
1126
                    "Right Stick",
1126
                    "Right Stick",
1127
                    "Left Shoulder",
1127
                    "Left Shoulder",
1128
                    "Right Shoulder",
1128
                    "Right Shoulder",
1129
                    "D-Pad Up",
1129
                    "D-Pad Up",
1130
                    "D-Pad Down",
1130
                    "D-Pad Down",
1131
                    "D-Pad Left",
1131
                    "D-Pad Left",
1132
                    "D-Pad Right",
1132
                    "D-Pad Right",
1133
                    NULL
1133
                    NULL
1134
                };
1134
                };
1135
                return buttonStrings[num];
1135
                return buttonStrings[num];
1136
# endif
1136
# endif
1137
            }
1137
            }
1138
#endif
1138
#endif
1139
1139
1140
            Bsprintf(tmp, "Button %d", num);
1140
            Bsprintf(tmp, "Button %d", num);
1141
            return (char *)tmp;
1141
            return (char *)tmp;
1142
1142
1143
        case 2:  // hat
1143
        case 2:  // hat
1144
            if ((unsigned)num > (unsigned)joystick.numHats)
1144
            if ((unsigned)num > (unsigned)joystick.numHats)
1145
                return NULL;
1145
                return NULL;
1146
            Bsprintf(tmp, "Hat %d", num);
1146
            Bsprintf(tmp, "Hat %d", num);
1147
            return (char *)tmp;
1147
            return (char *)tmp;
1148
1148
1149
        default: return NULL;
1149
        default: return NULL;
1150
    }
1150
    }
1151
}
1151
}
1152
#endif
1152
#endif
1153
1153
1154
1154
1155
//
1155
//
1156
// initmouse() -- init mouse input
1156
// initmouse() -- init mouse input
1157
//
1157
//
1158
void mouseInit(void)
1158
void mouseInit(void)
1159
{
1159
{
1160
    mouseGrabInput(g_mouseEnabled = g_mouseLockedToWindow);  // FIXME - SA
1160
    mouseGrabInput(g_mouseEnabled = g_mouseLockedToWindow);  // FIXME - SA
1161
}
1161
}
1162
1162
1163
//
1163
//
1164
// uninitmouse() -- uninit mouse input
1164
// uninitmouse() -- uninit mouse input
1165
//
1165
//
1166
void mouseUninit(void)
1166
void mouseUninit(void)
1167
{
1167
{
1168
    mouseGrabInput(0);
1168
    mouseGrabInput(0);
1169
    g_mouseEnabled = 0;
1169
    g_mouseEnabled = 0;
1170
}
1170
}
1171
1171
1172
1172
1173
#if SDL_MAJOR_VERSION != 1
1173
#if SDL_MAJOR_VERSION != 1
1174
//
1174
//
1175
// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state).
1175
// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state).
1176
//                    furthermore return 0 if successful.
1176
//                    furthermore return 0 if successful.
1177
//
1177
//
1178
1178
1179
static inline char grabmouse_low(char a)
1179
static inline char grabmouse_low(char a)
1180
{
1180
{
1181
#if !defined EDUKE32_TOUCH_DEVICES
1181
#if !defined EDUKE32_TOUCH_DEVICES
1182
    /* FIXME: Maybe it's better to make sure that grabmouse_low
1182
    /* FIXME: Maybe it's better to make sure that grabmouse_low
1183
       is called only when a window is ready?                */
1183
       is called only when a window is ready?                */
1184
    if (sdl_window)
1184
    if (sdl_window)
1185
        SDL_SetWindowGrab(sdl_window, a ? SDL_TRUE : SDL_FALSE);
1185
        SDL_SetWindowGrab(sdl_window, a ? SDL_TRUE : SDL_FALSE);
1186
    return SDL_SetRelativeMouseMode(a ? SDL_TRUE : SDL_FALSE);
1186
    return SDL_SetRelativeMouseMode(a ? SDL_TRUE : SDL_FALSE);
1187
#else
1187
#else
1188
    UNREFERENCED_PARAMETER(a);
1188
    UNREFERENCED_PARAMETER(a);
1189
    return 0;
1189
    return 0;
1190
#endif
1190
#endif
1191
}
1191
}
1192
#endif
1192
#endif
1193
1193
1194
//
1194
//
1195
// grabmouse() -- show/hide mouse cursor
1195
// grabmouse() -- show/hide mouse cursor
1196
//
1196
//
1197
void mouseGrabInput(bool grab)
1197
void mouseGrabInput(bool grab)
1198
{
1198
{
1199
    if (appactive && g_mouseEnabled)
1199
    if (appactive && g_mouseEnabled)
1200
    {
1200
    {
1201
#if !defined EDUKE32_TOUCH_DEVICES
1201
#if !defined EDUKE32_TOUCH_DEVICES
1202
        if ((grab != g_mouseGrabbed) && !grabmouse_low(grab))
1202
        if ((grab != g_mouseGrabbed) && !grabmouse_low(grab))
1203
#endif
1203
#endif
1204
            g_mouseGrabbed = grab;
1204
            g_mouseGrabbed = grab;
1205
    }
1205
    }
1206
    else
1206
    else
1207
        g_mouseGrabbed = grab;
1207
        g_mouseGrabbed = grab;
1208
1208
1209
    g_mousePos.x = g_mousePos.y = 0;
1209
    g_mousePos.x = g_mousePos.y = 0;
1210
}
1210
}
1211
1211
1212
void mouseLockToWindow(char a)
1212
void mouseLockToWindow(char a)
1213
{
1213
{
1214
    if (!(a & 2))
1214
    if (!(a & 2))
1215
    {
1215
    {
1216
        mouseGrabInput(a);
1216
        mouseGrabInput(a);
1217
        g_mouseLockedToWindow = g_mouseGrabbed;
1217
        g_mouseLockedToWindow = g_mouseGrabbed;
1218
    }
1218
    }
1219
1219
1220
    SDL_ShowCursor((osd && osd->flags & OSD_CAPTURE) ? SDL_ENABLE : SDL_DISABLE);
1220
    SDL_ShowCursor((osd && osd->flags & OSD_CAPTURE) ? SDL_ENABLE : SDL_DISABLE);
1221
}
1221
}
1222
1222
1223
//
1223
//
1224
// setjoydeadzone() -- sets the dead and saturation zones for the joystick
1224
// setjoydeadzone() -- sets the dead and saturation zones for the joystick
1225
//
1225
//
1226
void joySetDeadZone(int32_t axis, uint16_t dead, uint16_t satur)
1226
void joySetDeadZone(int32_t axis, uint16_t dead, uint16_t satur)
1227
{
1227
{
1228
    joydead[axis] = dead;
1228
    joydead[axis] = dead;
1229
    joysatur[axis] = satur;
1229
    joysatur[axis] = satur;
1230
}
1230
}
1231
1231
1232
1232
1233
//
1233
//
1234
// getjoydeadzone() -- gets the dead and saturation zones for the joystick
1234
// getjoydeadzone() -- gets the dead and saturation zones for the joystick
1235
//
1235
//
1236
void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur)
1236
void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur)
1237
{
1237
{
1238
    *dead = joydead[axis];
1238
    *dead = joydead[axis];
1239
    *satur = joysatur[axis];
1239
    *satur = joysatur[axis];
1240
}
1240
}
1241
1241
1242
1242
1243
//
1243
//
1244
//
1244
//
1245
// ---------------------------------------
1245
// ---------------------------------------
1246
//
1246
//
1247
// All things Video
1247
// All things Video
1248
//
1248
//
1249
// ---------------------------------------
1249
// ---------------------------------------
1250
//
1250
//
1251
//
1251
//
1252
1252
1253
1253
1254
//
1254
//
1255
// getvalidmodes() -- figure out what video modes are available
1255
// getvalidmodes() -- figure out what video modes are available
1256
//
1256
//
1257
static int sortmodes(const void *a_, const void *b_)
1257
static int sortmodes(const void *a_, const void *b_)
1258
{
1258
{
1259
    auto a = (const struct validmode_t *)b_;
1259
    auto a = (const struct validmode_t *)b_;
1260
    auto b = (const struct validmode_t *)a_;
1260
    auto b = (const struct validmode_t *)a_;
1261
1261
1262
    int x;
1262
    int x;
1263
1263
1264
    if ((x = a->fs   - b->fs)   != 0) return x;
1264
    if ((x = a->fs   - b->fs)   != 0) return x;
1265
    if ((x = a->bpp  - b->bpp)  != 0) return x;
1265
    if ((x = a->bpp  - b->bpp)  != 0) return x;
1266
    if ((x = a->xdim - b->xdim) != 0) return x;
1266
    if ((x = a->xdim - b->xdim) != 0) return x;
1267
    if ((x = a->ydim - b->ydim) != 0) return x;
1267
    if ((x = a->ydim - b->ydim) != 0) return x;
1268
1268
1269
    return 0;
1269
    return 0;
1270
}
1270
}
1271
1271
1272
static char modeschecked=0;
1272
static char modeschecked=0;
1273
1273
1274
#if SDL_MAJOR_VERSION != 1
1274
#if SDL_MAJOR_VERSION != 1
1275
void videoGetModes(void)
1275
void videoGetModes(void)
1276
{
1276
{
1277
    int32_t i, maxx = 0, maxy = 0;
1277
    int32_t i, maxx = 0, maxy = 0;
1278
    SDL_DisplayMode dispmode;
1278
    SDL_DisplayMode dispmode;
1279
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1279
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1280
1280
1281
    if (modeschecked || novideo)
1281
    if (modeschecked || novideo)
1282
        return;
1282
        return;
1283
1283
1284
    validmodecnt = 0;
1284
    validmodecnt = 0;
1285
    //    initprintf("Detecting video modes:\n");
1285
    //    initprintf("Detecting video modes:\n");
1286
1286
1287
    // do fullscreen modes first
1287
    // do fullscreen modes first
1288
    for (i = 0; i < SDL_GetNumDisplayModes(display); i++)
1288
    for (i = 0; i < SDL_GetNumDisplayModes(display); i++)
1289
    {
1289
    {
1290
        SDL_GetDisplayMode(display, i, &dispmode);
1290
        SDL_GetDisplayMode(display, i, &dispmode);
1291
1291
1292
        if (!SDL_CHECKMODE(dispmode.w, dispmode.h) ||
1292
        if (!SDL_CHECKMODE(dispmode.w, dispmode.h) ||
1293
            (maxrefreshfreq && (dispmode.refresh_rate > maxrefreshfreq)))
1293
            (maxrefreshfreq && (dispmode.refresh_rate > maxrefreshfreq)))
1294
            continue;
1294
            continue;
1295
1295
1296
        // HACK: 8-bit == Software, 32-bit == OpenGL
1296
        // HACK: 8-bit == Software, 32-bit == OpenGL
1297
        SDL_ADDMODE(dispmode.w, dispmode.h, 8, 1);
1297
        SDL_ADDMODE(dispmode.w, dispmode.h, 8, 1);
1298
#ifdef USE_OPENGL
1298
#ifdef USE_OPENGL
1299
        if (!nogl)
1299
        if (!nogl)
1300
            SDL_ADDMODE(dispmode.w, dispmode.h, 32, 1);
1300
            SDL_ADDMODE(dispmode.w, dispmode.h, 32, 1);
1301
#endif
1301
#endif
1302
        if ((dispmode.w > maxx) || (dispmode.h > maxy))
1302
        if ((dispmode.w > maxx) || (dispmode.h > maxy))
1303
        {
1303
        {
1304
            maxx = dispmode.w;
1304
            maxx = dispmode.w;
1305
            maxy = dispmode.h;
1305
            maxy = dispmode.h;
1306
        }
1306
        }
1307
    }
1307
    }
1308
1308
1309
    SDL_CHECKFSMODES(maxx, maxy);
1309
    SDL_CHECKFSMODES(maxx, maxy);
1310
1310
1311
    // add windowed modes next
1311
    // add windowed modes next
1312
    // SDL sorts display modes largest to smallest, so we can just compare with mode 0
1312
    // SDL sorts display modes largest to smallest, so we can just compare with mode 0
1313
    // to make sure we aren't adding modes that are larger than the actual screen res
1313
    // to make sure we aren't adding modes that are larger than the actual screen res
1314
    SDL_GetDisplayMode(display, 0, &dispmode);
1314
    SDL_GetDisplayMode(display, 0, &dispmode);
1315
1315
1316
    for (i = 0; g_defaultVideoModes[i].x; i++)
1316
    for (i = 0; g_defaultVideoModes[i].x; i++)
1317
    {
1317
    {
1318
        auto const &mode = g_defaultVideoModes[i];
1318
        auto const &mode = g_defaultVideoModes[i];
1319
1319
1320
        if (mode.x > dispmode.w || mode.y > dispmode.h || !SDL_CHECKMODE(mode.x, mode.y))
1320
        if (mode.x > dispmode.w || mode.y > dispmode.h || !SDL_CHECKMODE(mode.x, mode.y))
1321
            continue;
1321
            continue;
1322
1322
1323
        // 8-bit == Software, 32-bit == OpenGL
1323
        // 8-bit == Software, 32-bit == OpenGL
1324
        SDL_ADDMODE(mode.x, mode.y, 8, 0);
1324
        SDL_ADDMODE(mode.x, mode.y, 8, 0);
1325
1325
1326
#ifdef USE_OPENGL
1326
#ifdef USE_OPENGL
1327
        if (nogl)
1327
        if (nogl)
1328
            continue;
1328
            continue;
1329
1329
1330
        SDL_ADDMODE(mode.x, mode.y, 32, 0);
1330
        SDL_ADDMODE(mode.x, mode.y, 32, 0);
1331
#endif
1331
#endif
1332
    }
1332
    }
1333
1333
1334
    qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes);
1334
    qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes);
1335
1335
1336
    modeschecked = 1;
1336
    modeschecked = 1;
1337
}
1337
}
1338
#endif
1338
#endif
1339
1339
1340
//
1340
//
1341
// checkvideomode() -- makes sure the video mode passed is legal
1341
// checkvideomode() -- makes sure the video mode passed is legal
1342
//
1342
//
1343
int32_t videoCheckMode(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t forced)
1343
int32_t videoCheckMode(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t forced)
1344
{
1344
{
1345
    int32_t i, nearest=-1, dx, dy, odx=9999, ody=9999;
1345
    int32_t i, nearest=-1, dx, dy, odx=9999, ody=9999;
1346
1346
1347
    videoGetModes();
1347
    videoGetModes();
1348
1348
1349
    if (c>8
1349
    if (c>8
1350
#ifdef USE_OPENGL
1350
#ifdef USE_OPENGL
1351
            && nogl
1351
            && nogl
1352
#endif
1352
#endif
1353
       ) return -1;
1353
       ) return -1;
1354
1354
1355
    // fix up the passed resolution values to be multiples of 8
1355
    // fix up the passed resolution values to be multiples of 8
1356
    // and at least 320x200 or at most MAXXDIMxMAXYDIM
1356
    // and at least 320x200 or at most MAXXDIMxMAXYDIM
1357
    *x = clamp(*x, 320, MAXXDIM);
1357
    *x = clamp(*x, 320, MAXXDIM);
1358
    *y = clamp(*y, 200, MAXYDIM);
1358
    *y = clamp(*y, 200, MAXYDIM);
1359
1359
1360
    for (i = 0; i < validmodecnt; i++)
1360
    for (i = 0; i < validmodecnt; i++)
1361
    {
1361
    {
1362
        if (validmode[i].bpp != c || validmode[i].fs != fs)
1362
        if (validmode[i].bpp != c || validmode[i].fs != fs)
1363
            continue;
1363
            continue;
1364
1364
1365
        dx = klabs(validmode[i].xdim - *x);
1365
        dx = klabs(validmode[i].xdim - *x);
1366
        dy = klabs(validmode[i].ydim - *y);
1366
        dy = klabs(validmode[i].ydim - *y);
1367
1367
1368
        if (!(dx | dy))
1368
        if (!(dx | dy))
1369
        {
1369
        {
1370
            // perfect match
1370
            // perfect match
1371
            nearest = i;
1371
            nearest = i;
1372
            break;
1372
            break;
1373
        }
1373
        }
1374
1374
1375
        if ((dx <= odx) && (dy <= ody))
1375
        if ((dx <= odx) && (dy <= ody))
1376
        {
1376
        {
1377
            nearest = i;
1377
            nearest = i;
1378
            odx = dx;
1378
            odx = dx;
1379
            ody = dy;
1379
            ody = dy;
1380
        }
1380
        }
1381
    }
1381
    }
1382
1382
1383
#ifdef ANY_WINDOWED_SIZE
1383
#ifdef ANY_WINDOWED_SIZE
1384
    if (!forced && (fs&1) == 0 && (nearest < 0 || (validmode[nearest].xdim!=*x || validmode[nearest].ydim!=*y)))
1384
    if (!forced && (fs&1) == 0 && (nearest < 0 || (validmode[nearest].xdim!=*x || validmode[nearest].ydim!=*y)))
1385
        return 0x7fffffffl;
1385
        return 0x7fffffffl;
1386
#endif
1386
#endif
1387
1387
1388
    if (nearest < 0)
1388
    if (nearest < 0)
1389
        return -1;
1389
        return -1;
1390
1390
1391
    *x = validmode[nearest].xdim;
1391
    *x = validmode[nearest].xdim;
1392
    *y = validmode[nearest].ydim;
1392
    *y = validmode[nearest].ydim;
1393
1393
1394
    return nearest;
1394
    return nearest;
1395
}
1395
}
1396
1396
1397
static void destroy_window_resources()
1397
static void destroy_window_resources()
1398
{
1398
{
1399
/* We should NOT destroy the window surface. This is done automatically
1399
/* We should NOT destroy the window surface. This is done automatically
1400
   when SDL_DestroyWindow or SDL_SetVideoMode is called.             */
1400
   when SDL_DestroyWindow or SDL_SetVideoMode is called.             */
1401
1401
1402
#if SDL_MAJOR_VERSION == 2
1402
#if SDL_MAJOR_VERSION == 2
1403
    if (sdl_context)
1403
    if (sdl_context)
1404
        SDL_GL_DeleteContext(sdl_context);
1404
        SDL_GL_DeleteContext(sdl_context);
1405
    sdl_context = NULL;
1405
    sdl_context = NULL;
1406
    if (sdl_window)
1406
    if (sdl_window)
1407
        SDL_DestroyWindow(sdl_window);
1407
        SDL_DestroyWindow(sdl_window);
1408
    sdl_window = NULL;
1408
    sdl_window = NULL;
1409
#endif
1409
#endif
1410
}
1410
}
1411
1411
1412
#ifdef USE_OPENGL
1412
#ifdef USE_OPENGL
1413
void sdlayer_setvideomode_opengl(void)
1413
void sdlayer_setvideomode_opengl(void)
1414
{
1414
{
1415
    glsurface_destroy();
1415
    glsurface_destroy();
1416
    polymost_glreset();
1416
    polymost_glreset();
1417
1417
1418
    glShadeModel(GL_SMOOTH);  // GL_FLAT
1418
    glShadeModel(GL_SMOOTH);  // GL_FLAT
1419
    glClearColor(0, 0, 0, 1.0);  // Black Background
1419
    glClearColor(0, 0, 0, 1.0);  // Black Background
1420
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Use FASTEST for ortho!
1420
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Use FASTEST for ortho!
1421
//    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1421
//    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1422
1422
1423
#ifndef EDUKE32_GLES
1423
#ifndef EDUKE32_GLES
1424
    glDisable(GL_DITHER);
1424
    glDisable(GL_DITHER);
1425
#endif
1425
#endif
1426
1426
1427
    fill_glinfo();
1427
    fill_glinfo();
1428
1428
1429
}
1429
}
1430
#endif  // defined USE_OPENGL
1430
#endif  // defined USE_OPENGL
1431
1431
1432
//
1432
//
1433
// setvideomode() -- set SDL video mode
1433
// setvideomode() -- set SDL video mode
1434
//
1434
//
1435
1435
1436
int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t *regrab)
1436
int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t *regrab)
1437
{
1437
{
1438
    if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (c == bpp) && !videomodereset)
1438
    if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (c == bpp) && !videomodereset)
1439
        return 0;
1439
        return 0;
1440
1440
1441
    if (videoCheckMode(x, y, c, fs, 0) < 0)
1441
    if (videoCheckMode(x, y, c, fs, 0) < 0)
1442
        return -1;
1442
        return -1;
1443
1443
1444
#ifdef GEKKO
1444
#ifdef GEKKO
1445
    if (!sdl_surface) // only run this the first time we set a video mode
1445
    if (!sdl_surface) // only run this the first time we set a video mode
1446
        wii_initgamevideo();
1446
        wii_initgamevideo();
1447
#endif
1447
#endif
1448
1448
1449
    startwin_close();
1449
    startwin_close();
1450
1450
1451
    if (g_mouseGrabbed)
1451
    if (g_mouseGrabbed)
1452
    {
1452
    {
1453
        *regrab = 1;
1453
        *regrab = 1;
1454
        mouseGrabInput(0);
1454
        mouseGrabInput(0);
1455
    }
1455
    }
1456
1456
1457
    while (lockcount) videoEndDrawing();
1457
    while (lockcount) videoEndDrawing();
1458
1458
1459
#ifdef USE_OPENGL
1459
#ifdef USE_OPENGL
1460
    if (sdl_surface)
1460
    if (sdl_surface)
1461
    {
1461
    {
1462
        if (bpp > 8)
1462
        if (bpp > 8)
1463
            polymost_glreset();
1463
            polymost_glreset();
1464
    }
1464
    }
1465
    if (!nogl)
1465
    if (!nogl)
1466
    {
1466
    {
1467
        if (bpp == 8)
1467
        if (bpp == 8)
1468
            glsurface_destroy();
1468
            glsurface_destroy();
1469
        if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (bpp != 0) && !videomodereset)
1469
        if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (bpp != 0) && !videomodereset)
1470
            return 0;
1470
            return 0;
1471
    }
1471
    }
1472
    else
1472
    else
1473
#endif
1473
#endif
1474
    {
1474
    {
1475
       softsurface_destroy();
1475
       softsurface_destroy();
1476
    }
1476
    }
1477
1477
1478
    // clear last gamma/contrast/brightness so that it will be set anew
1478
    // clear last gamma/contrast/brightness so that it will be set anew
1479
    lastvidgcb[0] = lastvidgcb[1] = lastvidgcb[2] = 0.0f;
1479
    lastvidgcb[0] = lastvidgcb[1] = lastvidgcb[2] = 0.0f;
1480
1480
1481
    return 1;
1481
    return 1;
1482
}
1482
}
1483
1483
1484
void setvideomode_sdlcommonpost(int32_t x, int32_t y, int32_t c, int32_t fs, int32_t regrab)
1484
void setvideomode_sdlcommonpost(int32_t x, int32_t y, int32_t c, int32_t fs, int32_t regrab)
1485
{
1485
{
1486
    wm_setapptitle(apptitle);
1486
    wm_setapptitle(apptitle);
1487
1487
1488
#ifdef USE_OPENGL
1488
#ifdef USE_OPENGL
1489
    if (!nogl)
1489
    if (!nogl)
1490
        sdlayer_setvideomode_opengl();
1490
        sdlayer_setvideomode_opengl();
1491
#endif
1491
#endif
1492
1492
1493
    xres = x;
1493
    xres = x;
1494
    yres = y;
1494
    yres = y;
1495
    bpp = c;
1495
    bpp = c;
1496
    fullscreen = fs;
1496
    fullscreen = fs;
1497
    // bytesperline = sdl_surface->pitch;
1497
    // bytesperline = sdl_surface->pitch;
1498
    numpages = c > 8 ? 2 : 1;
1498
    numpages = c > 8 ? 2 : 1;
1499
    frameplace = 0;
1499
    frameplace = 0;
1500
    lockcount = 0;
1500
    lockcount = 0;
1501
    modechange = 1;
1501
    modechange = 1;
1502
    videomodereset = 0;
1502
    videomodereset = 0;
1503
1503
1504
    // save the current system gamma to determine if gamma is available
1504
    // save the current system gamma to determine if gamma is available
1505
#ifndef EDUKE32_GLES
1505
#ifndef EDUKE32_GLES
1506
    if (!gammabrightness)
1506
    if (!gammabrightness)
1507
    {
1507
    {
1508
        //        float f = 1.0 + ((float)curbrightness / 10.0);
1508
        //        float f = 1.0 + ((float)curbrightness / 10.0);
1509
#if SDL_MAJOR_VERSION != 1
1509
#if SDL_MAJOR_VERSION != 1
1510
        if (SDL_GetWindowGammaRamp(sdl_window, sysgamma[0], sysgamma[1], sysgamma[2]) == 0)
1510
        if (SDL_GetWindowGammaRamp(sdl_window, sysgamma[0], sysgamma[1], sysgamma[2]) == 0)
1511
#else
1511
#else
1512
        if (SDL_GetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]) >= 0)
1512
        if (SDL_GetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]) >= 0)
1513
#endif
1513
#endif
1514
            gammabrightness = 1;
1514
            gammabrightness = 1;
1515
1515
1516
        // see if gamma really is working by trying to set the brightness
1516
        // see if gamma really is working by trying to set the brightness
1517
        if (gammabrightness && videoSetGamma() < 0)
1517
        if (gammabrightness && videoSetGamma() < 0)
1518
            gammabrightness = 0;  // nope
1518
            gammabrightness = 0;  // nope
1519
    }
1519
    }
1520
#endif
1520
#endif
1521
1521
1522
    videoFadePalette(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
1522
    videoFadePalette(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
1523
1523
1524
    if (regrab)
1524
    if (regrab)
1525
        mouseGrabInput(g_mouseLockedToWindow);
1525
        mouseGrabInput(g_mouseLockedToWindow);
1526
}
1526
}
1527
1527
1528
#if SDL_MAJOR_VERSION!=1
1528
#if SDL_MAJOR_VERSION!=1
1529
void setrefreshrate(void)
1529
void setrefreshrate(void)
1530
{
1530
{
1531
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1531
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1532
1532
1533
    SDL_DisplayMode dispmode;
1533
    SDL_DisplayMode dispmode;
1534
    SDL_GetCurrentDisplayMode(display, &dispmode);
1534
    SDL_GetCurrentDisplayMode(display, &dispmode);
1535
1535
1536
    dispmode.refresh_rate = maxrefreshfreq;
1536
    dispmode.refresh_rate = maxrefreshfreq;
1537
1537
1538
    SDL_DisplayMode newmode;
1538
    SDL_DisplayMode newmode;
1539
    SDL_GetClosestDisplayMode(display, &dispmode, &newmode);
1539
    SDL_GetClosestDisplayMode(display, &dispmode, &newmode);
1540
1540
1541
    char error = 0;
1541
    char error = 0;
1542
1542
1543
    if (dispmode.refresh_rate != newmode.refresh_rate)
1543
    if (dispmode.refresh_rate != newmode.refresh_rate)
1544
        error = SDL_SetWindowDisplayMode(sdl_window, &newmode);
1544
        error = SDL_SetWindowDisplayMode(sdl_window, &newmode);
1545
1545
1546
    if (!newmode.refresh_rate || error)
1546
    if (!newmode.refresh_rate || error)
1547
        newmode.refresh_rate = 59;
1547
        newmode.refresh_rate = 59;
1548
1548
1549
#ifdef _WIN32
1549
#ifdef _WIN32
1550
    if (timingInfo.rateRefresh.uiNumerator)
1550
    if (timingInfo.rateRefresh.uiNumerator)
1551
        refreshfreq = (double)timingInfo.rateRefresh.uiNumerator / timingInfo.rateRefresh.uiDenominator;
1551
        refreshfreq = (double)timingInfo.rateRefresh.uiNumerator / timingInfo.rateRefresh.uiDenominator;
1552
    else
1552
    else
1553
#endif
1553
#endif
1554
        refreshfreq = newmode.refresh_rate;
1554
        refreshfreq = newmode.refresh_rate;
1555
1555
1556
    initprintf("Refresh rate: %.2fHz\n", refreshfreq);
1556
    initprintf("Refresh rate: %.2fHz\n", refreshfreq);
1557
}
1557
}
1558
1558
1559
int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
1559
int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
1560
{
1560
{
1561
    int32_t regrab = 0, ret;
1561
    int32_t regrab = 0, ret;
1562
1562
1563
    ret = setvideomode_sdlcommon(&x, &y, c, fs, &regrab);
1563
    ret = setvideomode_sdlcommon(&x, &y, c, fs, &regrab);
1564
1564
1565
    if (ret != 1)
1565
    if (ret != 1)
1566
    {
1566
    {
1567
        if (ret == 0)
1567
        if (ret == 0)
1568
        {
1568
        {
1569
            setvideomode_sdlcommonpost(x, y, c, fs, regrab);
1569
            setvideomode_sdlcommonpost(x, y, c, fs, regrab);
1570
        }
1570
        }
1571
        return ret;
1571
        return ret;
1572
    }
1572
    }
1573
1573
1574
    // deinit
1574
    // deinit
1575
    destroy_window_resources();
1575
    destroy_window_resources();
1576
1576
1577
    initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
1577
    initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
1578
1578
1579
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1579
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1580
1580
1581
    SDL_DisplayMode desktopmode;
1581
    SDL_DisplayMode desktopmode;
1582
    SDL_GetDesktopDisplayMode(display, &desktopmode);
1582
    SDL_GetDesktopDisplayMode(display, &desktopmode);
1583
1583
1584
    int const matchedResolution = (desktopmode.w == x && desktopmode.h == y);
1584
    int const matchedResolution = (desktopmode.w == x && desktopmode.h == y);
1585
    int const borderless = (r_borderless == 1 || (r_borderless == 2 && matchedResolution)) ? SDL_WINDOW_BORDERLESS : 0;
1585
    int const borderless = (r_borderless == 1 || (r_borderless == 2 && matchedResolution)) ? SDL_WINDOW_BORDERLESS : 0;
1586
#ifdef USE_OPENGL
1586
#ifdef USE_OPENGL
1587
    if (c > 8 || !nogl)
1587
    if (c > 8 || !nogl)
1588
    {
1588
    {
1589
        int32_t i;
1589
        int32_t i;
1590
1590
1591
        if (nogl)
1591
        if (nogl)
1592
            return -1;
1592
            return -1;
1593
1593
1594
        struct glattribs
1594
        struct glattribs
1595
        {
1595
        {
1596
            SDL_GLattr attr;
1596
            SDL_GLattr attr;
1597
            int32_t value;
1597
            int32_t value;
1598
        } sdlayer_gl_attributes[] =
1598
        } sdlayer_gl_attributes[] =
1599
        {
1599
        {
1600
#ifdef EDUKE32_GLES
1600
#ifdef EDUKE32_GLES
1601
              { SDL_GL_CONTEXT_MAJOR_VERSION, 1 },
1601
              { SDL_GL_CONTEXT_MAJOR_VERSION, 1 },
1602
              { SDL_GL_CONTEXT_MINOR_VERSION, 1 },
1602
              { SDL_GL_CONTEXT_MINOR_VERSION, 1 },
1603
#endif
1603
#endif
1604
              { SDL_GL_DOUBLEBUFFER, 1 },
1604
              { SDL_GL_DOUBLEBUFFER, 1 },
1605
1605
1606
              { SDL_GL_STENCIL_SIZE, 1 },
1606
              { SDL_GL_STENCIL_SIZE, 1 },
1607
              { SDL_GL_ACCELERATED_VISUAL, 1 },
1607
              { SDL_GL_ACCELERATED_VISUAL, 1 },
1608
          };
1608
          };
1609
1609
1610
        SDL_GL_ATTRIBUTES(i, sdlayer_gl_attributes);
1610
        SDL_GL_ATTRIBUTES(i, sdlayer_gl_attributes);
1611
1611
1612
        /* HACK: changing SDL GL attribs only works before surface creation,
1612
        /* HACK: changing SDL GL attribs only works before surface creation,
1613
            so we have to create a new surface in a different format first
1613
            so we have to create a new surface in a different format first
1614
            to force the surface we WANT to be recreated instead of reused. */
1614
            to force the surface we WANT to be recreated instead of reused. */
1615
1615
1616
1616
1617
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display),
1617
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display),
1618
                                        windowpos ? windowy : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display), x, y,
1618
                                        windowpos ? windowy : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display), x, y,
1619
                                        SDL_WINDOW_OPENGL | borderless);
1619
                                        SDL_WINDOW_OPENGL | borderless);
1620
1620
1621
        if (sdl_window)
1621
        if (sdl_window)
1622
            sdl_context = SDL_GL_CreateContext(sdl_window);
1622
            sdl_context = SDL_GL_CreateContext(sdl_window);
1623
1623
1624
        if (!sdl_window || !sdl_context)
1624
        if (!sdl_window || !sdl_context)
1625
        {
1625
        {
1626
            initprintf("Unable to set video mode: %s failed: %s\n", sdl_window ? "SDL_GL_CreateContext" : "SDL_GL_CreateWindow",  SDL_GetError());
1626
            initprintf("Unable to set video mode: %s failed: %s\n", sdl_window ? "SDL_GL_CreateContext" : "SDL_GL_CreateWindow",  SDL_GetError());
1627
            nogl = 1;
1627
            nogl = 1;
1628
            destroy_window_resources();
1628
            destroy_window_resources();
1629
            return -1;
1629
            return -1;
1630
        }
1630
        }
1631
1631
1632
        gladLoadGLLoader(SDL_GL_GetProcAddress);
1632
        gladLoadGLLoader(SDL_GL_GetProcAddress);
1633
        if (GLVersion.major < 2)
1633
        if (GLVersion.major < 2)
1634
        {
1634
        {
1635
            initprintf("Your computer does not support OpenGL version 2 or greater. GL modes are unavailable.\n");
1635
            initprintf("Your computer does not support OpenGL version 2 or greater. GL modes are unavailable.\n");
1636
            nogl = 1;
1636
            nogl = 1;
1637
            destroy_window_resources();
1637
            destroy_window_resources();
1638
            return -1;
1638
            return -1;
1639
        }
1639
        }
1640
1640
1641
        SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? (matchedResolution ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0));
1641
        SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? (matchedResolution ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0));
1642
        SDL_GL_SetSwapInterval(sdlayer_getswapinterval(vsync_renderlayer));
1642
        SDL_GL_SetSwapInterval(sdlayer_getswapinterval(vsync_renderlayer));
1643
        vsync_renderlayer = sdlayer_checkvsync(vsync_renderlayer);
1643
        vsync_renderlayer = sdlayer_checkvsync(vsync_renderlayer);
1644
1644
1645
        setrefreshrate();
1645
        setrefreshrate();
1646
    }
1646
    }
1647
    else
1647
    else
1648
#endif  // defined USE_OPENGL
1648
#endif  // defined USE_OPENGL
1649
    {
1649
    {
1650
        // init
1650
        // init
1651
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display),
1651
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display),
1652
                                      windowpos ? windowy : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display), x, y,
1652
                                      windowpos ? windowy : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display), x, y,
1653
                                      borderless);
1653
                                      borderless);
1654
        if (!sdl_window)
1654
        if (!sdl_window)
1655
            SDL2_VIDEO_ERR("SDL_CreateWindow");
1655
            SDL2_VIDEO_ERR("SDL_CreateWindow");
1656
1656
1657
        setrefreshrate();
1657
        setrefreshrate();
1658
1658
1659
        sdl_surface = SDL_GetWindowSurface(sdl_window);
1659
        sdl_surface = SDL_GetWindowSurface(sdl_window);
1660
        if (!sdl_surface)
1660
        if (!sdl_surface)
1661
            SDL2_VIDEO_ERR("SDL_GetWindowSurface");
1661
            SDL2_VIDEO_ERR("SDL_GetWindowSurface");
1662
1662
1663
        SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? (matchedResolution ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0));
1663
        SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? (matchedResolution ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0));
1664
    }
1664
    }
1665
1665
1666
    setvideomode_sdlcommonpost(x, y, c, fs, regrab);
1666
    setvideomode_sdlcommonpost(x, y, c, fs, regrab);
1667
1667
1668
    return 0;
1668
    return 0;
1669
}
1669
}
1670
#endif
1670
#endif
1671
1671
1672
//
1672
//
1673
// resetvideomode() -- resets the video system
1673
// resetvideomode() -- resets the video system
1674
//
1674
//
1675
void videoResetMode(void)
1675
void videoResetMode(void)
1676
{
1676
{
1677
    videomodereset = 1;
1677
    videomodereset = 1;
1678
    modeschecked = 0;
1678
    modeschecked = 0;
1679
}
1679
}
1680
1680
1681
//
1681
//
1682
// begindrawing() -- locks the framebuffer for drawing
1682
// begindrawing() -- locks the framebuffer for drawing
1683
//
1683
//
1684
1684
1685
#ifdef DEBUG_FRAME_LOCKING
1685
#ifdef DEBUG_FRAME_LOCKING
1686
uint32_t begindrawing_line[BEGINDRAWING_SIZE];
1686
uint32_t begindrawing_line[BEGINDRAWING_SIZE];
1687
const char *begindrawing_file[BEGINDRAWING_SIZE];
1687
const char *begindrawing_file[BEGINDRAWING_SIZE];
1688
void begindrawing_real(void)
1688
void begindrawing_real(void)
1689
#else
1689
#else
1690
void videoBeginDrawing(void)
1690
void videoBeginDrawing(void)
1691
#endif
1691
#endif
1692
{
1692
{
1693
    if (bpp > 8)
1693
    if (bpp > 8)
1694
    {
1694
    {
1695
        if (offscreenrendering) return;
1695
        if (offscreenrendering) return;
1696
        frameplace = 0;
1696
        frameplace = 0;
1697
        bytesperline = 0;
1697
        bytesperline = 0;
1698
        modechange = 0;
1698
        modechange = 0;
1699
        return;
1699
        return;
1700
    }
1700
    }
1701
1701
1702
    // lock the frame
1702
    // lock the frame
1703
    if (lockcount++ > 0)
1703
    if (lockcount++ > 0)
1704
        return;
1704
        return;
1705
1705
1706
    static intptr_t backupFrameplace = 0;
1706
    static intptr_t backupFrameplace = 0;
1707
1707
1708
    if (inpreparemirror)
1708
    if (inpreparemirror)
1709
    {
1709
    {
1710
        //POGO: if we are offscreenrendering and we need to render a mirror
1710
        //POGO: if we are offscreenrendering and we need to render a mirror
1711
        //      or we are rendering a mirror and we start offscreenrendering,
1711
        //      or we are rendering a mirror and we start offscreenrendering,
1712
        //      backup our offscreen target so we can restore it later
1712
        //      backup our offscreen target so we can restore it later
1713
        //      (but only allow one level deep,
1713
        //      (but only allow one level deep,
1714
        //       i.e. no viewscreen showing a camera showing a mirror that reflects the same viewscreen and recursing)
1714
        //       i.e. no viewscreen showing a camera showing a mirror that reflects the same viewscreen and recursing)
1715
        if (offscreenrendering)
1715
        if (offscreenrendering)
1716
        {
1716
        {
1717
            if (!backupFrameplace)
1717
            if (!backupFrameplace)
1718
                backupFrameplace = frameplace;
1718
                backupFrameplace = frameplace;
1719
            else if (frameplace != (intptr_t)mirrorBuffer &&
1719
            else if (frameplace != (intptr_t)mirrorBuffer &&
1720
                     frameplace != backupFrameplace)
1720
                     frameplace != backupFrameplace)
1721
                return;
1721
                return;
1722
        }
1722
        }
1723
1723
1724
        frameplace = (intptr_t)mirrorBuffer;
1724
        frameplace = (intptr_t)mirrorBuffer;
1725
1725
1726
        if (offscreenrendering)
1726
        if (offscreenrendering)
1727
            return;
1727
            return;
1728
    }
1728
    }
1729
    else if (offscreenrendering)
1729
    else if (offscreenrendering)
1730
    {
1730
    {
1731
        if (backupFrameplace)
1731
        if (backupFrameplace)
1732
        {
1732
        {
1733
            frameplace = backupFrameplace;
1733
            frameplace = backupFrameplace;
1734
            backupFrameplace = 0;
1734
            backupFrameplace = 0;
1735
        }
1735
        }
1736
        return;
1736
        return;
1737
    }
1737
    }
1738
    else
1738
    else
1739
#ifdef USE_OPENGL
1739
#ifdef USE_OPENGL
1740
    if (!nogl)
1740
    if (!nogl)
1741
    {
1741
    {
1742
        frameplace = (intptr_t)glsurface_getBuffer();
1742
        frameplace = (intptr_t)glsurface_getBuffer();
1743
    }
1743
    }
1744
    else
1744
    else
1745
#endif
1745
#endif
1746
    {
1746
    {
1747
        frameplace = (intptr_t)softsurface_getBuffer();
1747
        frameplace = (intptr_t)softsurface_getBuffer();
1748
    }
1748
    }
1749
1749
1750
    if (modechange)
1750
    if (modechange)
1751
    {
1751
    {
1752
        bytesperline = xdim;
1752
        bytesperline = xdim;
1753
        calc_ylookup(bytesperline, ydim);
1753
        calc_ylookup(bytesperline, ydim);
1754
        modechange=0;
1754
        modechange=0;
1755
    }
1755
    }
1756
}
1756
}
1757
1757
1758
1758
1759
//
1759
//
1760
// enddrawing() -- unlocks the framebuffer
1760
// enddrawing() -- unlocks the framebuffer
1761
//
1761
//
1762
void videoEndDrawing(void)
1762
void videoEndDrawing(void)
1763
{
1763
{
1764
    if (bpp > 8)
1764
    if (bpp > 8)
1765
    {
1765
    {
1766
        if (!offscreenrendering) frameplace = 0;
1766
        if (!offscreenrendering) frameplace = 0;
1767
        return;
1767
        return;
1768
    }
1768
    }
1769
1769
1770
    if (!frameplace) return;
1770
    if (!frameplace) return;
1771
    if (lockcount > 1) { lockcount--; return; }
1771
    if (lockcount > 1) { lockcount--; return; }
1772
    if (!offscreenrendering) frameplace = 0;
1772
    if (!offscreenrendering) frameplace = 0;
1773
    if (lockcount == 0) return;
1773
    if (lockcount == 0) return;
1774
    lockcount = 0;
1774
    lockcount = 0;
1775
}
1775
}
1776
1776
1777
//
1777
//
1778
// showframe() -- update the display
1778
// showframe() -- update the display
1779
//
1779
//
1780
#if SDL_MAJOR_VERSION != 1
1780
#if SDL_MAJOR_VERSION != 1
1781
1781
1782
#ifdef __ANDROID__
1782
#ifdef __ANDROID__
1783
extern "C" void AndroidDrawControls();
1783
extern "C" void AndroidDrawControls();
1784
#endif
1784
#endif
1785
1785
1786
void videoShowFrame(int32_t w)
1786
void videoShowFrame(int32_t w)
1787
{
1787
{
1788
    UNREFERENCED_PARAMETER(w);
1788
    UNREFERENCED_PARAMETER(w);
1789
1789
1790
#ifdef __ANDROID__
1790
#ifdef __ANDROID__
1791
    if (mobile_halted) return;
1791
    if (mobile_halted) return;
1792
#endif
1792
#endif
1793
1793
1794
#ifdef USE_OPENGL
1794
#ifdef USE_OPENGL
1795
    if (!nogl)
1795
    if (!nogl)
1796
    {
1796
    {
1797
        if (bpp > 8)
1797
        if (bpp > 8)
1798
        {
1798
        {
1799
            if (palfadedelta)
1799
            if (palfadedelta)
1800
                fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
1800
                fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
1801
1801
1802
#ifdef __ANDROID__
1802
#ifdef __ANDROID__
1803
            AndroidDrawControls();
1803
            AndroidDrawControls();
1804
#endif
1804
#endif
1805
        }
1805
        }
1806
        else
1806
        else
1807
        {
1807
        {
1808
            glsurface_blitBuffer();
1808
            glsurface_blitBuffer();
1809
        }
1809
        }
1810
1810
1811
#ifdef _WIN32
1811
#ifdef _WIN32
1812
        if (vsync_renderlayer == 2)
1812
        if (vsync_renderlayer == 2)
1813
        {
1813
        {
1814
            glFinish();
1814
            glFinish();
1815
1815
1816
            static uint64_t nextSwapTime = timerGetPerformanceCounter();
1816
            static uint64_t nextSwapTime = timerGetPerformanceCounter();
1817
            uint64_t const  swapInterval = (timerGetPerformanceFrequency() / refreshfreq);
1817
            uint64_t const  swapInterval = (timerGetPerformanceFrequency() / refreshfreq);
1818
            uint64_t const  swapTime     = timerGetPerformanceCounter();
1818
            uint64_t const  swapTime     = timerGetPerformanceCounter();
1819
1819
1820
            // TODO: use timing information to determine swap time and just busy loop ourselves for more timing control
1820
            // TODO: use timing information to determine swap time and just busy loop ourselves for more timing control
1821
            if (swapTime < nextSwapTime)
1821
            if (swapTime < nextSwapTime)
1822
                windowsWaitForVBlank();
1822
                windowsWaitForVBlank();
1823
1823
1824
            if (swapTime > nextSwapTime + swapInterval)
1824
            if (swapTime > nextSwapTime + swapInterval)
1825
                nextSwapTime += swapInterval;
1825
                nextSwapTime += swapInterval;
1826
1826
1827
            nextSwapTime += swapInterval;
1827
            nextSwapTime += swapInterval;
1828
        }
1828
        }
1829
#endif
1829
#endif
1830
1830
1831
        SDL_GL_SwapWindow(sdl_window);
1831
        SDL_GL_SwapWindow(sdl_window);
1832
1832
1833
        return;
1833
        return;
1834
    }
1834
    }
1835
#endif
1835
#endif
1836
1836
1837
    if (offscreenrendering) return;
1837
    if (offscreenrendering) return;
1838
1838
1839
    if (lockcount)
1839
    if (lockcount)
1840
    {
1840
    {
1841
        OSD_Printf("Frame still locked %d times when showframe() called.\n", lockcount);
1841
        OSD_Printf("Frame still locked %d times when showframe() called.\n", lockcount);
1842
        while (lockcount) videoEndDrawing();
1842
        while (lockcount) videoEndDrawing();
1843
    }
1843
    }
1844
1844
1845
    if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface);
1845
    if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface);
1846
    softsurface_blitBuffer((uint32_t*) sdl_surface->pixels, sdl_surface->format->BitsPerPixel);
1846
    softsurface_blitBuffer((uint32_t*) sdl_surface->pixels, sdl_surface->format->BitsPerPixel);
1847
    if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface);
1847
    if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface);
1848
1848
1849
    if (SDL_UpdateWindowSurface(sdl_window))
1849
    if (SDL_UpdateWindowSurface(sdl_window))
1850
    {
1850
    {
1851
        // If a fullscreen X11 window is minimized then this may be required.
1851
        // If a fullscreen X11 window is minimized then this may be required.
1852
        // FIXME: What to do if this fails...
1852
        // FIXME: What to do if this fails...
1853
        sdl_surface = SDL_GetWindowSurface(sdl_window);
1853
        sdl_surface = SDL_GetWindowSurface(sdl_window);
1854
        SDL_UpdateWindowSurface(sdl_window);
1854
        SDL_UpdateWindowSurface(sdl_window);
1855
    }
1855
    }
1856
}
1856
}
1857
#endif
1857
#endif
1858
//
1858
//
1859
// setpalette() -- set palette values
1859
// setpalette() -- set palette values
1860
//
1860
//
1861
int32_t videoUpdatePalette(int32_t start, int32_t num)
1861
int32_t videoUpdatePalette(int32_t start, int32_t num)
1862
{
1862
{
1863
    UNREFERENCED_PARAMETER(start);
1863
    UNREFERENCED_PARAMETER(start);
1864
    UNREFERENCED_PARAMETER(num);
1864
    UNREFERENCED_PARAMETER(num);
1865
1865
1866
    if (bpp > 8)
1866
    if (bpp > 8)
1867
        return 0;  // no palette in opengl
1867
        return 0;  // no palette in opengl
1868
1868
1869
#ifdef USE_OPENGL
1869
#ifdef USE_OPENGL
1870
    if (!nogl)
1870
    if (!nogl)
1871
        glsurface_setPalette(curpalettefaded);
1871
        glsurface_setPalette(curpalettefaded);
1872
    else
1872
    else
1873
#endif
1873
#endif
1874
    {
1874
    {
1875
        if (sdl_surface)
1875
        if (sdl_surface)
1876
            softsurface_setPalette(curpalettefaded,
1876
            softsurface_setPalette(curpalettefaded,
1877
                                   sdl_surface->format->Rmask,
1877
                                   sdl_surface->format->Rmask,
1878
                                   sdl_surface->format->Gmask,
1878
                                   sdl_surface->format->Gmask,
1879
                                   sdl_surface->format->Bmask);
1879
                                   sdl_surface->format->Bmask);
1880
    }
1880
    }
1881
1881
1882
    return 0;
1882
    return 0;
1883
}
1883
}
1884
1884
1885
//
1885
//
1886
// setgamma
1886
// setgamma
1887
//
1887
//
1888
int32_t videoSetGamma(void)
1888
int32_t videoSetGamma(void)
1889
{
1889
{
1890
    if (novideo)
1890
    if (novideo)
1891
        return 0;
1891
        return 0;
1892
1892
1893
    int32_t i;
1893
    int32_t i;
1894
    uint16_t gammaTable[768];
1894
    uint16_t gammaTable[768];
1895
    float gamma = max(0.1f, min(4.f, g_videoGamma));
1895
    float gamma = max(0.1f, min(4.f, g_videoGamma));
1896
    float contrast = max(0.1f, min(3.f, g_videoContrast));
1896
    float contrast = max(0.1f, min(3.f, g_videoContrast));
1897
    float bright = max(-0.8f, min(0.8f, g_videoBrightness));
1897
    float bright = max(-0.8f, min(0.8f, g_videoBrightness));
1898
1898
1899
    float invgamma = 1.f / gamma;
1899
    float invgamma = 1.f / gamma;
1900
    float norm = powf(255.f, invgamma - 1.f);
1900
    float norm = powf(255.f, invgamma - 1.f);
1901
1901
1902
    if (lastvidgcb[0] == gamma && lastvidgcb[1] == contrast && lastvidgcb[2] == bright)
1902
    if (lastvidgcb[0] == gamma && lastvidgcb[1] == contrast && lastvidgcb[2] == bright)
1903
        return 0;
1903
        return 0;
1904
1904
1905
    // This formula is taken from Doomsday
1905
    // This formula is taken from Doomsday
1906
1906
1907
    for (i = 0; i < 256; i++)
1907
    for (i = 0; i < 256; i++)
1908
    {
1908
    {
1909
        float val = i * contrast - (contrast - 1.f) * 127.f;
1909
        float val = i * contrast - (contrast - 1.f) * 127.f;
1910
        if (gamma != 1.f)
1910
        if (gamma != 1.f)
1911
            val = powf(val, invgamma) / norm;
1911
            val = powf(val, invgamma) / norm;
1912
1912
1913
        val += bright * 128.f;
1913
        val += bright * 128.f;
1914
1914
1915
        gammaTable[i] = gammaTable[i + 256] = gammaTable[i + 512] = (uint16_t)max(0.f, min(65535.f, val * 256.f));
1915
        gammaTable[i] = gammaTable[i + 256] = gammaTable[i + 512] = (uint16_t)max(0.f, min(65535.f, val * 256.f));
1916
    }
1916
    }
1917
1917
1918
#if SDL_MAJOR_VERSION == 1
1918
#if SDL_MAJOR_VERSION == 1
1919
    i = SDL_SetGammaRamp(&gammaTable[0], &gammaTable[256], &gammaTable[512]);
1919
    i = SDL_SetGammaRamp(&gammaTable[0], &gammaTable[256], &gammaTable[512]);
1920
    if (i != -1)
1920
    if (i != -1)
1921
#else
1921
#else
1922
    i = INT32_MIN;
1922
    i = INT32_MIN;
1923
1923
1924
    if (sdl_window)
1924
    if (sdl_window)
1925
        i = SDL_SetWindowGammaRamp(sdl_window, &gammaTable[0], &gammaTable[256], &gammaTable[512]);
1925
        i = SDL_SetWindowGammaRamp(sdl_window, &gammaTable[0], &gammaTable[256], &gammaTable[512]);
1926
1926
1927
    if (i < 0)
1927
    if (i < 0)
1928
    {
1928
    {
1929
#ifndef __ANDROID__  // Don't do this check, it is really supported, TODO
1929
#ifndef __ANDROID__  // Don't do this check, it is really supported, TODO
1930
/*
1930
/*
1931
        if (i != INT32_MIN)
1931
        if (i != INT32_MIN)
1932
            initprintf("Unable to set gamma: SDL_SetWindowGammaRamp failed: %s\n", SDL_GetError());
1932
            initprintf("Unable to set gamma: SDL_SetWindowGammaRamp failed: %s\n", SDL_GetError());
1933
*/
1933
*/
1934
#endif
1934
#endif
1935
1935
1936
        OSD_Printf("videoSetGamma(): %s\n", SDL_GetError());
1936
        OSD_Printf("videoSetGamma(): %s\n", SDL_GetError());
1937
1937
1938
#ifndef EDUKE32_GLES
1938
#ifndef EDUKE32_GLES
1939
#if SDL_MAJOR_VERSION == 1
1939
#if SDL_MAJOR_VERSION == 1
1940
        SDL_SetGammaRamp(&sysgamma[0][0], &sysgamma[1][0], &sysgamma[2][0]);
1940
        SDL_SetGammaRamp(&sysgamma[0][0], &sysgamma[1][0], &sysgamma[2][0]);
1941
#else
1941
#else
1942
1942
1943
        if (sdl_window)
1943
        if (sdl_window)
1944
            SDL_SetWindowGammaRamp(sdl_window, &sysgamma[0][0], &sysgamma[1][0], &sysgamma[2][0]);
1944
            SDL_SetWindowGammaRamp(sdl_window, &sysgamma[0][0], &sysgamma[1][0], &sysgamma[2][0]);
1945
#endif
1945
#endif
1946
        gammabrightness = 0;
1946
        gammabrightness = 0;
1947
#endif
1947
#endif
1948
    }
1948
    }
1949
    else
1949
    else
1950
#endif
1950
#endif
1951
    {
1951
    {
1952
        lastvidgcb[0] = gamma;
1952
        lastvidgcb[0] = gamma;
1953
        lastvidgcb[1] = contrast;
1953
        lastvidgcb[1] = contrast;
1954
        lastvidgcb[2] = bright;
1954
        lastvidgcb[2] = bright;
1955
1955
1956
        gammabrightness = 1;
1956
        gammabrightness = 1;
1957
    }
1957
    }
1958
1958
1959
    return i;
1959
    return i;
1960
}
1960
}
1961
1961
1962
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
1962
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
1963
extern "C" struct sdlappicon sdlappicon;
1963
extern "C" struct sdlappicon sdlappicon;
1964
static inline SDL_Surface *loadappicon(void)
1964
static inline SDL_Surface *loadappicon(void)
1965
{
1965
{
1966
    SDL_Surface *surf = SDL_CreateRGBSurfaceFrom((void *)sdlappicon.pixels, sdlappicon.width, sdlappicon.height, 32,
1966
    SDL_Surface *surf = SDL_CreateRGBSurfaceFrom((void *)sdlappicon.pixels, sdlappicon.width, sdlappicon.height, 32,
1967
                                                 sdlappicon.width * 4, 0xffl, 0xff00l, 0xff0000l, 0xff000000l);
1967
                                                 sdlappicon.width * 4, 0xffl, 0xff00l, 0xff0000l, 0xff000000l);
1968
    return surf;
1968
    return surf;
1969
}
1969
}
1970
#endif
1970
#endif
1971
1971
1972
//
1972
//
1973
//
1973
//
1974
// ---------------------------------------
1974
// ---------------------------------------
1975
//
1975
//
1976
// Miscellany
1976
// Miscellany
1977
//
1977
//
1978
// ---------------------------------------
1978
// ---------------------------------------
1979
//
1979
//
1980
//
1980
//
1981
1981
1982
int32_t handleevents_peekkeys(void)
1982
int32_t handleevents_peekkeys(void)
1983
{
1983
{
1984
    SDL_PumpEvents();
1984
    SDL_PumpEvents();
1985
1985
1986
#if SDL_MAJOR_VERSION==1
1986
#if SDL_MAJOR_VERSION==1
1987
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN));
1987
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN));
1988
#else
1988
#else
1989
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN);
1989
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN);
1990
#endif
1990
#endif
1991
}
1991
}
1992
1992
1993
void handleevents_updatemousestate(uint8_t state)
1993
void handleevents_updatemousestate(uint8_t state)
1994
{
1994
{
1995
    g_mouseClickState = state == SDL_RELEASED ? MOUSE_RELEASED : MOUSE_PRESSED;
1995
    g_mouseClickState = state == SDL_RELEASED ? MOUSE_RELEASED : MOUSE_PRESSED;
1996
}
1996
}
1997
1997
1998
1998
1999
//
1999
//
2000
// handleevents() -- process the SDL message queue
2000
// handleevents() -- process the SDL message queue
2001
//   returns !0 if there was an important event worth checking (like quitting)
2001
//   returns !0 if there was an important event worth checking (like quitting)
2002
//
2002
//
2003
2003
2004
int32_t handleevents_sdlcommon(SDL_Event *ev)
2004
int32_t handleevents_sdlcommon(SDL_Event *ev)
2005
{
2005
{
2006
    switch (ev->type)
2006
    switch (ev->type)
2007
    {
2007
    {
2008
#if !defined EDUKE32_IOS
2008
#if !defined EDUKE32_IOS
2009
        case SDL_MOUSEMOTION:
2009
        case SDL_MOUSEMOTION:
2010
#ifndef GEKKO
2010
#ifndef GEKKO
2011
            g_mouseAbs.x = ev->motion.x;
2011
            g_mouseAbs.x = ev->motion.x;
2012
            g_mouseAbs.y = ev->motion.y;
2012
            g_mouseAbs.y = ev->motion.y;
2013
            fallthrough__;
2013
            fallthrough__;
2014
#endif
2014
#endif
2015
        case SDL_JOYBALLMOTION:
2015
        case SDL_JOYBALLMOTION:
2016
            // SDL <VER> doesn't handle relative mouse movement correctly yet as the cursor still clips to the
2016
            // SDL <VER> doesn't handle relative mouse movement correctly yet as the cursor still clips to the
2017
            // screen edges
2017
            // screen edges
2018
            // so, we call SDL_WarpMouse() to center the cursor and ignore the resulting motion event that occurs
2018
            // so, we call SDL_WarpMouse() to center the cursor and ignore the resulting motion event that occurs
2019
            //  <VER> is 1.3 for PK, 1.2 for tueidj
2019
            //  <VER> is 1.3 for PK, 1.2 for tueidj
2020
            if (appactive && g_mouseGrabbed)
2020
            if (appactive && g_mouseGrabbed)
2021
            {
2021
            {
2022
# if SDL_MAJOR_VERSION==1
2022
# if SDL_MAJOR_VERSION==1
2023
                if (ev->motion.x != xdim >> 1 || ev->motion.y != ydim >> 1)
2023
                if (ev->motion.x != xdim >> 1 || ev->motion.y != ydim >> 1)
2024
# endif
2024
# endif
2025
                {
2025
                {
2026
                    g_mousePos.x += ev->motion.xrel;
2026
                    g_mousePos.x += ev->motion.xrel;
2027
                    g_mousePos.y += ev->motion.yrel;
2027
                    g_mousePos.y += ev->motion.yrel;
2028
# if SDL_MAJOR_VERSION==1
2028
# if SDL_MAJOR_VERSION==1
2029
                    SDL_WarpMouse(xdim>>1, ydim>>1);
2029
                    SDL_WarpMouse(xdim>>1, ydim>>1);
2030
# endif
2030
# endif
2031
                }
2031
                }
2032
            }
2032
            }
2033
            break;
2033
            break;
2034
2034
2035
        case SDL_MOUSEBUTTONDOWN:
2035
        case SDL_MOUSEBUTTONDOWN:
2036
        case SDL_MOUSEBUTTONUP:
2036
        case SDL_MOUSEBUTTONUP:
2037
        {
2037
        {
2038
            int32_t j;
2038
            int32_t j;
2039
2039
2040
            // some of these get reordered to match winlayer
2040
            // some of these get reordered to match winlayer
2041
            switch (ev->button.button)
2041
            switch (ev->button.button)
2042
            {
2042
            {
2043
                default: j = -1; break;
2043
                default: j = -1; break;
2044
                case SDL_BUTTON_LEFT: j = 0; handleevents_updatemousestate(ev->button.state); break;
2044
                case SDL_BUTTON_LEFT: j = 0; handleevents_updatemousestate(ev->button.state); break;
2045
                case SDL_BUTTON_RIGHT: j = 1; break;
2045
                case SDL_BUTTON_RIGHT: j = 1; break;
2046
                case SDL_BUTTON_MIDDLE: j = 2; break;
2046
                case SDL_BUTTON_MIDDLE: j = 2; break;
2047
2047
2048
#if SDL_MAJOR_VERSION == 1
2048
#if SDL_MAJOR_VERSION == 1
2049
                case SDL_BUTTON_WHEELUP:    // 4
2049
                case SDL_BUTTON_WHEELUP:    // 4
2050
                case SDL_BUTTON_WHEELDOWN:  // 5
2050
                case SDL_BUTTON_WHEELDOWN:  // 5
2051
                    j = ev->button.button;
2051
                    j = ev->button.button;
2052
                    break;
2052
                    break;
2053
#endif
2053
#endif
2054
                /* Thumb buttons. */
2054
                /* Thumb buttons. */
2055
#if SDL_MAJOR_VERSION==1
2055
#if SDL_MAJOR_VERSION==1
2056
                // NOTE: SDL1 does have SDL_BUTTON_X1, but that's not what is
2056
                // NOTE: SDL1 does have SDL_BUTTON_X1, but that's not what is
2057
                // generated. (Only tested on Linux and Windows.)
2057
                // generated. (Only tested on Linux and Windows.)
2058
                case 8: j = 3; break;
2058
                case 8: j = 3; break;
2059
                case 9: j = 6; break;
2059
                case 9: j = 6; break;
2060
#else
2060
#else
2061
                // On SDL2/Windows and SDL >= 2.0.?/Linux, everything is as it should be.
2061
                // On SDL2/Windows and SDL >= 2.0.?/Linux, everything is as it should be.
2062
                // If anyone cares about old versions of SDL2 on Linux, patches welcome.
2062
                // If anyone cares about old versions of SDL2 on Linux, patches welcome.
2063
                case SDL_BUTTON_X1: j = 3; break;
2063
                case SDL_BUTTON_X1: j = 3; break;
2064
                case SDL_BUTTON_X2: j = 6; break;
2064
                case SDL_BUTTON_X2: j = 6; break;
2065
#endif
2065
#endif
2066
            }
2066
            }
2067
2067
2068
            if (j < 0)
2068
            if (j < 0)
2069
                break;
2069
                break;
2070
2070
2071
            if (ev->button.state == SDL_PRESSED)
2071
            if (ev->button.state == SDL_PRESSED)
2072
                g_mouseBits |= (1 << j);
2072
                g_mouseBits |= (1 << j);
2073
            else
2073
            else
2074
#if SDL_MAJOR_VERSION==1
2074
#if SDL_MAJOR_VERSION==1
2075
                if (j != SDL_BUTTON_WHEELUP && j != SDL_BUTTON_WHEELDOWN)
2075
                if (j != SDL_BUTTON_WHEELUP && j != SDL_BUTTON_WHEELDOWN)
2076
#endif
2076
#endif
2077
                g_mouseBits &= ~(1 << j);
2077
                g_mouseBits &= ~(1 << j);
2078
2078
2079
            if (g_mouseCallback)
2079
            if (g_mouseCallback)
2080
                g_mouseCallback(j+1, ev->button.state == SDL_PRESSED);
2080
                g_mouseCallback(j+1, ev->button.state == SDL_PRESSED);
2081
            break;
2081
            break;
2082
        }
2082
        }
2083
#else
2083
#else
2084
# if SDL_MAJOR_VERSION != 1
2084
# if SDL_MAJOR_VERSION != 1
2085
        case SDL_FINGERUP:
2085
        case SDL_FINGERUP:
2086
            g_mouseClickState = MOUSE_RELEASED;
2086
            g_mouseClickState = MOUSE_RELEASED;
2087
            break;
2087
            break;
2088
        case SDL_FINGERDOWN:
2088
        case SDL_FINGERDOWN:
2089
            g_mouseClickState = MOUSE_PRESSED;
2089
            g_mouseClickState = MOUSE_PRESSED;
2090
        case SDL_FINGERMOTION:
2090
        case SDL_FINGERMOTION:
2091
            g_mouseAbs.x = Blrintf(ev->tfinger.x * xdim);
2091
            g_mouseAbs.x = Blrintf(ev->tfinger.x * xdim);
2092
            g_mouseAbs.y = Blrintf(ev->tfinger.y * ydim);
2092
            g_mouseAbs.y = Blrintf(ev->tfinger.y * ydim);
2093
            break;
2093
            break;
2094
# endif
2094
# endif
2095
#endif
2095
#endif
2096
2096
2097
        case SDL_JOYAXISMOTION:
2097
        case SDL_JOYAXISMOTION:
2098
#if SDL_MAJOR_VERSION >= 2
2098
#if SDL_MAJOR_VERSION >= 2
2099
            if (joystick.isGameController)
2099
            if (joystick.isGameController)
2100
                break;
2100
                break;
2101
            fallthrough__;
2101
            fallthrough__;
2102
        case SDL_CONTROLLERAXISMOTION:
2102
        case SDL_CONTROLLERAXISMOTION:
2103
#endif
2103
#endif
2104
            if (appactive && ev->jaxis.axis < joystick.numAxes)
2104
            if (appactive && ev->jaxis.axis < joystick.numAxes)
2105
            {
2105
            {
2106
                joystick.pAxis[ev->jaxis.axis] = ev->jaxis.value;
2106
                joystick.pAxis[ev->jaxis.axis] = ev->jaxis.value;
2107
                int32_t const scaledValue = ev->jaxis.value * 10000 / 32767;
2107
                int32_t const scaledValue = ev->jaxis.value * 10000 / 32767;
2108
                if ((scaledValue < joydead[ev->jaxis.axis]) &&
2108
                if ((scaledValue < joydead[ev->jaxis.axis]) &&
2109
                    (scaledValue > -joydead[ev->jaxis.axis]))
2109
                    (scaledValue > -joydead[ev->jaxis.axis]))
2110
                    joystick.pAxis[ev->jaxis.axis] = 0;
2110
                    joystick.pAxis[ev->jaxis.axis] = 0;
2111
                else if (scaledValue >= joysatur[ev->jaxis.axis])
2111
                else if (scaledValue >= joysatur[ev->jaxis.axis])
2112
                    joystick.pAxis[ev->jaxis.axis] = 32767;
2112
                    joystick.pAxis[ev->jaxis.axis] = 32767;
2113
                else if (scaledValue <= -joysatur[ev->jaxis.axis])
2113
                else if (scaledValue <= -joysatur[ev->jaxis.axis])
2114
                    joystick.pAxis[ev->jaxis.axis] = -32767;
2114
                    joystick.pAxis[ev->jaxis.axis] = -32767;
2115
                else
2115
                else
2116
                    joystick.pAxis[ev->jaxis.axis] = joystick.pAxis[ev->jaxis.axis] * 10000 / joysatur[ev->jaxis.axis];
2116
                    joystick.pAxis[ev->jaxis.axis] = joystick.pAxis[ev->jaxis.axis] * 10000 / joysatur[ev->jaxis.axis];
2117
            }
2117
            }
2118
            break;
2118
            break;
2119
2119
2120
        case SDL_JOYHATMOTION:
2120
        case SDL_JOYHATMOTION:
2121
        {
2121
        {
2122
            int32_t hatvals[16] = {
2122
            int32_t hatvals[16] = {
2123
                -1,     // centre
2123
                -1,     // centre
2124
                0,      // up 1
2124
                0,      // up 1
2125
                9000,   // right 2
2125
                9000,   // right 2
2126
                4500,   // up+right 3
2126
                4500,   // up+right 3
2127
                18000,  // down 4
2127
                18000,  // down 4
2128
                -1,     // down+up!! 5
2128
                -1,     // down+up!! 5
2129
                13500,  // down+right 6
2129
                13500,  // down+right 6
2130
                -1,     // down+right+up!! 7
2130
                -1,     // down+right+up!! 7
2131
                27000,  // left 8
2131
                27000,  // left 8
2132
                27500,  // left+up 9
2132
                27500,  // left+up 9
2133
                -1,     // left+right!! 10
2133
                -1,     // left+right!! 10
2134
                -1,     // left+right+up!! 11
2134
                -1,     // left+right+up!! 11
2135
                22500,  // left+down 12
2135
                22500,  // left+down 12
2136
                -1,     // left+down+up!! 13
2136
                -1,     // left+down+up!! 13
2137
                -1,     // left+down+right!! 14
2137
                -1,     // left+down+right!! 14
2138
                -1,     // left+down+right+up!! 15
2138
                -1,     // left+down+right+up!! 15
2139
            };
2139
            };
2140
            if (appactive && ev->jhat.hat < joystick.numHats)
2140
            if (appactive && ev->jhat.hat < joystick.numHats)
2141
                joystick.pHat[ev->jhat.hat] = hatvals[ev->jhat.value & 15];
2141
                joystick.pHat[ev->jhat.hat] = hatvals[ev->jhat.value & 15];
2142
            break;
2142
            break;
2143
        }
2143
        }
2144
2144
2145
        case SDL_JOYBUTTONDOWN:
2145
        case SDL_JOYBUTTONDOWN:
2146
        case SDL_JOYBUTTONUP:
2146
        case SDL_JOYBUTTONUP:
2147
#if SDL_MAJOR_VERSION >= 2
2147
#if SDL_MAJOR_VERSION >= 2
2148
            if (joystick.isGameController)
2148
            if (joystick.isGameController)
2149
                break;
2149
                break;
2150
            fallthrough__;
2150
            fallthrough__;
2151
        case SDL_CONTROLLERBUTTONDOWN:
2151
        case SDL_CONTROLLERBUTTONDOWN:
2152
        case SDL_CONTROLLERBUTTONUP:
2152
        case SDL_CONTROLLERBUTTONUP:
2153
#endif
2153
#endif
2154
            if (appactive && ev->jbutton.button < joystick.numButtons)
2154
            if (appactive && ev->jbutton.button < joystick.numButtons)
2155
            {
2155
            {
2156
                if (ev->jbutton.state == SDL_PRESSED)
2156
                if (ev->jbutton.