Subversion Repositories eduke32

Rev

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