Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
5 Plagman 1
// SDL interface layer
2
// for the Build Engine
2456 hendricks2 3
// by Jonathon Fowler (jf@jonof.id.au)
5 Plagman 4
//
4074 hendricks2 5
// Use SDL 1.2 or 2.0 from http://www.libsdl.org
5 Plagman 6
 
3116 hendricks2 7
#define __STDC_FORMAT_MACROS
4540 hendricks2 8
#ifndef __STDC_LIMIT_MACROS
3116 hendricks2 9
#define __STDC_LIMIT_MACROS
4540 hendricks2 10
#endif
5 Plagman 11
#include <stdlib.h>
2985 helixhorne 12
#include <math.h>  // pow
1485 helixhorne 13
#include <signal.h>
710 terminx 14
#include "sdl_inc.h"
5 Plagman 15
#include "compat.h"
4648 hendricks2 16
#include "renderlayer.h"
5 Plagman 17
#include "cache1d.h"
2222 helixhorne 18
//#include "pragmas.h"
5 Plagman 19
#include "a.h"
20
#include "build.h"
21
#include "osd.h"
4890 terminx 22
#include "engine_priv.h"
5 Plagman 23
 
24
#ifdef USE_OPENGL
25
# include "glbuild.h"
26
#endif
27
 
3221 hendricks2 28
#if defined _WIN32
29
# define WIN32_LEAN_AND_MEAN
30
# include <windows.h>
31
# include "winbits.h"
4548 hendricks2 32
#endif
33
#if defined __APPLE__
5 Plagman 34
# include "osxbits.h"
2861 helixhorne 35
# include <mach/mach.h>
36
# include <mach/mach_time.h>
4548 hendricks2 37
#endif
38
#if defined HAVE_GTK2
5 Plagman 39
# include "gtkbits.h"
4548 hendricks2 40
#endif
4749 terminx 41
#ifdef __ANDROID__
4852 hendricks2 42
# include <android/log.h>
1935 helixhorne 43
#endif
4819 hendricks2 44
#if defined GEKKO
4820 hendricks2 45
# include "wiibits.h"
46
# include <ogc/lwp.h>
47
# include <ogc/lwp_watchdog.h>
4819 hendricks2 48
# define SDL_DISABLE_8BIT_BUFFER
49
#endif
1935 helixhorne 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*/;
4819 hendricks2 76
#if !defined SDL_DISABLE_8BIT_BUFFER
4080 hendricks2 77
static SDL_Surface *sdl_buffersurface=NULL;
4819 hendricks2 78
#else
79
# define sdl_buffersurface sdl_surface
80
#endif
4432 terminx 81
 
2777 helixhorne 82
#if SDL_MAJOR_VERSION==2
4089 hendricks2 83
static SDL_Palette *sdl_palptr=NULL;
84
static SDL_Window *sdl_window=NULL;
85
static SDL_GLContext sdl_context=NULL;
4253 hendricks2 86
static SDL_Texture *sdl_texture=NULL;
87
static SDL_Renderer *sdl_renderer=NULL;
2777 helixhorne 88
#endif
4432 terminx 89
 
2023 helixhorne 90
int32_t xres=-1, yres=-1, bpp=0, fullscreen=0, bytesperline;
618 terminx 91
intptr_t frameplace=0;
1205 terminx 92
int32_t lockcount=0;
5 Plagman 93
char modechange=1;
94
char offscreenrendering=0;
95
char videomodereset = 0;
4904 terminx 96
int32_t nofog=0;
1205 terminx 97
static uint16_t sysgamma[3][256];
98
extern int32_t curbrightness, gammabrightness;
5 Plagman 99
#ifdef USE_OPENGL
100
// OpenGL stuff
1036 terminx 101
char nogl=0;
4102 hendricks2 102
static int32_t vsync_render=0;
5 Plagman 103
#endif
104
 
2222 helixhorne 105
// last gamma, contrast, brightness
106
static float lastvidgcb[3];
107
 
2119 helixhorne 108
//#define KEY_PRINT_DEBUG
109
 
4075 hendricks2 110
#include "sdlkeytrans.c"
5 Plagman 111
 
1762 terminx 112
static SDL_Surface *appicon = NULL;
4852 hendricks2 113
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
1762 terminx 114
static SDL_Surface *loadappicon(void);
4644 hendricks2 115
#endif
5 Plagman 116
 
1658 terminx 117
static mutex_t m_initprintf;
118
 
1716 plagman 119
// Joystick dead and saturation zones
120
uint16_t *joydead, *joysatur;
121
 
3219 hendricks2 122
#ifdef _WIN32
4774 hendricks2 123
# if SDL_MAJOR_VERSION != 1
3219 hendricks2 124
//
4084 hendricks2 125
// win_gethwnd() -- gets the window handle
126
//
127
HWND win_gethwnd(void)
128
{
129
    struct SDL_SysWMinfo wmInfo;
130
    SDL_VERSION(&wmInfo.version);
131
 
132
    if (SDL_GetWindowWMInfo(sdl_window, &wmInfo) != SDL_TRUE)
133
        return 0;
134
 
135
    if (wmInfo.subsystem == SDL_SYSWM_WINDOWS)
136
        return wmInfo.info.win.window;
137
 
138
    initprintf("win_gethwnd: Unknown WM subsystem?!\n");
139
 
140
    return 0;
141
}
4774 hendricks2 142
# endif
4084 hendricks2 143
//
3219 hendricks2 144
// win_gethinstance() -- gets the application instance
145
//
3278 hendricks2 146
HINSTANCE win_gethinstance(void)
3219 hendricks2 147
{
3278 hendricks2 148
    return (HINSTANCE)GetModuleHandle(NULL);
3219 hendricks2 149
}
150
#endif
151
 
4469 hendricks2 152
 
4558 hendricks2 153
int32_t wm_msgbox(const char *name, const char *fmt, ...)
5 Plagman 154
{
298 terminx 155
    char buf[2048];
109 terminx 156
    va_list va;
5 Plagman 157
 
659 plagman 158
    UNREFERENCED_PARAMETER(name);
159
 
109 terminx 160
    va_start(va,fmt);
4120 helixhorne 161
    vsnprintf(buf,sizeof(buf),fmt,va);
109 terminx 162
    va_end(va);
5 Plagman 163
 
4942 hendricks2 164
#if defined EDUKE32_OSX
109 terminx 165
    return osx_msgbox(name, buf);
5 Plagman 166
#elif defined HAVE_GTK2
109 terminx 167
    if (gtkbuild_msgbox(name, buf) >= 0) return 1;
4254 hendricks2 168
#elif defined _WIN32
169
    MessageBox(win_gethwnd(),buf,name,MB_OK|MB_TASKMODAL);
170
    return 0;
4852 hendricks2 171
#elif defined EDUKE32_TOUCH_DEVICES
4440 terminx 172
    initprintf("wm_msgbox called. Message: %s: %s",name,buf);
173
    return 0;
4085 hendricks2 174
#elif SDL_MAJOR_VERSION==2
4120 helixhorne 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
    {
4469 hendricks2 179
        size_t i;
180
        for (i=0; i<sizeof(buf); i++)
4120 helixhorne 181
            if (buf[i] == '\t')
182
                buf[i] = ' ';
183
    }
184
# endif
4085 hendricks2 185
    return SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, name, buf, NULL);
4825 hendricks2 186
#elif defined GEKKO
187
    puts(buf);
188
    return 0;
5 Plagman 189
#endif
109 terminx 190
    puts(buf);
191
    puts("   (press Return or Enter to continue)");
192
    getchar();
5 Plagman 193
 
109 terminx 194
    return 0;
5 Plagman 195
}
196
 
4767 hendricks2 197
#if SDL_MAJOR_VERSION != 1
4558 hendricks2 198
int32_t wm_ynbox(const char *name, const char *fmt, ...)
5 Plagman 199
{
298 terminx 200
    char buf[2048];
109 terminx 201
    va_list va;
5 Plagman 202
 
659 plagman 203
    UNREFERENCED_PARAMETER(name);
204
 
109 terminx 205
    va_start(va,fmt);
206
    vsprintf(buf,fmt,va);
207
    va_end(va);
5 Plagman 208
 
4942 hendricks2 209
#if defined EDUKE32_OSX
109 terminx 210
    return osx_ynbox(name, buf);
5 Plagman 211
#elif defined HAVE_GTK2
4476 helixhorne 212
    {
213
        int32_t r = gtkbuild_ynbox(name, buf);
4803 hendricks2 214
 
215
        return r >= 0 ? r : 0;
4476 helixhorne 216
    }
4254 hendricks2 217
#elif defined _WIN32
4476 helixhorne 218
    return (MessageBox(win_gethwnd(),buf,name,MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL) == IDYES);
4852 hendricks2 219
#elif defined EDUKE32_TOUCH_DEVICES
4440 terminx 220
    initprintf("wm_ynbox called, this is bad! Message: %s: %s",name,buf);
221
    initprintf("Returning false..");
222
    return 0;
4749 terminx 223
#else
4469 hendricks2 224
    {
4476 helixhorne 225
        int32_t r = -1;
226
 
4469 hendricks2 227
        const SDL_MessageBoxButtonData buttons[] = {
228
            {
229
                SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
230
                0,
231
                "No"
232
            },{
233
                SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
234
                1,
235
                "Yes"
236
            },
237
        };
238
 
239
        SDL_MessageBoxData data = {
240
            SDL_MESSAGEBOX_INFORMATION,
241
            NULL, /* no parent window */
242
            name,
243
            buf,
244
            2,
245
            buttons,
246
            NULL /* Default color scheme */
247
        };
248
 
249
        SDL_ShowMessageBox(&data, &r);
250
 
251
        return r;
252
    }
5 Plagman 253
#endif
254
}
4767 hendricks2 255
#endif
5 Plagman 256
 
4558 hendricks2 257
void wm_setapptitle(const char *name)
5 Plagman 258
{
4852 hendricks2 259
#ifndef EDUKE32_TOUCH_DEVICES
4749 terminx 260
    if (name != apptitle)
261
        Bstrncpyz(apptitle, name, sizeof(apptitle));
262
 
263
#if !defined(__APPLE__)
4774 hendricks2 264
    if (!appicon)
265
        appicon = loadappicon();
4440 terminx 266
#endif
267
 
2777 helixhorne 268
#if SDL_MAJOR_VERSION == 1
109 terminx 269
    SDL_WM_SetCaption(apptitle, NULL);
4749 terminx 270
 
4774 hendricks2 271
    if (appicon && sdl_surface)
4749 terminx 272
        SDL_WM_SetIcon(appicon, 0);
2777 helixhorne 273
#else
274
    SDL_SetWindowTitle(sdl_window, apptitle);
4749 terminx 275
 
276
    if (appicon)
277
        SDL_SetWindowIcon(sdl_window, appicon);
2777 helixhorne 278
#endif
5 Plagman 279
 
194 terminx 280
    startwin_settitle(apptitle);
4852 hendricks2 281
#else
282
    UNREFERENCED_PARAMETER(name);
4749 terminx 283
#endif
5 Plagman 284
}
285
 
286
//
287
//
288
// ---------------------------------------
289
//
290
// System
291
//
292
// ---------------------------------------
293
//
294
//
295
 
4749 terminx 296
static void attach_debugger_here(void) {}
297
 
298
/* XXX: libexecinfo could be used on systems without gnu libc. */
4852 hendricks2 299
#if !defined _WIN32 && defined __GNUC__ && !defined __OpenBSD__ && !(defined __APPLE__ && defined __BIG_ENDIAN__) && !defined GEKKO && !defined EDUKE32_TOUCH_DEVICES && !defined __OPENDINGUX__
4749 terminx 300
# define PRINTSTACKONSEGV 1
301
# include <execinfo.h>
4557 hendricks2 302
#endif
303
 
