Subversion Repositories eduke32

Rev

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

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