Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
4774 hendricks2 1
// SDL 1.2 compatibility.
4749 terminx 2
 
3
#include <SDL/SDL_events.h>
4
 
5
int32_t wm_ynbox(const char *name, const char *fmt, ...)
6
{
7
    char buf[2048];
8
    char c;
9
    va_list va;
10
 
11
    UNREFERENCED_PARAMETER(name);
12
 
13
    va_start(va, fmt);
14
    vsprintf(buf, fmt, va);
15
    va_end(va);
16
 
17
#if defined __APPLE__
18
    return osx_ynbox(name, buf);
19
#elif defined HAVE_GTK2
20
    {
21
        int32_t r = gtkbuild_ynbox(name, buf);
22
        if (r >= 0)
23
            return r;
24
    }
25
#endif
26
 
27
    // NOTE: this is dead code for most #ifdef cases above.
28
    puts(buf);
29
    puts("   (type 'Y' or 'N', and press Return or Enter to continue)");
30
    do c = getchar(); while (c != 'Y' && c != 'y' && c != 'N' && c != 'n');
31
    if (c == 'Y' || c == 'y') return 1;
32
 
33
    return 0;
34
}
35
 
4774 hendricks2 36
#ifdef _WIN32
37
HWND win_gethwnd(void)
38
{
39
    struct SDL_SysWMinfo wmInfo;
40
    SDL_VERSION(&wmInfo.version);
41
 
42
    if (SDL_GetWMInfo(&wmInfo) != 1)
43
    {
44
        initprintf("win_gethwnd: SDL_GetWindowWMInfo() failed: %s\n", SDL_GetError());
45
        return 0;
46
    }
47
 
48
    return wmInfo.window;
49
}
50
#endif
51
 
4749 terminx 52
#ifdef USE_OPENGL
53
void setvsync(int32_t sync)
54
{
55
    if (vsync_render == sync) return;
56
    vsync_render = sync;
57
 
58
    resetvideomode();
59
    if (setgamemode(fullscreen, xdim, ydim, bpp))
60
        OSD_Printf("restartvid: Reset failed...\n");
61
}
62
#endif
63
 
64
int32_t sdlayer_checkversion(void)
65
{
66
    const SDL_version *linked = SDL_Linked_Version();
67
    SDL_version compiled;
68
 
69
    SDL_VERSION(&compiled);
70
 
71
    initprintf("Initializing SDL system interface "
72
               "(compiled against SDL version %d.%d.%d, found version %d.%d.%d)\n",
73
               compiled.major, compiled.minor, compiled.patch, linked->major, linked->minor, linked->patch);
74
 
75
    if (SDL_VERSIONNUM(linked->major, linked->minor, linked->patch) < SDL_REQUIREDVERSION)
76
    {
77
        /*reject running under SDL versions older than what is stated in sdl_inc.h */
78
        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);
79
        return -1;
80
    }
81
 
82
    return 0;
83
}
84
 
85
//
86
// initsystem() -- init SDL systems
87
//
88
int32_t initsystem(void)
89
{
90
#if defined NOSDLPARACHUTE
91
    const int sdlinitflags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
92
#else
93
    const int sdlinitflags = SDL_INIT_VIDEO;
94
#endif
95
 
96
    mutex_init(&m_initprintf);
97
 
98
    if (sdlayer_checkversion())
99
        return -1;
100
 
101
    if (SDL_Init(sdlinitflags))
102
    {
103
        initprintf("Initialization failed! (%s)\nNon-interactive mode enabled\n", SDL_GetError());
104
        novideo = 1;
105
#ifdef USE_OPENGL
106
        nogl = 1;
107
#endif
108
    }
109
 
110
    atexit(uninitsystem);
111
 
112
    frameplace = 0;
113
    lockcount = 0;
114
 
115
 
116
    if (!novideo)
117
    {
118
        char drvname[32];
119
 
120
#ifdef USE_OPENGL
121
        if (loadgldriver(getenv("BUILD_GLDRV")))
122
        {
123
            initprintf("Failed loading OpenGL driver. GL modes will be unavailable.\n");
124
            nogl = 1;
125
        }
126
#endif
127
 
128
        if (SDL_VideoDriverName(drvname, 32))
129
            initprintf("Using \"%s\" video driver\n", drvname);
130
 
131
        wm_setapptitle(apptitle);
132
    }
133
 
134
    return 0;
135
}
136
 