4749 terminx 304
static inline char grabmouse_low(char a);
305
 
306
static void sighandler(int signum)
307
{
308
    UNREFERENCED_PARAMETER(signum);
309
    //    if (signum==SIGSEGV)
310
    {
311
        grabmouse_low(0);
312
#if PRINTSTACKONSEGV
313
        {
314
            void *addr[32];
315
            int32_t errfd = fileno(stderr);
316
            int32_t n=backtrace(addr, ARRAY_SIZE(addr));
317
            backtrace_symbols_fd(addr, n, errfd);
318
        }
319
        // This is useful for attaching the debugger post-mortem. For those pesky
320
        // cases where the program runs through happily when inspected from the start.
321
        //        usleep(15000000);
322
#endif
323
        attach_debugger_here();
324
        app_crashhandler();
325
        uninitsystem();
326
        Bexit(8);
327
    }
328
}
329
 
4992 terminx 330
#ifdef __ANDROID__
331
int mobile_halted = 0;
332
#ifdef __cplusplus
333
extern "C"
334
{
335
#endif
336
void G_Shutdown(void);
337
#ifdef __cplusplus
338
}
339
#endif
340
 
341
int sdlayer_mobilefilter(void *userdata, SDL_Event *event)
342
{
343
    switch (event->type)
344
    {
345
        case SDL_APP_TERMINATING:
346
            // yes, this calls into the game, ugh
347
            G_Shutdown();
348
            return 0;
349
        case SDL_APP_LOWMEMORY:
350
            gltexinvalidatetype(INVALIDATE_ALL);
351
            return 0;
352
        case SDL_APP_WILLENTERBACKGROUND:
353
            mobile_halted = 1;
354
            return 0;
355
        case SDL_APP_DIDENTERBACKGROUND:
356
            // tear down video?
357
            return 0;
358
        case SDL_APP_WILLENTERFOREGROUND:
359
            // restore video?
360
            return 0;
361
        case SDL_APP_DIDENTERFOREGROUND:
362
            mobile_halted = 0;
363
            return 0;
364
        default:
365
            return 1;//!halt;
366
    }
367
}
368
#endif
369
 
4983 terminx 370
#ifdef _WIN32
371
int32_t WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int32_t nCmdShow)
372
#else
1205 terminx 373
int32_t main(int32_t argc, char *argv[])
4983 terminx 374
#endif
5 Plagman 375
{
1205 terminx 376
    int32_t r;
4749 terminx 377
 
3382 hendricks2 378
#ifdef USE_OPENGL
622 terminx 379
    char *argp;
109 terminx 380
 
4749 terminx 381
    if ((argp = Bgetenv("BUILD_NOFOG")) != NULL)
382
        nofog = Batol(argp);
4557 hendricks2 383
#endif
384
 
109 terminx 385
    buildkeytranslationtable();
386
 
4992 terminx 387
#ifndef __ANDROID__
4749 terminx 388
    signal(SIGSEGV, sighandler);
389
    signal(SIGILL, sighandler);  /* clang -fcatch-undefined-behavior uses an ill. insn */
390
    signal(SIGABRT, sighandler);
391
    signal(SIGFPE, sighandler);
4992 terminx 392
#else
393
    SDL_SetEventFilter(sdlayer_mobilefilter, NULL);
394
#endif
4447 Plagman 395
 
3221 hendricks2 396
#ifdef _WIN32
4983 terminx 397
    UNREFERENCED_PARAMETER(hInst);
398
    UNREFERENCED_PARAMETER(hPrevInst);
399
    UNREFERENCED_PARAMETER(lpCmdLine);
400
    UNREFERENCED_PARAMETER(nCmdShow);
401
 
4749 terminx 402
    win_open();
403
 
3221 hendricks2 404
    if (!CheckWinVersion())
405
    {
4749 terminx 406
        MessageBox(0, "This application requires Windows XP or better to run.", apptitle, MB_OK | MB_ICONSTOP);
3221 hendricks2 407
        return -1;
408
    }
4749 terminx 409
#elif defined(GEKKO)
4820 hendricks2 410
    wii_open();
4749 terminx 411
#elif defined(HAVE_GTK2)
412
    // Pre-initialize SDL video system in order to make sure XInitThreads() is called
413
    // before GTK starts talking to X11.
414
    SDL_Init(SDL_INIT_VIDEO);
415
    gtkbuild_init(&argc, &argv);
3221 hendricks2 416
#endif
417
 
194 terminx 418
    startwin_open();
3377 helixhorne 419
    maybe_redirect_outputs();
4749 terminx 420
    baselayer_init();
1736 helixhorne 421
 
4983 terminx 422
#ifdef _WIN32
423
    char *argvbuf;
424
    int32_t buildargc = win_buildargs(&argvbuf);
425
    const char **buildargv = (const char **) Bmalloc(sizeof(char *)*(buildargc+1));
426
    char *wp = argvbuf;
427
 
428
    for (int i=0; i<buildargc; i++, wp++)
429
    {
430
        buildargv[i] = wp;
431
        while (*wp) wp++;
432
    }
433
    buildargv[buildargc] = NULL;
434
 
435
    r = app_main(buildargc, (const char **)buildargv);
436
#else
3583 helixhorne 437
    r = app_main(argc, (const char **)argv);
4983 terminx 438
#endif
5 Plagman 439
 
194 terminx 440
    startwin_close();
4749 terminx 441
 
3221 hendricks2 442
#ifdef _WIN32
443
    win_close();
4749 terminx 444
#elif defined(HAVE_GTK2)
445
    gtkbuild_exit(r);
3221 hendricks2 446
#endif
447
 
109 terminx 448
    return r;
5 Plagman 449
}
450
 
1820 terminx 451
#ifdef USE_OPENGL
4769 hendricks2 452
void setvsync(int32_t sync);
453
#if SDL_MAJOR_VERSION != 1
1205 terminx 454
void setvsync(int32_t sync)
889 terminx 455
{
4090 hendricks2 456
    if (vsync_render == sync) return;
457
    vsync_render = sync;
4102 hendricks2 458
 
4090 hendricks2 459
    if (sdl_context)
460
        SDL_GL_SetSwapInterval(vsync_render);
889 terminx 461
}
462
#endif
4769 hendricks2 463
#endif
5 Plagman 464
 
4767 hendricks2 465
int32_t sdlayer_checkversion(void);
466
#if SDL_MAJOR_VERSION != 1
4749 terminx 467
int32_t sdlayer_checkversion(void)
468
{
469
    SDL_version compiled;
4964 helixhorne 470
    SDL_version linked;
1485 helixhorne 471
 
4964 helixhorne 472
    SDL_GetVersion(&linked);
4749 terminx 473
    SDL_VERSION(&compiled);
3972 hendricks2 474
 
4749 terminx 475
    initprintf("Initializing SDL system interface "
476
               "(compiled against SDL version %d.%d.%d, found version %d.%d.%d)\n",
4964 helixhorne 477
               compiled.major, compiled.minor, compiled.patch, linked.major, linked.minor, linked.patch);
1712 helixhorne 478
 
4964 helixhorne 479
    if (SDL_VERSIONNUM(linked.major, linked.minor, linked.patch) < SDL_REQUIREDVERSION)
1485 helixhorne 480
    {
4749 terminx 481
        /*reject running under SDL versions older than what is stated in sdl_inc.h */
482
        initprintf("You need at least v%d.%d.%d of SDL to run this game\n",SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z);
483
        return -1;
1485 helixhorne 484
    }
4749 terminx 485
 
486
    return 0;
1485 helixhorne 487
}
488
 
5 Plagman 489
//
490
// initsystem() -- init SDL systems
491
//
1205 terminx 492
int32_t initsystem(void)
5 Plagman 493
{
4749 terminx 494
    const int sdlinitflags = SDL_INIT_VIDEO;
5 Plagman 495
 
1658 terminx 496
    mutex_init(&m_initprintf);
497
 
3221 hendricks2 498
#ifdef _WIN32
499
    win_init();
500
#endif
501
 
4749 terminx 502
    if (sdlayer_checkversion())
710 terminx 503
        return -1;
504
 
4749 terminx 505
    if (SDL_Init(sdlinitflags))
342 terminx 506
    {
1762 terminx 507
        initprintf("Initialization failed! (%s)\nNon-interactive mode enabled\n", SDL_GetError());
1810 plagman 508
        novideo = 1;
509
#ifdef USE_OPENGL
510
        nogl = 1;
511
#endif
109 terminx 512
    }
5 Plagman 513
 
109 terminx 514
    atexit(uninitsystem);
5 Plagman 515
 
109 terminx 516
    frameplace = 0;
517
    lockcount = 0;
5 Plagman 518
 
1762 terminx 519
    if (!novideo)
520
    {
4749 terminx 521
        const char *drvname = SDL_GetVideoDriver(0);
522
 
523
#ifdef USE_OPENGL
524
        if (loadgldriver(getenv("BUILD_GLDRV")))
2777 helixhorne 525
        {
4749 terminx 526
            initprintf("Failed loading OpenGL driver. GL modes will be unavailable.\n");
527
            nogl = 1;
2777 helixhorne 528
        }
5 Plagman 529
#endif
530
 
2777 helixhorne 531
        if (drvname)
532
            initprintf("Using \"%s\" video driver\n", drvname);
4749 terminx 533
 
534
        wm_setapptitle(apptitle);
2777 helixhorne 535
    }
5 Plagman 536
 
109 terminx 537
    return 0;
5 Plagman 538
}
4767 hendricks2 539
#endif
5 Plagman 540
 
541
 
542
//
543
// uninitsystem() -- uninit SDL systems
544
//
545
void uninitsystem(void)
546
{
109 terminx 547
    uninitinput();
548
    uninittimer();
5 Plagman 549
 
1544 terminx 550
    if (appicon)
1552 terminx 551
    {
1544 terminx 552
        SDL_FreeSurface(appicon);
1552 terminx 553
        appicon = NULL;
554
    }
1544 terminx 555
 
109 terminx 556
    SDL_Quit();
5 Plagman 557
 
3221 hendricks2 558
#ifdef _WIN32
559
    win_uninit();
560
#endif
561
 
5 Plagman 562
#ifdef USE_OPENGL
109 terminx 563
    unloadgldriver();
5 Plagman 564
#endif
565
}
566
 
567
 
568
//
4090 hendricks2 569
// system_getcvars() -- propagate any cvars that are read post-initialization
570
//
571
void system_getcvars(void)
572
{
4102 hendricks2 573
#ifdef USE_OPENGL
4090 hendricks2 574
    setvsync(vsync);
4102 hendricks2 575
#endif
4090 hendricks2 576
}
577
 
578
//
4555 hendricks2 579
// initprintf() -- prints a formatted string to the intitialization window
5 Plagman 580
//
581
void initprintf(const char *f, ...)
582
{
109 terminx 583
    va_list va;
1663 helixhorne 584
    char buf[2048];
5 Plagman 585
 
109 terminx 586
    va_start(va, f);
1663 helixhorne 587
    Bvsnprintf(buf, sizeof(buf), f, va);
109 terminx 588
    va_end(va);
5 Plagman 589
 
4555 hendricks2 590
    initputs(buf);
591
}
592
 
593
 
