Subversion Repositories eduke32

Rev

Rev 8728 | Details | Compare with Previous | Last modification | View Log | RSS feed

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