137
#ifdef GEKKO
138
static const char *joynames[3][15] = {
139
        {
140
            "Left Stick X", "Left Stick Y", "Right Stick X", "Right Stick Y", "Axis 5", "Axis 6", "Axis 7", "Axis 8",
141
            "Axis 9", "Axis 10", "Axis 11", "Axis 12", "Axis 13", "Axis 14", "Axis 15",
142
        },
143
        {
144
            "Button A", "Button B", "Button 1", "Button 2", "Button -", "Button +", "Button HOME", "Button Z", "Button C",
145
            "Button X", "Button Y", "Trigger L", "Trigger R", "Trigger ZL", "Trigger ZR",
146
        },
147
        {
148
            "D-Pad Up", "D-Pad Right", "D-Pad Down", "D-Pad Left", "Hat 5", "Hat 6", "Hat 7", "Hat 8", "Hat 9", "Hat 10",
149
            "Hat 11", "Hat 12", "Hat 13", "Hat 14", "Hat 15",
150
        }
151
};
152
const char *getjoyname(int32_t what, int32_t num)
153
{
154
    switch (what)
155
    {
156
        case 0: // axis
157
            if ((unsigned)num > (unsigned)joynumaxes) return NULL;
158
            return joynames[0][num];
159
 
160
        case 1: // button
161
            if ((unsigned)num > (unsigned)joynumbuttons) return NULL;
162
            return joynames[1][num];
163
 
164
        case 2: // hat
165
            if ((unsigned)num > (unsigned)joynumhats) return NULL;
166
            return joynames[2][num];
167
 
168
        default:
169
            return NULL;
170
    }
171
}
172
#endif
173
 
174
//
175
// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state).
176
//                    furthermore return 0 if successful.
177
//
178
 
179
static inline char grabmouse_low(char a)
180
{
181
#if (!defined DEBUGGINGAIDS || defined __APPLE__)
182
    SDL_ShowCursor(a ? SDL_DISABLE : SDL_ENABLE);
183
    return (SDL_WM_GrabInput(a ? SDL_GRAB_ON : SDL_GRAB_OFF) != (a ? SDL_GRAB_ON : SDL_GRAB_OFF));
184
#else
185
    UNREFERENCED_PARAMETER(a);
186
    return 0;
187
#endif
188
}
189
 
190
// high-resolution timers for profiling
191
uint64_t getu64ticks(void)
192
{
4774 hendricks2 193
# if defined _WIN32
194
    return win_getu64ticks();
195
# elif defined __APPLE__
4749 terminx 196
    return mach_absolute_time();
197
# elif _POSIX_TIMERS>0 && defined _POSIX_MONOTONIC_CLOCK
198
    // This is SDL HG's SDL_GetPerformanceCounter() when clock_gettime() is
199
    // available.
200
    uint64_t ticks;
201
    struct timespec now;
202
 
203
    clock_gettime(CLOCK_MONOTONIC, &now);
204
    ticks = now.tv_sec;
205
    ticks *= 1000000000;
206
    ticks += now.tv_nsec;
207
    return ticks;
208
# elif defined GEKKO
209
    return ticks_to_nanosecs(gettime());
210
# else
211
    // Blar. This pragma is unsupported on earlier GCC versions.
212
    // At least we'll get a warning and a reference to this line...
213
#  pragma message "Using low-resolution (1ms) timer for getu64ticks. Profiling will work badly."
214
    return SDL_GetTicks();
215
# endif
216
}
217
 
218
uint64_t getu64tickspersec(void)
219
{
220
# if defined __APPLE__
221
    static mach_timebase_info_data_t ti;
222
    if (ti.denom == 0)
223
        (void) mach_timebase_info(&ti);  // ti.numer/ti.denom: nsec/(m_a_t() tick)
224
    return (1000000000LL*ti.denom)/ti.numer;
225
# elif _POSIX_TIMERS>0 && defined _POSIX_MONOTONIC_CLOCK
226
    return 1000000000;
227
# elif defined GEKKO
228
    return TB_NSPERSEC;
229
# else
230
    return 1000;
231
# endif
232
}
233
 