594
//
595
// initputs() -- prints a string to the intitialization window
596
//
597
void initputs(const char *buf)
598
{
599
    static char dabuf[2048];
600
 
4440 terminx 601
#ifdef __ANDROID__
602
    __android_log_print(ANDROID_LOG_INFO,"DUKE", "%s",buf);
603
#endif
4555 hendricks2 604
    OSD_Puts(buf);
1762 terminx 605
//    Bprintf("%s", buf);
109 terminx 606
 
1658 terminx 607
    mutex_lock(&m_initprintf);
1203 terminx 608
    if (Bstrlen(dabuf) + Bstrlen(buf) > 1022)
609
    {
610
        startwin_puts(dabuf);
611
        Bmemset(dabuf, 0, sizeof(dabuf));
612
    }
613
 
614
    Bstrcat(dabuf,buf);
615
 
1430 terminx 616
    if (flushlogwindow || Bstrlen(dabuf) > 768)
1203 terminx 617
    {
618
        startwin_puts(dabuf);
3219 hendricks2 619
#ifndef _WIN32
1203 terminx 620
        startwin_idle(NULL);
4086 hendricks2 621
#else
622
        handleevents();
3219 hendricks2 623
#endif
1203 terminx 624
        Bmemset(dabuf, 0, sizeof(dabuf));
625
    }
1658 terminx 626
    mutex_unlock(&m_initprintf);
5 Plagman 627
}
628
 
629
//
4555 hendricks2 630
// debugprintf() -- prints a formatted debug string to stderr
5 Plagman 631
//
632
void debugprintf(const char *f, ...)
633
{
1935 helixhorne 634
#if defined DEBUGGINGAIDS && !(defined __APPLE__ && defined __BIG_ENDIAN__)
109 terminx 635
    va_list va;
5 Plagman 636
 
109 terminx 637
    va_start(va,f);
638
    Bvfprintf(stderr, f, va);
639
    va_end(va);
661 plagman 640
#else
641
    UNREFERENCED_PARAMETER(f);
5 Plagman 642
#endif
643
}
644
 
645
 
646
//
647
//
648
// ---------------------------------------
649
//
650
// All things Input
651
//
652
// ---------------------------------------
653
//
654
//
655
 
4482 helixhorne 656
#ifdef _WIN32
657
static void switchlayout(const char *layout)
658
{
659
    char layoutname[KL_NAMELENGTH];
660
 
661
    GetKeyboardLayoutName(layoutname);
662
 
663
    if (!Bstrcmp(layoutname, layout))
664
        return;
665
 
666
    initprintf("Switching keyboard layout from %s to %s\n", layoutname, layout);
667
    LoadKeyboardLayout(layout, KLF_ACTIVATE|KLF_SETFORPROCESS|KLF_SUBSTITUTE_OK);
668
}
669
 
670
static void W_SetKeyboardLayoutUS(int32_t resetp)
671
{
672
    static char defaultlayoutname[KL_NAMELENGTH];
673
 
674
    if (!resetp)
675
    {
676
        static int done = 0;
677
 
678
        if (!done)
679
        {
680
            GetKeyboardLayoutName(defaultlayoutname);
681
            // 00000409 is "American English"
682
            switchlayout("00000409");
683
 
684
            done = 1;
685
        }
686
    }
687
    else if (defaultlayoutname[0])
688
    {
689
        switchlayout(defaultlayoutname);
690
    }
691
}
692
#endif
693
 
1205 terminx 694
// static int32_t joyblast=0;
5 Plagman 695
static SDL_Joystick *joydev = NULL;
696
 
697
//
698
// initinput() -- init input system
699
//
1205 terminx 700
int32_t initinput(void)
5 Plagman 701
{
4749 terminx 702
    int32_t i, j;
109 terminx 703
 
4482 helixhorne 704
#ifdef _WIN32
705
    W_SetKeyboardLayoutUS(0);
706
#endif
707
 
5 Plagman 708
#ifdef __APPLE__
109 terminx 709
    // force OS X to operate in >1 button mouse mode so that LMB isn't adulterated
4749 terminx 710
    if (!getenv("SDL_HAS3BUTTONMOUSE"))
711
        putenv("SDL_HAS3BUTTONMOUSE=1");
5 Plagman 712
#endif
4749 terminx 713
 
4808 hendricks2 714
    if (!keyremapinit)
715
        for (i = 0; i < 256; i++) keyremap[i] = i;
716
    keyremapinit = 1;
5 Plagman 717
 
4749 terminx 718
    inputdevices = 1 | 2;  // keyboard (1) and mouse (2)
1857 terminx 719
    mousegrab = 0;
5 Plagman 720
 
4749 terminx 721
    memset(key_names, 0, sizeof(key_names));
4432 terminx 722
 
723
#if SDL_MAJOR_VERSION == 1
4749 terminx 724
#define SDL_SCANCODE_TO_KEYCODE(x) (SDLKey)(x)
725
#define SDL_JoystickNameForIndex(x) SDL_JoystickName(x)
726
#define SDL_NUM_SCANCODES SDLK_LAST
727
    if (SDL_EnableKeyRepeat(250, 30))
728
        initprintf("Error enabling keyboard repeat.\n");
729
    SDL_EnableUNICODE(1);  // let's hope this doesn't hit us too hard
4432 terminx 730
#endif
731
 
4749 terminx 732
    for (i = SDL_NUM_SCANCODES - 1; i >= 0; i--)
342 terminx 733
    {
4749 terminx 734
        if (!keytranslation[i])
735
            continue;
736
 
737
        Bstrncpyz(key_names[keytranslation[i]], SDL_GetKeyName(SDL_SCANCODE_TO_KEYCODE(i)), sizeof(key_names[i]));
1109 terminx 738
    }
5 Plagman 739
 
342 terminx 740
    if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
741
    {
109 terminx 742
        i = SDL_NumJoysticks();
4749 terminx 743
        initprintf("%d joystick(s) found\n", i);
744
 
745
        for (j = 0; j < i; j++)
746
            initprintf("  %d. %s\n", j + 1, SDL_JoystickNameForIndex(j));
747
 
109 terminx 748
        joydev = SDL_JoystickOpen(0);
4749 terminx 749
 
342 terminx 750
        if (joydev)
751
        {
109 terminx 752
            SDL_JoystickEventState(SDL_ENABLE);
289 terminx 753
            inputdevices |= 4;
5 Plagman 754
 
4827 hendricks2 755
            // KEEPINSYNC source/gamedefs.h, source/jmact/_control.h
756
            joynumaxes = min(9, SDL_JoystickNumAxes(joydev));
4749 terminx 757
            joynumbuttons = min(32, SDL_JoystickNumButtons(joydev));
4827 hendricks2 758
            joynumhats = min((36-joynumbuttons)/4,SDL_JoystickNumHats(joydev));
4749 terminx 759
            initprintf("Joystick 1 has %d axes, %d buttons, and %d hat(s).\n", joynumaxes, joynumbuttons, joynumhats);
5 Plagman 760
 
1205 terminx 761
            joyaxis = (int32_t *)Bcalloc(joynumaxes, sizeof(int32_t));
4749 terminx 762
 
2331 helixhorne 763
            if (joynumhats)
764
                joyhat = (int32_t *)Bcalloc(joynumhats, sizeof(int32_t));
1716 plagman 765
 
4749 terminx 766
            for (i = 0; i < joynumhats; i++) joyhat[i] = -1;  // centre
1716 plagman 767
 
768
            joydead = (uint16_t *)Bcalloc(joynumaxes, sizeof(uint16_t));
769
            joysatur = (uint16_t *)Bcalloc(joynumaxes, sizeof(uint16_t));
109 terminx 770
        }
771
    }
772
 
773
    return 0;
5 Plagman 774
}
775
 
776
//
777
// uninitinput() -- uninit input system
778
//
779
void uninitinput(void)
780
{
4482 helixhorne 781
#ifdef _WIN32
782
    W_SetKeyboardLayoutUS(1);
783
#endif
109 terminx 784
    uninitmouse();
5 Plagman 785
 
342 terminx 786
    if (joydev)
787
    {
109 terminx 788
        SDL_JoystickClose(joydev);
789
        joydev = NULL;
790
    }
5 Plagman 791
}
792
 
2624 helixhorne 793
#ifndef GEKKO
1205 terminx 794
const char *getjoyname(int32_t what, int32_t num)
5 Plagman 795
{
109 terminx 796
    static char tmp[64];
5 Plagman 797
 
342 terminx 798
    switch (what)
799
    {
4749 terminx 800
        case 0:  // axis
801
            if ((unsigned)num > (unsigned)joynumaxes)
802
                return NULL;
803
            Bsprintf(tmp, "Axis %d", num);
804
            return (char *)tmp;
5 Plagman 805
 
4749 terminx 806
        case 1:  // button
807
            if ((unsigned)num > (unsigned)joynumbuttons)
808
                return NULL;
809
            Bsprintf(tmp, "Button %d", num);
810
            return (char *)tmp;
5 Plagman 811
 
4749 terminx 812
        case 2:  // hat
813
            if ((unsigned)num > (unsigned)joynumhats)
814
                return NULL;
815
            Bsprintf(tmp, "Hat %d", num);
816
            return (char *)tmp;
5 Plagman 817
 
4749 terminx 818
        default: return NULL;
109 terminx 819
    }
5 Plagman 820
}
2624 helixhorne 821
#endif
822
 
823
 
5 Plagman 824
//
825
// initmouse() -- init mouse input
826
//
1205 terminx 827
int32_t initmouse(void)
5 Plagman 828
{
4738 hendricks2 829
    moustat=AppMouseGrab;
830
    grabmouse(AppMouseGrab); // FIXME - SA
109 terminx 831
    return 0;
5 Plagman 832
}
833
 
834
//
835
// uninitmouse() -- uninit mouse input
836
//
837
void uninitmouse(void)
838
{
109 terminx 839
    grabmouse(0);
4749 terminx 840
    moustat = 0;
5 Plagman 841
}
842
 
843
 
4767 hendricks2 844
#if SDL_MAJOR_VERSION != 1
5 Plagman 845
//
4089 hendricks2 846
// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state).
847
//                    furthermore return 0 if successful.
848
//
849
 
850
static inline char grabmouse_low(char a)
851
{
4852 hendricks2 852
#if !defined EDUKE32_TOUCH_DEVICES && (!defined DEBUGGINGAIDS || defined _WIN32 || defined __APPLE__)
4089 hendricks2 853
    /* FIXME: Maybe it's better to make sure that grabmouse_low
854
       is called only when a window is ready?                */
855
    if (sdl_window)
856
        SDL_SetWindowGrab(sdl_window, a ? SDL_TRUE : SDL_FALSE);
857
    return SDL_SetRelativeMouseMode(a ? SDL_TRUE : SDL_FALSE);
4446 helixhorne 858
#else
859
    UNREFERENCED_PARAMETER(a);
860
    return 0;
4432 terminx 861
#endif
4089 hendricks2 862
}
4767 hendricks2 863
#endif
4089 hendricks2 864
 
865
//
5 Plagman 866
// grabmouse() -- show/hide mouse cursor
867
//
868
void grabmouse(char a)
869
{
342 terminx 870
    if (appactive && moustat)
871
    {
4852 hendricks2 872
#if !defined EDUKE32_TOUCH_DEVICES && (!defined DEBUGGINGAIDS || defined _WIN32 || defined __APPLE__)
4089 hendricks2 873
        if ((a != mousegrab) && !grabmouse_low(a))
4095 helixhorne 874
#endif
1857 terminx 875
            mousegrab = a;
342 terminx 876
    }
877
    else
1857 terminx 878
        mousegrab = a;
4749 terminx 879
 
109 terminx 880
    mousex = mousey = 0;
5 Plagman 881
}
882
 
4738 hendricks2 883
void AppGrabMouse(char a)
884
{
4906 terminx 885
    if (!(a & 2))
886
    {
887
        grabmouse(a);
888
        AppMouseGrab = mousegrab;
889
    }
890
 
891
    SDL_ShowCursor((osd && osd->flags & OSD_CAPTURE) ? SDL_ENABLE : SDL_DISABLE);
4738 hendricks2 892
}
893
 
5 Plagman 894
//
895
// setjoydeadzone() -- sets the dead and saturation zones for the joystick
896
//
1205 terminx 897
void setjoydeadzone(int32_t axis, uint16_t dead, uint16_t satur)
655 terminx 898
{
1716 plagman 899
    joydead[axis] = dead;
900
    joysatur[axis] = satur;
655 terminx 901
}
5 Plagman 902
 
903
 
904
//
905
// getjoydeadzone() -- gets the dead and saturation zones for the joystick
906
//
1205 terminx 907
void getjoydeadzone(int32_t axis, uint16_t *dead, uint16_t *satur)
5 Plagman 908
{
1716 plagman 909
    *dead = joydead[axis];
910
    *satur = joysatur[axis];
5 Plagman 911
}
912
 
913
 
914
//
915
// releaseallbuttons()
916
//
917
void releaseallbuttons(void)
342 terminx 918
{}
5 Plagman 919
 
920
 
921
//
922
//
923
// ---------------------------------------
924
//
925
// All things Timer
926
// Ken did this
927
//
928
// ---------------------------------------
929
//
930
//
931
 
4749 terminx 932
static uint32_t timerfreq;
933
static uint32_t timerlastsample;
2285 helixhorne 934
int32_t timerticspersec=0;
3934 helixhorne 935
static double msperu64tick = 0;
342 terminx 936
static void(*usertimercallback)(void) = NULL;
5 Plagman 937
 
2778 helixhorne 938
 
5 Plagman 939
//
627 terminx 940
// inittimer() -- initialize timer
5 Plagman 941
//
1205 terminx 942
int32_t inittimer(int32_t tickspersecond)
5 Plagman 943
{
109 terminx 944
    if (timerfreq) return 0;    // already installed
5 Plagman 945
 
627 terminx 946
//    initprintf("Initializing timer\n");
5 Plagman 947
 
3221 hendricks2 948
#ifdef _WIN32
949
    {
950
        int32_t t = win_inittimer();
951
        if (t < 0)
952
            return t;
953
    }
954
#endif
955
 
109 terminx 956
    timerfreq = 1000;
957
    timerticspersec = tickspersecond;
958
    timerlastsample = SDL_GetTicks() * timerticspersec / timerfreq;
5 Plagman 959
 
109 terminx 960
    usertimercallback = NULL;
5 Plagman 961
 
3934 helixhorne 962
    msperu64tick = 1000.0 / (double)getu64tickspersec();
2778 helixhorne 963
 
109 terminx 964
    return 0;
5 Plagman 965
}
966
 
967
//
968
// uninittimer() -- shut down timer
969
//
970
void uninittimer(void)
971
{
109 terminx 972
    if (!timerfreq) return;
5 Plagman 973
 
109 terminx 974
    timerfreq=0;
2778 helixhorne 975
 
3221 hendricks2 976
#ifdef _WIN32
977
    win_timerfreq=0;
978
#endif
979
 
3934 helixhorne 980
    msperu64tick = 0;
5 Plagman 981
}
982
 
983
//
984
// sampletimer() -- update totalclock
985
//
986
void sampletimer(void)
987
{
4749 terminx 988
    uint32_t i;
1205 terminx 989
    int32_t n;
5 Plagman 990
 
109 terminx 991
    if (!timerfreq) return;
992
    i = SDL_GetTicks();
4749 terminx 993
    n = tabledivide32(i * timerticspersec, timerfreq) - timerlastsample;
109 terminx 994
 
4749 terminx 995
    if (n <= 0) return;
5 Plagman 996
 
4749 terminx 997
    totalclock += n;
998
    timerlastsample += n;
999
 
1000
    if (usertimercallback)
1001
        for (; n > 0; n--) usertimercallback();
5 Plagman 1002
}
1003
 
4765 hendricks2 1004
#if defined LUNATIC
1005
//
1006
// getticks() -- returns the sdl ticks count
1007
//
1008
uint32_t getticks(void)
1009
{
1010
    return (uint32_t)SDL_GetTicks();
1011
}
1012
#endif
1013
 
2026 helixhorne 1014
// high-resolution timers for profiling
4749 terminx 1015
 
1016
#if SDL_MAJOR_VERSION!=1
3934 helixhorne 1017
uint64_t getu64ticks(void)
2026 helixhorne 1018
{
2778 helixhorne 1019
    return SDL_GetPerformanceCounter();
2026 helixhorne 1020
}
5 Plagman 1021
 
3934 helixhorne 1022
uint64_t getu64tickspersec(void)
2026 helixhorne 1023
{
2778 helixhorne 1024
    return SDL_GetPerformanceFrequency();
4749 terminx 1025
}
2778 helixhorne 1026
#endif
2026 helixhorne 1027
 
2778 helixhorne 1028
// Returns the time since an unspecified starting time in milliseconds.
1029
// (May be not monotonic for certain configurations.)
1030
ATTRIBUTE((flatten))
3935 helixhorne 1031
double gethiticks(void)
2026 helixhorne 1032
{
3934 helixhorne 1033
    return (double)getu64ticks() * msperu64tick;
2026 helixhorne 1034
}
1035
 
5 Plagman 1036
//
1037
// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
1038
//
1205 terminx 1039
int32_t gettimerfreq(void)
5 Plagman 1040
{
109 terminx 1041
    return timerticspersec;
5 Plagman 1042
}
1043
 
1044
 
1045
//
1046
// installusertimercallback() -- set up a callback function to be called when the timer is fired
1047
//
342 terminx 1048
void(*installusertimercallback(void(*callback)(void)))(void)
5 Plagman 1049
{
342 terminx 1050
    void(*oldtimercallback)(void);
5 Plagman 1051
 
109 terminx 1052
    oldtimercallback = usertimercallback;
1053
    usertimercallback = callback;
5 Plagman 1054
 
109 terminx 1055
    return oldtimercallback;
5 Plagman 1056
}
1057
 
1058
 
1059
 
1060
//
1061
//
1062
// ---------------------------------------
1063
//
1064
// All things Video
1065
//
1066
// ---------------------------------------
1067
//
109 terminx 1068
//
5 Plagman 1069
 
1070
 
1071
//
1072
// getvalidmodes() -- figure out what video modes are available
1073
//
4068 helixhorne 1074
static int sortmodes(const void *a_, const void *b_)
5 Plagman 1075
{
1205 terminx 1076
    int32_t x;
5 Plagman 1077
 
4068 helixhorne 1078
    const struct validmode_t *a = (const struct validmode_t *)a_;
1079
    const struct validmode_t *b = (const struct validmode_t *)b_;
1080
 
109 terminx 1081
    if ((x = a->fs   - b->fs)   != 0) return x;
1082
    if ((x = a->bpp  - b->bpp)  != 0) return x;
1083
    if ((x = a->xdim - b->xdim) != 0) return x;
1084
    if ((x = a->ydim - b->ydim) != 0) return x;
5 Plagman 1085
 
109 terminx 1086
    return 0;
5 Plagman 1087
}
4432 terminx 1088
 
5 Plagman 1089
static char modeschecked=0;
4432 terminx 1090
 
4749 terminx 1091
#if SDL_MAJOR_VERSION != 1
5 Plagman 1092
void getvalidmodes(void)
1093
{
4749 terminx 1094
    int32_t i, maxx = 0, maxy = 0;
4432 terminx 1095
    SDL_DisplayMode dispmode;
1096
 
4749 terminx 1097
    if (modeschecked || novideo)
1098
        return;
4432 terminx 1099
 
4749 terminx 1100
    validmodecnt = 0;
4432 terminx 1101
    //    initprintf("Detecting video modes:\n");
1102
 
1103
    // do fullscreen modes first
4749 terminx 1104
    for (i = 0; i < SDL_GetNumDisplayModes(0); i++)
4089 hendricks2 1105
    {
1106
        SDL_GetDisplayMode(0, i, &dispmode);
4749 terminx 1107
        if ((dispmode.w > MAXXDIM) || (dispmode.h > MAXYDIM))
1108
            continue;
4089 hendricks2 1109
 
1110
        // HACK: 8-bit == Software, 32-bit == OpenGL
4749 terminx 1111
        SDL_ADDMODE(dispmode.w, dispmode.h, 8, 1);
4089 hendricks2 1112
#ifdef USE_OPENGL
1113
        if (!nogl)
4749 terminx 1114
            SDL_ADDMODE(dispmode.w, dispmode.h, 32, 1);
4089 hendricks2 1115
#endif
4749 terminx 1116
        if ((dispmode.w > maxx) || (dispmode.h > maxy))
4089 hendricks2 1117
        {
1118
            maxx = dispmode.w;
1119
            maxy = dispmode.h;
1120
        }
1121
    }
5 Plagman 1122
 
4749 terminx 1123
    SDL_CHECKFSMODES(maxx, maxy);
1124
 
109 terminx 1125
    // add windowed modes next
4749 terminx 1126
    for (i = 0; defaultres[i][0]; i++)
342 terminx 1127
    {
4749 terminx 1128
        if (!SDL_CHECKMODE(defaultres[i][0], defaultres[i][1]))
1129
            continue;
1130
 
1131
        // HACK: 8-bit == Software, 32-bit == OpenGL
1132
        SDL_ADDMODE(defaultres[i][0], defaultres[i][1], 8, 0);
1133
 
4089 hendricks2 1134
#ifdef USE_OPENGL
4749 terminx 1135
        if (nogl)
1136
            continue;
1137
 
1138
        SDL_ADDMODE(defaultres[i][0], defaultres[i][1], 32, 0);
4089 hendricks2 1139
#endif
4432 terminx 1140
    }
5 Plagman 1141
 
4749 terminx 1142
    qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes);
5 Plagman 1143
 
4749 terminx 1144
    modeschecked = 1;
5 Plagman 1145
}
4432 terminx 1146
#endif
5 Plagman 1147
 
1148
//
1149
// checkvideomode() -- makes sure the video mode passed is legal
1150
//
1205 terminx 1151
int32_t checkvideomode(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t forced)
5 Plagman 1152
{
1205 terminx 1153
    int32_t i, nearest=-1, dx, dy, odx=9999, ody=9999;
5 Plagman 1154
 
109 terminx 1155
    getvalidmodes();
5 Plagman 1156
 
109 terminx 1157
    if (c>8
5 Plagman 1158
#ifdef USE_OPENGL
109 terminx 1159
            && nogl
5 Plagman 1160
#endif
109 terminx 1161
       ) return -1;
5 Plagman 1162
 
109 terminx 1163
    // fix up the passed resolution values to be multiples of 8
1164
    // and at least 320x200 or at most MAXXDIMxMAXYDIM
4749 terminx 1165
    *x = clamp(*x, 320, MAXXDIM);
1166
    *y = clamp(*y, 200, MAXYDIM);
5 Plagman 1167
 
4749 terminx 1168
    for (i = 0; i < validmodecnt; i++)
342 terminx 1169
    {
4749 terminx 1170
        if (validmode[i].bpp != c || validmode[i].fs != fs)
1171
            continue;
1172
 
109 terminx 1173
        dx = klabs(validmode[i].xdim - *x);
1174
        dy = klabs(validmode[i].ydim - *y);
4749 terminx 1175
 
342 terminx 1176
        if (!(dx | dy))
584 terminx 1177
        {
1178
            // perfect match
109 terminx 1179
            nearest = i;
1180
            break;
1181
        }
4749 terminx 1182
 
342 terminx 1183
        if ((dx <= odx) && (dy <= ody))
1184
        {
109 terminx 1185
            nearest = i;
4749 terminx 1186
            odx = dx;
1187
            ody = dy;
109 terminx 1188
        }
1189
    }
1190
 
331 terminx 1191
#ifdef ANY_WINDOWED_SIZE
194 terminx 1192
    if (!forced && (fs&1) == 0 && (nearest < 0 || (validmode[nearest].xdim!=*x || validmode[nearest].ydim!=*y)))
109 terminx 1193
        return 0x7fffffffl;
331 terminx 1194
#endif
5 Plagman 1195
 
342 terminx 1196
    if (nearest < 0)
109 terminx 1197
        return -1;
5 Plagman 1198
 
109 terminx 1199
    *x = validmode[nearest].xdim;
1200
    *y = validmode[nearest].ydim;
5 Plagman 1201
 
4749 terminx 1202
    return nearest;
5 Plagman 1203
}
1204
 