234
void getvalidmodes(void)
235
{
236
    int32_t i, maxx = 0, maxy = 0;
237
    int32_t j;
238
    static int32_t cdepths[] = { 8,
239
#ifdef USE_OPENGL
240
                                 16, 24, 32,
241
#endif
242
 
243
    SDL_Rect **modes;
244
    SDL_PixelFormat pf;
245
 
246
    pf.palette = NULL;
247
    pf.BitsPerPixel = 8;
248
    pf.BytesPerPixel = 1;
249
 
250
    if (modeschecked || novideo)
251
        return;
252
 
253
    validmodecnt = 0;
254
    //    initprintf("Detecting video modes:\n");
255
 
256
    // do fullscreen modes first
257
    for (j = 0; cdepths[j]; j++)
258
    {
259
#ifdef USE_OPENGL
260
        if (nogl && cdepths[j] > 8)
261
            continue;
262
#endif
263
        pf.BitsPerPixel = cdepths[j];
264
        pf.BytesPerPixel = cdepths[j] >> 3;
265
 
266
        // We convert paletted contents to non-paletted
267
        modes = SDL_ListModes((cdepths[j] == 8) ? NULL : &pf, SURFACE_FLAGS | SDL_FULLSCREEN);
268
 
269
        if (modes == (SDL_Rect **)0)
270
        {
271
            if (cdepths[j] > 8)
272
                cdepths[j] = -1;
273
            continue;
274
        }
275
 
276
        if (modes == (SDL_Rect **)-1)
277
        {
278
            for (i = 0; defaultres[i][0]; i++)
279
                SDL_ADDMODE(defaultres[i][0], defaultres[i][1], cdepths[j], 1);
280
        }
281
        else
282
        {
283
            for (i = 0; modes[i]; i++)
284
            {
285
                if ((modes[i]->w > MAXXDIM) || (modes[i]->h > MAXYDIM))
286
                    continue;
287
 
288
                SDL_ADDMODE(modes[i]->w, modes[i]->h, cdepths[j], 1);
289
 
290
                if ((modes[i]->w > maxx) || (modes[i]->h > maxy))
291
                {
292
                    maxx = modes[i]->w;
293
                    maxy = modes[i]->h;
294
                }
295
            }
296
        }
297
    }
298
 
299
    SDL_CHECKFSMODES(maxx, maxy);
300
 
301
    // add windowed modes next
302
    for (j = 0; cdepths[j]; j++)
303
    {
304
#ifdef USE_OPENGL
305
        if (nogl && cdepths[j] > 8)
306
            continue;
307
#endif
308
        if (cdepths[j] < 0)
309
            continue;
310
 
311
        for (i = 0; defaultres[i][0]; i++)
312
        {
313
            if (!SDL_CHECKMODE(defaultres[i][0], defaultres[i][1]))
314
                continue;
315
 
316
            SDL_ADDMODE(defaultres[i][0], defaultres[i][1], cdepths[j], 0);
317
        }
318
    }
319
 
320
    qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes);
321
 
322
    modeschecked = 1;
323
}
324
 
325
//
326
// setvideomode() -- set SDL video mode
327
//
328
int32_t setvideomode(int32_t x, int32_t y, int32_t c, int32_t fs)
329
{
330
    int32_t regrab = 0, ret;
331
#ifdef USE_OPENGL
332
    static int32_t ovsync = 1;
333
#endif
334
 
335
    ret = setvideomode_sdlcommon(&x, &y, c, fs, &regrab);
336
    if (ret != 1) return ret;
337
 
338
    // restore gamma before we change video modes if it was changed
339
    if (sdl_surface && gammabrightness)
340
    {
341
        SDL_SetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]);
342
        gammabrightness = 0;  // redetect on next mode switch
343
    }
344
 
345
    // deinit
346
    destroy_window_resources();
347
 
348
    initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
349
 
350
#ifdef USE_OPENGL
351
    if (c > 8)