2777 helixhorne 1205
static int32_t needpalupdate;
1206
static SDL_Color sdlayer_pal[256];
5 Plagman 1207
 
4089 hendricks2 1208
static void destroy_window_resources()
2777 helixhorne 1209
{
4819 hendricks2 1210
#if !defined SDL_DISABLE_8BIT_BUFFER
4749 terminx 1211
    if (sdl_buffersurface)
1212
        SDL_FreeSurface(sdl_buffersurface);
4270 hendricks2 1213
 
4749 terminx 1214
    sdl_buffersurface = NULL;
4819 hendricks2 1215
#endif
4749 terminx 1216
/* We should NOT destroy the window surface. This is done automatically
1217
   when SDL_DestroyWindow or SDL_SetVideoMode is called.             */
1218
 
1219
#if SDL_MAJOR_VERSION == 2
1220
    if (sdl_renderer && sdl_texture && sdl_surface)
1221
        SDL_FreeSurface(sdl_surface);
1222
    sdl_surface = NULL;
1223
    if (sdl_context)
1224
        SDL_GL_DeleteContext(sdl_context);
1225
    sdl_context = NULL;
1226
    if (sdl_texture)
1227
        SDL_DestroyTexture(sdl_texture);
1228
    sdl_texture = NULL;
1229
    if (sdl_renderer)
1230
        SDL_DestroyRenderer(sdl_renderer);
1231
    sdl_renderer = NULL;
1232
    if (sdl_window)
1233
        SDL_DestroyWindow(sdl_window);
1234
    sdl_window = NULL;
4088 hendricks2 1235
#endif
2777 helixhorne 1236
}
1237
 
4749 terminx 1238
#ifdef USE_OPENGL
1239
void sdlayer_setvideomode_opengl(void)
1240
{
1241
    polymost_glreset();
1242
 
1243
    bglEnable(GL_TEXTURE_2D);
1244
    bglShadeModel(GL_SMOOTH);  // GL_FLAT
1245
    bglClearColor(0, 0, 0, 0.5);  // Black Background
1246
    bglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Use FASTEST for ortho!
4992 terminx 1247
//    bglHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
4997 terminx 1248
 
1249
#ifndef EDUKE32_GLES
4749 terminx 1250
    bglDisable(GL_DITHER);
4997 terminx 1251
#endif
4749 terminx 1252
 
1253
    glinfo.vendor = (const char *) bglGetString(GL_VENDOR);
1254
    glinfo.renderer = (const char *) bglGetString(GL_RENDERER);
1255
    glinfo.version = (const char *) bglGetString(GL_VERSION);
1256
    glinfo.extensions = (const char *) bglGetString(GL_EXTENSIONS);
1257
 
1258
#ifdef POLYMER
1259
    if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc."))
1260
    {
1261
        pr_ati_fboworkaround = 1;
1262
        initprintf("Enabling ATI FBO color attachment workaround.\n");
1263
 
1264
        if (Bstrstr(glinfo.renderer, "Radeon X1"))
1265
        {
1266
            pr_ati_nodepthoffset = 1;
1267
            initprintf("Enabling ATI R520 polygon offset workaround.\n");
1268
        }
1269
        else
1270
            pr_ati_nodepthoffset = 0;
1271
#ifdef __APPLE__
1272
        // See bug description at http://lists.apple.com/archives/mac-opengl/2005/Oct/msg00169.html
1273
        if (!Bstrncmp(glinfo.renderer, "ATI Radeon 9600", 15))
1274
        {
1275
            pr_ati_textureformat_one = 1;
1276
            initprintf("Enabling ATI Radeon 9600 texture format workaround.\n");
1277
        }
1278
        else
1279
            pr_ati_textureformat_one = 0;
1280
#endif
1281
    }
1282
    else
1283
        pr_ati_fboworkaround = 0;
1284
#endif  // defined POLYMER
1285
 
1286
    glinfo.maxanisotropy = 1.0;
1287
    glinfo.bgra = 0;
1288
    glinfo.texcompr = 0;
4992 terminx 1289
    glinfo.clamptoedge = 1;
1290
    glinfo.multitex = 1;
4749 terminx 1291
 
1292
    // process the extensions string and flag stuff we recognize
4992 terminx 1293
 
1294
    glinfo.texcompr = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_compression") && Bstrcmp(glinfo.vendor, "ATI Technologies Inc.");
1295
    glinfo.texnpot = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_non_power_of_two") || !!Bstrstr(glinfo.extensions, "GL_OES_texture_npot");
4752 terminx 1296
    glinfo.multisample = !!Bstrstr(glinfo.extensions, "GL_ARB_multisample");
1297
    glinfo.nvmultisamplehint = !!Bstrstr(glinfo.extensions, "GL_NV_multisample_filter_hint");
1298
    glinfo.arbfp = !!Bstrstr(glinfo.extensions, "GL_ARB_fragment_program");
1299
    glinfo.depthtex = !!Bstrstr(glinfo.extensions, "GL_ARB_depth_texture");
1300
    glinfo.shadow = !!Bstrstr(glinfo.extensions, "GL_ARB_shadow");
4992 terminx 1301
    glinfo.fbos = !!Bstrstr(glinfo.extensions, "GL_EXT_framebuffer_object") || !!Bstrstr(glinfo.extensions, "GL_OES_framebuffer_object");
1302
 
1303
#ifndef __ANDROID__
4997 terminx 1304
    glinfo.bgra = !!Bstrstr(glinfo.extensions, "GL_EXT_bgra");
4992 terminx 1305
    glinfo.clamptoedge = !!Bstrstr(glinfo.extensions, "GL_EXT_texture_edge_clamp") ||
1306
                         !!Bstrstr(glinfo.extensions, "GL_SGIS_texture_edge_clamp");
4752 terminx 1307
    glinfo.rect =
1308
    !!Bstrstr(glinfo.extensions, "GL_NV_texture_rectangle") || !!Bstrstr(glinfo.extensions, "GL_EXT_texture_rectangle");
4992 terminx 1309
 
4752 terminx 1310
    glinfo.multitex = !!Bstrstr(glinfo.extensions, "GL_ARB_multitexture");
4992 terminx 1311
 
4752 terminx 1312
    glinfo.envcombine = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_env_combine");
1313
    glinfo.vbos = !!Bstrstr(glinfo.extensions, "GL_ARB_vertex_buffer_object");
1314
    glinfo.sm4 = !!Bstrstr(glinfo.extensions, "GL_EXT_gpu_shader4");
1315
    glinfo.occlusionqueries = !!Bstrstr(glinfo.extensions, "GL_ARB_occlusion_query");
1316
    glinfo.glsl = !!Bstrstr(glinfo.extensions, "GL_ARB_shader_objects");
1317
    glinfo.debugoutput = !!Bstrstr(glinfo.extensions, "GL_ARB_debug_output");
4749 terminx 1318
 
4752 terminx 1319
    if (Bstrstr(glinfo.extensions, "WGL_3DFX_gamma_control"))
4749 terminx 1320
    {
1321
        static int32_t warnonce;
1322
        // 3dfx cards have issues with fog
1323
        nofog = 1;
1324
        if (!(warnonce & 1))
1325
            initprintf("3dfx card detected: OpenGL fog disabled\n");
1326
        warnonce |= 1;
1327
    }
4992 terminx 1328
#endif
4749 terminx 1329
 
4992 terminx 1330
//    if (Bstrstr(glinfo.extensions, "GL_EXT_texture_filter_anisotropic"))
1331
        bglGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glinfo.maxanisotropy);
1332
 
4749 terminx 1333
    if (!glinfo.dumped)
1334
    {
1335
        int32_t oldbpp = bpp;
1336
        bpp = 32;
1337
        osdcmd_glinfo(NULL);
1338
        glinfo.dumped = 1;
1339
        bpp = oldbpp;
1340
    }
1341
}
1342
#endif  // defined USE_OPENGL
1343
 
5 Plagman 1344
//
1345
// setvideomode() -- set SDL video mode
1346
//
4749 terminx 1347
 
1348
int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t *regrab)
5 Plagman 1349
{
4749 terminx 1350
    if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (c == bpp) && !videomodereset)
342 terminx 1351
    {
4749 terminx 1352
        OSD_ResizeDisplay(xres, yres);
109 terminx 1353
        return 0;
1354
    }
5 Plagman 1355
 
4749 terminx 1356
    if (checkvideomode(x, y, c, fs, 0) < 0)
1357
        return -1;
109 terminx 1358
 
4820 hendricks2 1359
#ifdef GEKKO
1360
    if (!sdl_surface) // only run this the first time we set a video mode
1361
        wii_initgamevideo();
1362
#endif
1363
 
194 terminx 1364
    startwin_close();
5 Plagman 1365
 
1857 terminx 1366
    if (mousegrab)
342 terminx 1367
    {
4749 terminx 1368
        *regrab = 1;
109 terminx 1369
        grabmouse(0);
1370
    }
5 Plagman 1371
 
4749 terminx 1372
    while (lockcount) enddrawing();
5 Plagman 1373
 
1820 terminx 1374
#ifdef USE_OPENGL
4749 terminx 1375
    if (bpp > 8 && sdl_surface)
1376
        polymost_glreset();
5 Plagman 1377
#endif
1378
 
2222 helixhorne 1379
    // clear last gamma/contrast/brightness so that it will be set anew
1380
    lastvidgcb[0] = lastvidgcb[1] = lastvidgcb[2] = 0.0f;
1381
 
4749 terminx 1382
    return 1;
1383
}
1384
 
1385
void setvideomode_sdlcommonpost(int32_t x, int32_t y, int32_t c, int32_t fs, int32_t regrab)
1386
{
1387
    wm_setapptitle(apptitle);
1388
 
1389
#ifdef USE_OPENGL
1390
    if (c > 8)
1391
        sdlayer_setvideomode_opengl();
1392
#endif
1393
 
1394
    xres = x;
1395
    yres = y;
1396
    bpp = c;
1397
    fullscreen = fs;
1398
    // bytesperline = sdl_surface->pitch;
1399
    numpages = c > 8 ? 2 : 1;
1400
    frameplace = 0;
1401
    lockcount = 0;
1402
    modechange = 1;
1403
    videomodereset = 0;
1404
    OSD_ResizeDisplay(xres, yres);
1405
 
1406
    // save the current system gamma to determine if gamma is available
1407
    if (!gammabrightness)
342 terminx 1408
    {
4749 terminx 1409
        //        float f = 1.0 + ((float)curbrightness / 10.0);
1410
#if SDL_MAJOR_VERSION != 1
1411
        if (SDL_GetWindowGammaRamp(sdl_window, sysgamma[0], sysgamma[1], sysgamma[2]) == 0)
1412
#else
1413
        if (SDL_GetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]) >= 0)
1414
#endif
1415
            gammabrightness = 1;
1416
 
1417
        // see if gamma really is working by trying to set the brightness
1418
        if (gammabrightness && setgamma() < 0)
1419
            gammabrightness = 0;  // nope
109 terminx 1420
    }
4080 hendricks2 1421
 
4749 terminx 1422
    setpalettefade(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
1423
 
1424
    if (regrab)
1425
        grabmouse(AppMouseGrab);
1426
}
1427
 
1428
#if SDL_MAJOR_VERSION!=1
1429
int32_t setvideomode(int32_t x, int32_t y, int32_t c, int32_t fs)
1430
{
1431
    int32_t regrab = 0, ret;
109 terminx 1432
 
4749 terminx 1433
    ret = setvideomode_sdlcommon(&x, &y, c, fs, &regrab);
1434
    if (ret != 1) return ret;
1435
 
4089 hendricks2 1436
    // deinit
1437
    destroy_window_resources();
1438
 
4749 terminx 1439
    initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
1440
 
1820 terminx 1441
#ifdef USE_OPENGL
342 terminx 1442
    if (c > 8)
1443
    {
4997 terminx 1444
        int32_t i, j;
1445
#ifndef EDUKE32_GLES
1446
        int32_t multisamplecheck = (glmultisample > 0);
1447
#else
1448
        int32_t multisamplecheck = 0;
1449
#endif
4749 terminx 1450
        if (nogl)
1451
            return -1;
5 Plagman 1452
 
4749 terminx 1453
#ifdef _WIN32
3221 hendricks2 1454
        win_setvideomode(c);
4749 terminx 1455
#endif
4755 helixhorne 1456
        struct glattribs
1457
        {
1458
            SDL_GLattr attr;
1459
            int32_t value;
4992 terminx 1460
        } sdlayer_gl_attributes[] =
4755 helixhorne 1461
        {
4992 terminx 1462
#ifdef EDUKE32_TOUCH_DEVICES
1463
              { SDL_GL_CONTEXT_MAJOR_VERSION, 1 },
1464
              { SDL_GL_CONTEXT_MINOR_VERSION, 1 },
1465
#endif
1466
              { SDL_GL_DOUBLEBUFFER, 1 },
4997 terminx 1467
#ifndef EDUKE32_GLES
4992 terminx 1468
              { SDL_GL_MULTISAMPLEBUFFERS, glmultisample > 0 },
1469
              { SDL_GL_MULTISAMPLESAMPLES, glmultisample },
4997 terminx 1470
#endif
4992 terminx 1471
              { SDL_GL_STENCIL_SIZE, 1 },
1472
              { SDL_GL_ACCELERATED_VISUAL, 1 },
1473
          };
3221 hendricks2 1474
 
342 terminx 1475
        do
1476
        {
4749 terminx 1477
            SDL_GL_ATTRIBUTES(i, sdlayer_gl_attributes);
109 terminx 1478
 
890 terminx 1479
            /* HACK: changing SDL GL attribs only works before surface creation,
1480
               so we have to create a new surface in a different format first
1481
               to force the surface we WANT to be recreated instead of reused. */
4749 terminx 1482
            sdl_window = SDL_CreateWindow("", windowpos ? windowx : SDL_WINDOWPOS_CENTERED,
1483
                                          windowpos ? windowy : SDL_WINDOWPOS_CENTERED, x, y,
1484
                                          ((fs & 1) ? SDL_WINDOW_FULLSCREEN : 0) | SDL_WINDOW_OPENGL);
2777 helixhorne 1485
 
4749 terminx 1486
            if (sdl_window)
1487
                sdl_context = SDL_GL_CreateContext(sdl_window);
2777 helixhorne 1488
 
4749 terminx 1489
            if (!sdl_window || !sdl_context)
4089 hendricks2 1490
            {
4749 terminx 1491
                initprintf("Unable to set video mode: %s failed: %s\n", sdl_window ? "SDL_GL_CreateContext" : "SDL_GL_CreateWindow",  SDL_GetError());
4089 hendricks2 1492
                destroy_window_resources();
2777 helixhorne 1493
                return -1;
4089 hendricks2 1494
            }
4749 terminx 1495
 
4090 hendricks2 1496
            SDL_GL_SetSwapInterval(vsync_render);
4089 hendricks2 1497
 
1498
#ifdef _WIN32
1499
            loadglextensions();
1500
#endif
4749 terminx 1501
        } while (multisamplecheck--);
342 terminx 1502
    }
1503
    else
2014 helixhorne 1504
#endif  // defined USE_OPENGL
109 terminx 1505
    {
2777 helixhorne 1506
        // init
4896 terminx 1507
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : SDL_WINDOWPOS_CENTERED,
1508
                                      windowpos ? windowy : SDL_WINDOWPOS_CENTERED, x, y,
4749 terminx 1509
                                      ((fs & 1) ? SDL_WINDOW_FULLSCREEN : 0));
4089 hendricks2 1510
        if (!sdl_window)
4432 terminx 1511
            SDL2_VIDEO_ERR("SDL_CreateWindow");
2777 helixhorne 1512
 
4253 hendricks2 1513
        sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
1514
        if (!sdl_renderer)
4432 terminx 1515
            SDL2_VIDEO_FALLBACK("SDL_CreateRenderer")
4253 hendricks2 1516
        else
1517
        {
4271 hendricks2 1518
            SDL_RendererInfo sdl_rendererinfo;
1519
            SDL_GetRendererInfo(sdl_renderer, &sdl_rendererinfo);
4749 terminx 1520
            if (sdl_rendererinfo.flags & SDL_RENDERER_SOFTWARE)  // this would be useless
4432 terminx 1521
                SDL2_RENDERER_DESTROY(sdl_renderer);
4271 hendricks2 1522
            else
1523
            {
4749 terminx 1524
                sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, x, y);
4271 hendricks2 1525
                if (!sdl_texture)
1526
                {
4432 terminx 1527
                    SDL2_VIDEO_FALLBACK("SDL_CreateTexture");
1528
                    SDL2_RENDERER_DESTROY(sdl_renderer);
4271 hendricks2 1529
                }
1530
            }
2777 helixhorne 1531
 
4432 terminx 1532
            if (sdl_texture)
4253 hendricks2 1533
            {
4432 terminx 1534
                sdl_surface = SDL_CreateRGBSurface(0, x, y, 32, 0, 0, 0, 0);
1535
 
1536
                if (!sdl_surface)
1537
                {
1538
                    SDL2_VIDEO_FALLBACK("SDL_CreateRGBSurface");
1539
                    SDL_DestroyTexture(sdl_texture);
1540
                    sdl_texture = NULL;
1541
                    SDL2_RENDERER_DESTROY(sdl_renderer);
1542
                }
4253 hendricks2 1543
            }
1544
        }
1545
 
1546
        if (!sdl_surface)
1547
        {
1548
            sdl_surface = SDL_GetWindowSurface(sdl_window);
1549
            if (!sdl_surface)
4432 terminx 1550
                SDL2_VIDEO_ERR("SDL_GetWindowSurface");
4253 hendricks2 1551
        }
1552
 
4819 hendricks2 1553
#if !defined SDL_DISABLE_8BIT_BUFFER
4082 hendricks2 1554
        sdl_buffersurface = SDL_CreateRGBSurface(0, x, y, c, 0, 0, 0, 0);
4432 terminx 1555
 
4082 hendricks2 1556
        if (!sdl_buffersurface)
4432 terminx 1557
            SDL2_VIDEO_ERR("SDL_CreateRGBSurface");
4819 hendricks2 1558
#endif
4082 hendricks2 1559
 
2777 helixhorne 1560
        if (!sdl_palptr)
1561
            sdl_palptr = SDL_AllocPalette(256);
1562
 
4080 hendricks2 1563
        if (SDL_SetSurfacePalette(sdl_buffersurface, sdl_palptr) < 0)
2777 helixhorne 1564
            initprintf("SDL_SetSurfacePalette failed: %s\n", SDL_GetError());
109 terminx 1565
    }
5 Plagman 1566
 
4749 terminx 1567
    setvideomode_sdlcommonpost(x, y, c, fs, regrab);
5 Plagman 1568
 
109 terminx 1569
    return 0;
5 Plagman 1570
}
4749 terminx 1571
#endif
5 Plagman 1572
 
1573
//
1574
// resetvideomode() -- resets the video system
1575
//
1576
void resetvideomode(void)
1577
{
109 terminx 1578
    videomodereset = 1;
1579
    modeschecked = 0;
5 Plagman 1580
}
1581
 
1582
 
1583
//
1584
// begindrawing() -- locks the framebuffer for drawing
1585
//
1586
void begindrawing(void)
1587
{
342 terminx 1588
    if (bpp > 8)
1589
    {
109 terminx 1590
        if (offscreenrendering) return;
1591
        frameplace = 0;
1592
        bytesperline = 0;
1593
        modechange = 0;
1594
        return;
1595
    }
5 Plagman 1596
 
109 terminx 1597
    // lock the frame
1598
    if (lockcount++ > 0)
1599
        return;
5 Plagman 1600
 
109 terminx 1601
    if (offscreenrendering) return;
5 Plagman 1602
 
4080 hendricks2 1603
    if (SDL_MUSTLOCK(sdl_buffersurface)) SDL_LockSurface(sdl_buffersurface);
1604
    frameplace = (intptr_t)sdl_buffersurface->pixels;
109 terminx 1605
 
4080 hendricks2 1606
    if (sdl_buffersurface->pitch != bytesperline || modechange)
342 terminx 1607
    {
4080 hendricks2 1608
        bytesperline = sdl_buffersurface->pitch;
109 terminx 1609
 
3291 helixhorne 1610
        calc_ylookup(bytesperline, ydim);
1611
 
109 terminx 1612
        modechange=0;
1613
    }
5 Plagman 1614
}
1615
 
1616
 
1617
//
1618
// enddrawing() -- unlocks the framebuffer
1619
//
1620
void enddrawing(void)
1621
{
342 terminx 1622
    if (bpp > 8)
1623
    {
109 terminx 1624
        if (!offscreenrendering) frameplace = 0;
1625
        return;
1626
    }
5 Plagman 1627
 
109 terminx 1628
    if (!frameplace) return;
584 terminx 1629
    if (lockcount > 1) { lockcount--; return; }
109 terminx 1630
    if (!offscreenrendering) frameplace = 0;
1631
    if (lockcount == 0) return;
1632
    lockcount = 0;
5 Plagman 1633
 
109 terminx 1634
    if (offscreenrendering) return;
5 Plagman 1635
 
4080 hendricks2 1636
    if (SDL_MUSTLOCK(sdl_buffersurface)) SDL_UnlockSurface(sdl_buffersurface);
5 Plagman 1637
}
1638
 
1639
//
1640
// showframe() -- update the display
1641
//
4749 terminx 1642
#if SDL_MAJOR_VERSION != 1
4992 terminx 1643
 
1644
#ifdef __ANDROID__
1645
extern "C" void frameControls();
1646
#endif
1647
 