352
    {
353
        int32_t i, j, multisamplecheck = (glmultisample > 0);
354
 
355
        if (nogl)
356
            return -1;
357
 
4769 hendricks2 358
        struct glattribs
359
        {
360
            SDL_GLattr attr;
361
            int32_t value;
362
        } sdlayer_gl_attributes [] =
363
        {
364
            { SDL_GL_DOUBLEBUFFER, 1 },
365
            { SDL_GL_MULTISAMPLEBUFFERS, glmultisample > 0 },
366
            { SDL_GL_MULTISAMPLESAMPLES, glmultisample },
367
            { SDL_GL_STENCIL_SIZE, 1 },
368
            { SDL_GL_ACCELERATED_VISUAL, 1 },
369
            { SDL_GL_SWAP_CONTROL, vsync_render },
370
        };
371
 
4749 terminx 372
        do
373
        {
374
            SDL_GL_ATTRIBUTES(i, sdlayer_gl_attributes);
375
 
376
            /* HACK: changing SDL GL attribs only works before surface creation,
377
               so we have to create a new surface in a different format first
378
               to force the surface we WANT to be recreated instead of reused. */
379
            if (vsync_render != ovsync)
380
            {
381
                if (sdl_surface)
382
                {
383
                    SDL_FreeSurface(sdl_surface);
384
                    sdl_surface =
385
                    SDL_SetVideoMode(1, 1, 8, SDL_NOFRAME | SURFACE_FLAGS | ((fs & 1) ? SDL_FULLSCREEN : 0));
386
                    SDL_FreeSurface(sdl_surface);
387
                }
388
                ovsync = vsync_render;
389
            }
390
            sdl_surface = SDL_SetVideoMode(x, y, c, SDL_OPENGL | ((fs & 1) ? SDL_FULLSCREEN : 0));
391
            if (!sdl_surface)
392
            {
393
                if (multisamplecheck)
394
                {
395
                    initprintf("Multisample mode not possible. Retrying without multisampling.\n");
396
                    glmultisample = 0;
397
                    continue;
398
                }
399
                initprintf("Unable to set video mode!\n");
400
                return -1;
401
            }
402
 
403
        } while (multisamplecheck--);
404
    }
405
    else
406
#endif  // defined USE_OPENGL
407
    {
408
        // We convert paletted contents to non-paletted
409
        sdl_surface = SDL_SetVideoMode(x, y, 0, SURFACE_FLAGS | ((fs & 1) ? SDL_FULLSCREEN : 0));
410
        if (!sdl_surface)
411
        {
412
            initprintf("Unable to set video mode!\n");
413
            return -1;
414
        }
415
        sdl_buffersurface = SDL_CreateRGBSurface(SURFACE_FLAGS, x, y, c, 0, 0, 0, 0);
416
        if (!sdl_buffersurface)
417
        {
418
            initprintf("Unable to set video mode: SDL_CreateRGBSurface failed: %s\n", SDL_GetError());
419
            return -1;
420
        }
421
    }
422
 
423
    setvideomode_sdlcommonpost(x, y, c, fs, regrab);
424
 
425
    return 0;
426
}
427
 
428
//
429
// showframe() -- update the display
430
//
431
void showframe(int32_t w)
432
{
433
    UNREFERENCED_PARAMETER(w);
434
 
435
#ifdef USE_OPENGL
436
    if (bpp > 8)
437
    {
438
        if (palfadedelta)
439
            fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
440
 
441
        SDL_GL_SwapBuffers();
442
        return;
443
    }
444
#endif
445
 
446
    if (offscreenrendering) return;
447
 
448
    if (lockcount)
449
    {
450
        printf("Frame still locked %d times when showframe() called.\n", lockcount);
451
        while (lockcount) enddrawing();
452
    }
453
 
454
    // deferred palette updating
455
    if (needpalupdate)
456
    {
457
        SDL_SetColors(sdl_buffersurface, sdlayer_pal, 0, 256);
458
        needpalupdate = 0;
459
    }
460
 
461
    SDL_BlitSurface(sdl_buffersurface, NULL, sdl_surface, NULL);
462
    SDL_Flip(sdl_surface);
463
}
464
 
465
 