1205 terminx 1648
void showframe(int32_t w)
5 Plagman 1649
{
655 terminx 1650
    UNREFERENCED_PARAMETER(w);
5 Plagman 1651
 
4992 terminx 1652
#ifdef __ANDROID__
1653
    if (mobile_halted) return;
1654
#endif
1655
 
5 Plagman 1656
#ifdef USE_OPENGL
342 terminx 1657
    if (bpp > 8)
1658
    {
1659
        if (palfadedelta)
3263 helixhorne 1660
            fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
5 Plagman 1661
 
4992 terminx 1662
#ifdef __ANDROID__
1663
        frameControls();
1664
#endif
4082 hendricks2 1665
        SDL_GL_SwapWindow(sdl_window);
109 terminx 1666
        return;
1667
    }
5 Plagman 1668
#endif
1669
 
109 terminx 1670
    if (offscreenrendering) return;
5 Plagman 1671
 
342 terminx 1672
    if (lockcount)
1673
    {
584 terminx 1674
        printf("Frame still locked %d times when showframe() called.\n", lockcount);
109 terminx 1675
        while (lockcount) enddrawing();
1676
    }
1677
 
2221 helixhorne 1678
    // deferred palette updating
1679
    if (needpalupdate)
1680
    {
2777 helixhorne 1681
        if (SDL_SetPaletteColors(sdl_palptr, sdlayer_pal, 0, 256) < 0)
1682
            initprintf("SDL_SetPaletteColors failed: %s\n", SDL_GetError());
2221 helixhorne 1683
        needpalupdate = 0;
1684
    }
1685
 
4819 hendricks2 1686
#if !defined SDL_DISABLE_8BIT_BUFFER
4082 hendricks2 1687
    SDL_BlitSurface(sdl_buffersurface, NULL, sdl_surface, NULL);
4819 hendricks2 1688
#endif
4082 hendricks2 1689
 
4253 hendricks2 1690
    if (sdl_renderer && sdl_texture)
4089 hendricks2 1691
    {
4253 hendricks2 1692
        SDL_UpdateTexture(sdl_texture, NULL, sdl_surface->pixels, sdl_surface->pitch);
1693
 
1694
        SDL_RenderClear(sdl_renderer);
1695
        SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
1696
        SDL_RenderPresent(sdl_renderer);
1697
    }
1698
    else if (SDL_UpdateWindowSurface(sdl_window))
1699
    {
4089 hendricks2 1700
        // If a fullscreen X11 window is minimized then this may be required.
1701
        // FIXME: What to do if this fails...
1702
        sdl_surface = SDL_GetWindowSurface(sdl_window);
1703
        SDL_UpdateWindowSurface(sdl_window);
1704
    }
4749 terminx 1705
}
2777 helixhorne 1706
#endif
5 Plagman 1707
//
1708
// setpalette() -- set palette values
1709
//
1205 terminx 1710
int32_t setpalette(int32_t start, int32_t num)
5 Plagman 1711
{
4749 terminx 1712
    int32_t i, n;
5 Plagman 1713
 
4749 terminx 1714
    if (bpp > 8)
1715
        return 0;  // no palette in opengl
5 Plagman 1716
 
4749 terminx 1717
    Bmemcpy(sdlayer_pal, curpalettefaded, 256 * 4);
5 Plagman 1718
 
4749 terminx 1719
    for (i = start, n = num; n > 0; i++, n--)
4074 hendricks2 1720
        curpalettefaded[i].f =
4749 terminx 1721
#if SDL_MAJOR_VERSION == 1
4074 hendricks2 1722
        sdlayer_pal[i].unused
1723
#else
1724
        sdlayer_pal[i].a
1725
#endif
4749 terminx 1726
        = 0;
109 terminx 1727
 
2221 helixhorne 1728
    needpalupdate = 1;
1762 terminx 1729
 
2221 helixhorne 1730
    return 0;
5 Plagman 1731
}
1732
 
1733
//
1734
// setgamma
1735
//
1205 terminx 1736
int32_t setgamma(void)
5 Plagman 1737
{
4749 terminx 1738
    // return 0;
4440 terminx 1739
 
1205 terminx 1740
    int32_t i;
1741
    uint16_t gammaTable[768];
4606 terminx 1742
    float gamma = max(0.1f, min(4.f, vid_gamma));
1743
    float contrast = max(0.1f, min(3.f, vid_contrast));
1744
    float bright = max(-0.8f, min(0.8f, vid_brightness));
870 terminx 1745
 
4606 terminx 1746
    float invgamma = 1.f / gamma;
1747
    float norm = powf(255.f, invgamma - 1.f);
872 terminx 1748
 
4749 terminx 1749
    if (novideo)
1750
        return 0;
1762 terminx 1751
 
4749 terminx 1752
    if (lastvidgcb[0] == gamma && lastvidgcb[1] == contrast && lastvidgcb[2] == bright)
2222 helixhorne 1753
        return 0;
1754
 
872 terminx 1755
    // This formula is taken from Doomsday
1756
 
1757
    for (i = 0; i < 256; i++)
1758
    {
4606 terminx 1759
        float val = i * contrast - (contrast - 1.f) * 127.f;
1760
        if (gamma != 1.f)
1761
            val = powf(val, invgamma) / norm;
872 terminx 1762
 
4606 terminx 1763
        val += bright * 128.f;
1764
 
4749 terminx 1765
        gammaTable[i] = gammaTable[i + 256] = gammaTable[i + 512] = (uint16_t)max(0.f, min(65535.f, val * 256.f));
872 terminx 1766
    }
4432 terminx 1767
 
4749 terminx 1768
#if SDL_MAJOR_VERSION == 1
4606 terminx 1769
    i = SDL_SetGammaRamp(&gammaTable[0], &gammaTable[256], &gammaTable[512]);
4432 terminx 1770
    if (i != -1)
2777 helixhorne 1771
#else
1772
    i = INT32_MIN;
4606 terminx 1773
 
2777 helixhorne 1774
    if (sdl_window)
4606 terminx 1775
        i = SDL_SetWindowGammaRamp(sdl_window, &gammaTable[0], &gammaTable[256], &gammaTable[512]);
2222 helixhorne 1776
 
2777 helixhorne 1777
    if (i < 0)
2222 helixhorne 1778
    {
4749 terminx 1779
#ifndef __ANDROID__  // Don't do this check, it is really supported, TODO
2777 helixhorne 1780
        if (i != INT32_MIN)
1781
            initprintf("Unable to set gamma: SDL_SetWindowGammaRamp failed: %s\n", SDL_GetError());
4440 terminx 1782
#endif
2777 helixhorne 1783
    }
1784
    else
1785
#endif
1786
    {
2222 helixhorne 1787
        lastvidgcb[0] = gamma;
1788
        lastvidgcb[1] = contrast;
1789
        lastvidgcb[2] = bright;
1790
    }
1791
 
1792
    return i;
5 Plagman 1793
}
1794
 
4852 hendricks2 1795
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
5 Plagman 1796
extern struct sdlappicon sdlappicon;
4752 terminx 1797
static inline SDL_Surface *loadappicon(void)
5 Plagman 1798
{
4752 terminx 1799
    SDL_Surface *surf = SDL_CreateRGBSurfaceFrom((void *)sdlappicon.pixels, sdlappicon.width, sdlappicon.height, 32,
1800
                                                 sdlappicon.width * 4, 0xffl, 0xff00l, 0xff0000l, 0xff000000l);
109 terminx 1801
    return surf;
5 Plagman 1802
}
1803
#endif
1804
 
1805
//
1806
//
1807
// ---------------------------------------
1808
//
1809
// Miscellany
1810
//
1811
// ---------------------------------------
1812
//
109 terminx 1813
//
5 Plagman 1814
 
3022 helixhorne 1815
int32_t handleevents_peekkeys(void)
1816
{
1817
    SDL_PumpEvents();
4749 terminx 1818
 
4074 hendricks2 1819
#if SDL_MAJOR_VERSION==1
3022 helixhorne 1820
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN));
1821
#else
4074 hendricks2 1822
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN);
3022 helixhorne 1823
#endif
1824
}
5 Plagman 1825
 
4853 hendricks2 1826
void handleevents_updatemousestate(uint8_t state)
1827
{
1828
    mousepressstate = state == SDL_RELEASED ? Mouse_Released : Mouse_Pressed;
1829
}
3022 helixhorne 1830
 
4853 hendricks2 1831
 
5 Plagman 1832
//
1833
// handleevents() -- process the SDL message queue
1834
//   returns !0 if there was an important event worth checking (like quitting)
1835
//
1593 terminx 1836
 
4749 terminx 1837
int32_t handleevents_sdlcommon(SDL_Event *ev)
5 Plagman 1838
{
4749 terminx 1839
    int32_t j;
5 Plagman 1840
 
4749 terminx 1841
    switch (ev->type)
4200 hendricks2 1842
    {
4749 terminx 1843
        case SDL_MOUSEMOTION:
4753 terminx 1844
#ifndef GEKKO
4853 hendricks2 1845
            mouseabs.x = ev->motion.x;
1846
            mouseabs.y = ev->motion.y;
4753 terminx 1847
#endif
4749 terminx 1848
            // SDL <VER> doesn't handle relative mouse movement correctly yet as the cursor still clips to the
1849
            // screen edges
1850
            // so, we call SDL_WarpMouse() to center the cursor and ignore the resulting motion event that occurs
1851
            //  <VER> is 1.3 for PK, 1.2 for tueidj
1852
            if (appactive && mousegrab)
4200 hendricks2 1853
            {
4749 terminx 1854
                if (ev->motion.x != xdim >> 1 || ev->motion.y != ydim >> 1)
1109 terminx 1855
                {
4749 terminx 1856
                    mousex += ev->motion.xrel;
1857
                    mousey += ev->motion.yrel;
1858
#if !defined DEBUGGINGAIDS || MY_DEVELOPER_ID == 805120924
4754 terminx 1859
# if SDL_MAJOR_VERSION==1
1860
                    SDL_WarpMouse(xdim>>1, ydim>>1);
1861
# else
1862
                    SDL_WarpMouseInWindow(sdl_window, xdim>>1, ydim>>1);
1863
# endif
4432 terminx 1864
#endif
4327 terminx 1865
                }
1109 terminx 1866
            }
109 terminx 1867
            break;
5 Plagman 1868
 
109 terminx 1869
        case SDL_MOUSEBUTTONDOWN:
1870
        case SDL_MOUSEBUTTONUP:
4749 terminx 1871
            // some of these get reordered to match winlayer
1872
            switch (ev->button.button)
342 terminx 1873
            {
4749 terminx 1874
                default: j = -1; break;
4853 hendricks2 1875
                case SDL_BUTTON_LEFT: j = 0; handleevents_updatemousestate(ev->button.state); break;
4749 terminx 1876
                case SDL_BUTTON_RIGHT: j = 1; break;
1877
                case SDL_BUTTON_MIDDLE: j = 2; break;
4190 helixhorne 1878
 
4755 helixhorne 1879
#if SDL_MAJOR_VERSION == 1
4749 terminx 1880
                case SDL_BUTTON_WHEELUP:    // 4
1881
                case SDL_BUTTON_WHEELDOWN:  // 5
1882
                    j = ev->button.button;
1883
                    break;
4190 helixhorne 1884
#endif
4755 helixhorne 1885
                /* Thumb buttons. */
1886
#if SDL_MAJOR_VERSION==1 || !defined _WIN32
1887
                // NOTE: SDL1 does have SDL_BUTTON_X1, but that's not what is
1888
                // generated. Neither with SDL2 on Linux. (Other OSs: not tested.)
4749 terminx 1889
                case 8: j = 3; break;
1890
                case 9: j = 6; break;
4190 helixhorne 1891
#else
4755 helixhorne 1892
                // On SDL2/Windows, everything is as it should be.
4749 terminx 1893
                case SDL_BUTTON_X1: j = 3; break;
1894
                case SDL_BUTTON_X2: j = 6; break;
4190 helixhorne 1895
#endif
109 terminx 1896
            }
5 Plagman 1897
 
4749 terminx 1898
            if (j < 0)
1899
                break;
1900
 
1901
            if (ev->button.state == SDL_PRESSED)
1902
                mouseb |= (1 << j);
342 terminx 1903
            else
4775 hendricks2 1904
#if SDL_MAJOR_VERSION==1
1905
                if (j != SDL_BUTTON_WHEELUP && j != SDL_BUTTON_WHEELDOWN)
1906
#endif
4749 terminx 1907
                mouseb &= ~(1 << j);
5 Plagman 1908
 
109 terminx 1909
            if (mousepresscallback)
4749 terminx 1910
                mousepresscallback(j+1, ev->button.state == SDL_PRESSED);
109 terminx 1911
            break;
5 Plagman 1912
 
109 terminx 1913
        case SDL_JOYAXISMOTION:
4749 terminx 1914
            if (appactive && ev->jaxis.axis < joynumaxes)
1716 plagman 1915
            {
4749 terminx 1916
                joyaxis[ev->jaxis.axis] = ev->jaxis.value * 10000 / 32767;
1917
                if ((joyaxis[ev->jaxis.axis] < joydead[ev->jaxis.axis]) &&
1918
                    (joyaxis[ev->jaxis.axis] > -joydead[ev->jaxis.axis]))
1919
                    joyaxis[ev->jaxis.axis] = 0;
1920
                else if (joyaxis[ev->jaxis.axis] >= joysatur[ev->jaxis.axis])
1921
                    joyaxis[ev->jaxis.axis] = 10000;
1922
                else if (joyaxis[ev->jaxis.axis] <= -joysatur[ev->jaxis.axis])
1923
                    joyaxis[ev->jaxis.axis] = -10000;
1716 plagman 1924
                else
4749 terminx 1925
                    joyaxis[ev->jaxis.axis] = joyaxis[ev->jaxis.axis] * 10000 / joysatur[ev->jaxis.axis];
1716 plagman 1926
            }
109 terminx 1927
            break;
5 Plagman 1928
 
342 terminx 1929
        case SDL_JOYHATMOTION:
1930
        {
4749 terminx 1931
            int32_t hatvals[16] = {
1932
                -1,     // centre
1933
                0,      // up 1
1934
                9000,   // right 2
1935
                4500,   // up+right 3
1936
                18000,  // down 4
1937
                -1,     // down+up!! 5
1938
                13500,  // down+right 6
1939
                -1,     // down+right+up!! 7
1940
                27000,  // left 8
1941
                27500,  // left+up 9
1942
                -1,     // left+right!! 10
1943
                -1,     // left+right+up!! 11
1944
                22500,  // left+down 12
1945
                -1,     // left+down+up!! 13
1946
                -1,     // left+down+right!! 14
1947
                -1,     // left+down+right+up!! 15
584 terminx 1948
            };
4749 terminx 1949
            if (appactive && ev->jhat.hat < joynumhats)
1950
                joyhat[ev->jhat.hat] = hatvals[ev->jhat.value & 15];
331 terminx 1951
            break;
1952
        }
5 Plagman 1953
 
109 terminx 1954
        case SDL_JOYBUTTONDOWN:
1955
        case SDL_JOYBUTTONUP:
4749 terminx 1956
            if (appactive && ev->jbutton.button < joynumbuttons)
342 terminx 1957
            {
4749 terminx 1958
                if (ev->jbutton.state == SDL_PRESSED)
1959
                    joyb |= 1 << ev->jbutton.button;
109 terminx 1960
                else
4749 terminx 1961
                    joyb &= ~(1 << ev->jbutton.button);
4853 hendricks2 1962
 
1963
#ifdef GEKKO
1964
                if (ev->jbutton.button == 0) // WII_A
1965
                    handleevents_updatemousestate(ev->jbutton.state);
1966
#endif
109 terminx 1967
            }
1968
            break;
5 Plagman 1969
 
109 terminx 1970
        case SDL_QUIT:
1971
            quitevent = 1;
4749 terminx 1972
            return -1;
109 terminx 1973
    }
1974
 
4749 terminx 1975
    return 0;
1976
}
1644 helixhorne 1977
 
4767 hendricks2 1978
int32_t handleevents_pollsdl(void);
4749 terminx 1979
#if SDL_MAJOR_VERSION != 1
1980
// SDL 2.0 specific event handling
1981
int32_t handleevents_pollsdl(void)
1982
{
1983
    int32_t code, rv=0, j;
1984
    SDL_Event ev;
109 terminx 1985
 
4749 terminx 1986
    while (SDL_PollEvent(&ev))
1987
    {
1988
        switch (ev.type)
1989
        {
1990
            case SDL_TEXTINPUT:
1991
                j = 0;
1992
                do
1993
                {
1994
                    code = ev.text.text[j];
1995
 
1996
                    if (code != scantoasc[OSD_OSDKey()] && !keyascfifo_isfull())
1997
                    {
1998
                        if (OSD_HandleChar(code))
1999
                            keyascfifo_insert(code);
2000
                    }
2001
                } while (j < SDL_TEXTINPUTEVENT_TEXT_SIZE && ev.text.text[++j]);
2002
                break;
2003
 
2004
            case SDL_KEYDOWN:
2005
            case SDL_KEYUP:
2006
                code = keytranslation[ev.key.keysym.scancode];
2007
 
2008
                // XXX: see osd.c, OSD_HandleChar(), there are more...
2009
                if (ev.key.type == SDL_KEYDOWN && !keyascfifo_isfull() &&
2010
                    (ev.key.keysym.scancode == SDL_SCANCODE_RETURN ||
2011
                    ev.key.keysym.scancode == SDL_SCANCODE_KP_ENTER ||
2012
                    ev.key.keysym.scancode == SDL_SCANCODE_ESCAPE ||
2013
                    ev.key.keysym.scancode == SDL_SCANCODE_BACKSPACE ||
2014
                    ev.key.keysym.scancode == SDL_SCANCODE_TAB ||
2015
                    (ev.key.keysym.mod==KMOD_LCTRL &&
2016
                    (ev.key.keysym.scancode == SDL_SCANCODE_F ||
2017
                    ev.key.keysym.scancode == SDL_SCANCODE_G ||
2018
                    ev.key.keysym.scancode == SDL_SCANCODE_K ||
2019
                    ev.key.keysym.scancode == SDL_SCANCODE_U))))
2020
                {
2021
                    char keyvalue;
2022
                    switch (ev.key.keysym.scancode)
2023
                    {
2024
                        case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: keyvalue = '\r'; break;
2025
                        case SDL_SCANCODE_ESCAPE: keyvalue = 27; break;
2026
                        case SDL_SCANCODE_BACKSPACE: keyvalue = '\b'; break;
2027
                        case SDL_SCANCODE_TAB: keyvalue = '\t'; break;
2028
                        case SDL_SCANCODE_F: keyvalue = 6; break;
2029
                        case SDL_SCANCODE_G: keyvalue = 7; break;
2030
                        case SDL_SCANCODE_K: keyvalue = 11; break;
2031
                        case SDL_SCANCODE_U: keyvalue = 21; break;
2032
                        default: keyvalue = 0; break;
2033
                    }
2034
                    if (OSD_HandleChar(keyvalue))
2035
                        keyascfifo_insert(keyvalue);
2036
                }
2037
 
2038
                // initprintf("SDL2: got key %d, %d, %u\n", ev.key.keysym.scancode, code, ev.key.type);
2039
 
2040
                // hook in the osd
2041
                if ((j = OSD_HandleScanCode(code, (ev.key.type == SDL_KEYDOWN))) <= 0)
2042
                {
2043
                    if (j == -1)  // osdkey
2044
                        for (j = 0; j < KEYSTATUSSIZ; ++j)
2045
                            if (GetKey(j))
2046
                            {
2047
                                SetKey(j, 0);
2048
                                if (keypresscallback)
2049
                                    keypresscallback(j, 0);
2050
                            }
2051
                    break;
2052
                }
2053
 
2054
                if (ev.key.type == SDL_KEYDOWN)
2055
                {
2056
                    if (!GetKey(code))
2057
                    {
2058
                        SetKey(code, 1);
2059
                        if (keypresscallback)
2060
                            keypresscallback(code, 1);
2061
                    }
2062
                }
2063
                else
2064
                {
2065
# if 1
2066
                    // The pause key generates a release event right after
2067
                    // the pressing one. As a result, it gets unseen
2068
                    // by the game most of the time.
2069
                    if (code == 0x59)  // pause
2070
                        break;
2071
# endif
2072
                    SetKey(code, 0);
2073
                    if (keypresscallback)
2074
                        keypresscallback(code, 0);
2075
                }
2076
                break;
2077
 
2078
            case SDL_MOUSEWHEEL:
2079
                // initprintf("wheel y %d\n",ev.wheel.y);
2080
                if (ev.wheel.y > 0)
2081
                {
2082
                    mouseb |= 16;
2083
                    if (mousepresscallback)
2084
                        mousepresscallback(5, 1);
2085
                }
2086
                if (ev.wheel.y < 0)
2087
                {
2088
                    mouseb |= 32;
2089
                    if (mousepresscallback)
2090
                        mousepresscallback(6, 1);
2091
                }
2092
                break;
2093
 
2094
            case SDL_WINDOWEVENT:
2095
                switch (ev.window.event)
2096
                {
2097
                    case SDL_WINDOWEVENT_FOCUS_GAINED:
2098
                    case SDL_WINDOWEVENT_FOCUS_LOST:
2099
                        appactive = (ev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
2100
                        if (mousegrab && moustat)
2101
                            grabmouse_low(appactive);
2102
#ifdef _WIN32
2103
                        if (backgroundidle)
2104
                            SetPriorityClass(GetCurrentProcess(), appactive ? NORMAL_PRIORITY_CLASS : IDLE_PRIORITY_CLASS);
3219 hendricks2 2105
#endif
4749 terminx 2106
                        break;
5 Plagman 2107
 
4749 terminx 2108
                    case SDL_WINDOWEVENT_MOVED:
2109
                        if (windowpos)
2110
                        {
2111
                            windowx = ev.window.data1;
2112
                            windowy = ev.window.data2;
2113
                        }
2114
                        break;
4753 terminx 2115
                    case SDL_WINDOWEVENT_ENTER:
2116
                        mouseinwindow = 1;
2117
                        break;
2118
                    case SDL_WINDOWEVENT_LEAVE:
2119
                        mouseinwindow = 0;
2120
                        break;
4749 terminx 2121
                }
2122
                break;
5 Plagman 2123
 
4749 terminx 2124
            default:
2125
                rv = handleevents_sdlcommon(&ev);
2126
                break;
2127
        }
2128
    }
2129
 
109 terminx 2130
    return rv;
5 Plagman 2131
}
4749 terminx 2132
#endif
5 Plagman 2133
 
4749 terminx 2134
int32_t handleevents(void)
1644 helixhorne 2135
{
4992 terminx 2136
#ifdef __ANDROID__
2137
    extern int mobile_halted;
2138
    if (mobile_halted) return 0;
2139
#endif
2140
 
4749 terminx 2141
    int32_t rv;
1644 helixhorne 2142
 
4749 terminx 2143
    if (inputchecked && moustat)
1762 terminx 2144
    {
4749 terminx 2145
        if (mousepresscallback)
1762 terminx 2146
        {
4749 terminx 2147
            if (mouseb & 16)
2148
                mousepresscallback(5, 0);
2149
            if (mouseb & 32)
2150
                mousepresscallback(6, 0);
1644 helixhorne 2151
        }
4749 terminx 2152
        mouseb &= ~(16 | 32);
1644 helixhorne 2153
    }
4749 terminx 2154
 
2155
    rv = handleevents_pollsdl();
2156
 
2157
    inputchecked = 0;
2158
    sampletimer();
2159
 
2160
#ifndef _WIN32
2161
    startwin_idle(NULL);
1644 helixhorne 2162
#endif
2163
 
4749 terminx 2164
    return rv;
2165
}
109 terminx 2166
 
4749 terminx 2167
#if SDL_MAJOR_VERSION == 1
2168
#include "sdlayer12.c"
2169
#endif