466
// SDL 1.2 specific event handling
467
int32_t handleevents_pollsdl(void)
468
{
469
    int32_t code, rv = 0, j;
470
    SDL_Event ev;
471
 
472
    while (SDL_PollEvent(&ev))
473
    {
474
        switch (ev.type)
475
        {
476
            case SDL_KEYDOWN:
477
            case SDL_KEYUP:
478
                code = keytranslation[ev.key.keysym.sym];
479
#ifdef KEY_PRINT_DEBUG
480
                printf("keytranslation[%d] = %s (%d)  %s\n", ev.key.keysym.sym, key_names[code], code,
481
                       ev.key.type == SDL_KEYDOWN ? "DOWN" : "UP");
482
#endif
483
                if (code != OSD_OSDKey() && ev.key.keysym.unicode != 0 && ev.key.type == SDL_KEYDOWN &&
484
                    (ev.key.keysym.unicode & 0xff80) == 0 && !keyascfifo_isfull())
485
                {
486
                    if (OSD_HandleChar(ev.key.keysym.unicode & 0x7f))
487
                        keyascfifo_insert(ev.key.keysym.unicode & 0x7f);
488
                }
489
 
490
                // hook in the osd
491
                if ((j = OSD_HandleScanCode(code, (ev.key.type == SDL_KEYDOWN))) <= 0)
492
                {
493
                    if (j == -1)  // osdkey
494
                    {
495
                        for (j = 0; j < KEYSTATUSSIZ; ++j)
496
                        {
497
                            if (GetKey(j))
498
                            {
499
                                SetKey(j, 0);
500
                                if (keypresscallback)
501
                                    keypresscallback(j, 0);
502
                            }
503
                        }
504
                    }
505
                    break;
506
                }
507
 
508
                if (ev.key.type == SDL_KEYDOWN)
509
                {
510
                    if (!GetKey(code))
511
                    {
512
                        SetKey(code, 1);
513
                        if (keypresscallback)
514
                            keypresscallback(code, 1);
515
                    }
516
                }
517
                else
518
                {
519
#ifdef __linux
520
                    if (code == 0x59)  // pause
521
                        break;
522
#endif
523
                    SetKey(code, 0);
524
                    if (keypresscallback)
525
                        keypresscallback(code, 0);
526
                }
527
                break;
528
 
529
            case SDL_ACTIVEEVENT:
530
                if (ev.active.state & SDL_APPINPUTFOCUS)
531
                {
532
                    appactive = ev.active.gain;
533
#if !defined DEBUGGINGAIDS
534
                    if (mousegrab && moustat)
535
                        grabmouse_low(!!appactive);
536
#endif
537
                    rv = -1;
4753 terminx 538
 
539
                    if (ev.active.state & SDL_APPMOUSEFOCUS)
540
                        mouseinwindow = ev.active.gain;
4749 terminx 541
                }
542
                break;
543
 
544
            // SDL_MOUSEMOTION needs to fall through to default... this is just GEKKO processing!
545
            case SDL_MOUSEMOTION:
546
#ifdef GEKKO
4753 terminx 547
                // check if it's a wiimote pointer pretending to be a mouse
548
                if (ev.motion.state & SDL_BUTTON_X2MASK)
4749 terminx 549
                {
4753 terminx 550
                    // the absolute values are used to draw the crosshair
551
                    mouseabsx = ev.motion.x;
552
                    mouseabsy = ev.motion.y;
553
                    // hack: reduce the scale of the "relative" motions
554
                    // to make it act more like a real mouse
555
                    ev.motion.xrel /= 16;
556
                    ev.motion.yrel /= 12;
4749 terminx 557
                }
558
#endif
559
            default: // OSD_Printf("Got event (%d)\n", ev.type); break;
560
                rv = handleevents_sdlcommon(&ev);
561
                break;
562
        }
563
    }
564
 
565
    return rv;
566
}
567
 
568
// from SDL HG, modified
569
int32_t SDL_WaitEventTimeout(SDL_Event *event, int32_t timeout)
570
{
571
    uint32_t expiration = 0;
572
 
573
    if (timeout > 0)
574
        expiration = SDL_GetTicks() + timeout;
575
 
576
    for (;;)
577
    {
578
        SDL_PumpEvents();
579
        switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, ~0))  // SDL_FIRSTEVENT, SDL_LASTEVENT)) {
580
        {
581
            case -1: return 0;
582
            case 1: return 1;
583
            case 0:
584
                if (timeout == 0)
585
                {
586
                    /* Polling and no events, just return */
587
                    return 0;
588
                }
589
                if (timeout > 0 && ((int32_t)(SDL_GetTicks() - expiration) >= 0))
590
                {
591
                    /* Timeout expired and no events */
592
                    return 0;
593
                }
594
                SDL_Delay(10);
595
                break;
596
        }
597
    }
598
}