src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 18 Feb 2019 00:43:28 -0500
changeset 71 7a5593f0cd40
parent 70 aa6bf2a4a8c3
child 72 d20d9d70694b
permissions -rw-r--r--
Actually, just force the renderer to be SDL_DOUBLEBUF for now.

If this ends up being a problem, the dirty rect code is in revision control.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* This file contains functions for backwards compatibility with SDL 1.2 */
    23 
    24 // !!! FIXME: clean up code conventions
    25 // !!! FIXME: grep for VideoWindow20 places that might care if it's NULL
    26 
    27 #include "SDL20_include_wrapper.h"
    28 
    29 #if !SDL_VERSION_ATLEAST(2,0,0)
    30 #error You need to compile against SDL 2.0 headers.
    31 #endif
    32 
    33 /*
    34  * We report the library version as 1.2.$(SDL12_COMPAT_VERSION). This number
    35  *  should be way ahead of what SDL-1.2 Classic would report, so apps can
    36  *  decide if they're running under the compat layer, if they really care.
    37  */
    38 #define SDL12_COMPAT_VERSION 50
    39 
    40 #include <stdarg.h>
    41 
    42 // !!! IMPLEMENT_ME SDL_CDClose
    43 // !!! IMPLEMENT_ME SDL_CDEject
    44 // !!! IMPLEMENT_ME SDL_CDName
    45 // !!! IMPLEMENT_ME SDL_CDNumDrives
    46 // !!! IMPLEMENT_ME SDL_CDOpen
    47 // !!! IMPLEMENT_ME SDL_CDPause
    48 // !!! IMPLEMENT_ME SDL_CDPlay
    49 // !!! IMPLEMENT_ME SDL_CDPlayTracks
    50 // !!! IMPLEMENT_ME SDL_CDResume
    51 // !!! IMPLEMENT_ME SDL_CDStatus
    52 // !!! IMPLEMENT_ME SDL_CDStop
    53 // !!! IMPLEMENT_ME SDL_CreateYUVOverlay
    54 
    55 // !!! IMPLEMENT_ME SDL_DisplayFormatAlpha
    56 // !!! IMPLEMENT_ME SDL_DisplayYUVOverlay
    57 // !!! IMPLEMENT_ME SDL_EnableKeyRepeat
    58 // !!! IMPLEMENT_ME SDL_EnableUNICODE
    59 // !!! IMPLEMENT_ME SDL_FreeYUVOverlay
    60 
    61 // !!! IMPLEMENT_ME SDL_GL_Lock
    62 // !!! IMPLEMENT_ME SDL_GL_Unlock
    63 // !!! IMPLEMENT_ME SDL_GL_UpdateRects
    64 
    65 // !!! IMPLEMENT_ME SDL_GetKeyName
    66 // !!! IMPLEMENT_ME SDL_GetKeyState
    67 // !!! IMPLEMENT_ME SDL_GetModState
    68 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    69 
    70 // !!! IMPLEMENT_ME SDL_GetVideoSurface
    71 // !!! IMPLEMENT_ME SDL_GetWMInfo
    72 
    73 // !!! IMPLEMENT_ME SDL_LockSurface
    74 // !!! IMPLEMENT_ME SDL_LockYUVOverlay
    75 // !!! IMPLEMENT_ME SDL_LowerBlit
    76 
    77 // !!! IMPLEMENT_ME SDL_SetAlpha
    78 // !!! IMPLEMENT_ME SDL_SetColorKey
    79 // !!! IMPLEMENT_ME SDL_SetColors
    80 
    81 // !!! IMPLEMENT_ME SDL_SetModState
    82 // !!! IMPLEMENT_ME SDL_SetPalette
    83 // !!! IMPLEMENT_ME SDL_SetVideoMode
    84 // !!! IMPLEMENT_ME SDL_SoftStretch
    85 // !!! IMPLEMENT_ME SDL_UnlockSurface
    86 // !!! IMPLEMENT_ME SDL_UnlockYUVOverlay
    87 // !!! IMPLEMENT_ME SDL_UpdateRects
    88 // !!! IMPLEMENT_ME SDL_UpperBlit
    89 
    90 // !!! FIXME: should SDL_VideoInit really be a passthrough?
    91 // !!! FIXME: should SDL_VideoQuit really be a passthrough?
    92 
    93 // !!! IMPLEMENT_ME SDL_WM_SetIcon
    94 // !!! IMPLEMENT_ME SDL_WM_ToggleFullScreen
    95 
    96 // !!! IMPLEMENT_ME X11_KeyToUnicode
    97 
    98 #define SDL_BlitSurface SDL_UpperBlit
    99 
   100 
   101 #if 0
   102 #define FIXME(x) do {} while (0)
   103 #else
   104 #define FIXME(x) \
   105     do { \
   106         static SDL_bool seen = SDL_FALSE; \
   107         if (!seen) { \
   108             fprintf(stderr, "FIXME: %s (%s:%d)\n", x, __FILE__, __LINE__); \
   109             seen = SDL_TRUE; \
   110         } \
   111     } while (0)
   112 #endif
   113 
   114 #define SDL20_SYM(rc,fn,params,args,ret) \
   115     typedef rc (SDLCALL *SDL20_##fn##_t) params; \
   116     static SDL20_##fn##_t SDL20_##fn = NULL;
   117 #include "SDL20_syms.h"
   118 
   119 /* Things that _should_ be binary compatible pass right through... */
   120 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
   121     DECLSPEC rc SDLCALL SDL_##fn params { ret SDL20_##fn args; }
   122 #include "SDL20_syms.h"
   123 
   124 
   125 /* these are macros (etc) in the SDL headers, so make our own. */
   126 #define SDL20_OutOfMemory() SDL20_Error(SDL_ENOMEM)
   127 #define SDL20_Unsupported() SDL20_Error(SDL_UNSUPPORTED)
   128 #define SDL20_InvalidParamError(param) SDL20_SetError("Parameter '%s' is invalid", (param))
   129 #define SDL20_zero(x) SDL20_memset(&(x), 0, sizeof((x)))
   130 #define SDL20_zerop(x) SDL20_memset((x), 0, sizeof(*(x)))
   131 #define SDL_ReportAssertion SDL20_ReportAssertion
   132 
   133 #define SDL12_DEFAULT_REPEAT_DELAY 500
   134 #define SDL12_DEFAULT_REPEAT_INTERVAL 30
   135 
   136 #define SDL12_INIT_TIMER       0x00000001
   137 #define SDL12_INIT_AUDIO       0x00000010
   138 #define SDL12_INIT_VIDEO       0x00000020
   139 #define SDL12_INIT_CDROM       0x00000100
   140 #define SDL12_INIT_JOYSTICK    0x00000200
   141 #define SDL12_INIT_NOPARACHUTE 0x00100000
   142 #define SDL12_INIT_EVENTTHREAD 0x01000000
   143 #define SDL12_INIT_EVERYTHING  0x0000FFFF
   144 
   145 typedef struct SDL12_Palette
   146 {
   147     int       ncolors;
   148     SDL_Color *colors;
   149 } SDL12_Palette;
   150 
   151 typedef struct SDL12_PixelFormat
   152 {
   153     SDL12_Palette *palette;
   154     Uint8 BitsPerPixel;
   155     Uint8 BytesPerPixel;
   156     Uint8 Rloss;
   157     Uint8 Gloss;
   158     Uint8 Bloss;
   159     Uint8 Aloss;
   160     Uint8 Rshift;
   161     Uint8 Gshift;
   162     Uint8 Bshift;
   163     Uint8 Ashift;
   164     Uint32 Rmask;
   165     Uint32 Gmask;
   166     Uint32 Bmask;
   167     Uint32 Amask;
   168     Uint32 colorkey;
   169     Uint8 alpha;
   170 } SDL12_PixelFormat;
   171 
   172 typedef struct SDL12_Surface
   173 {
   174     Uint32 flags;
   175     SDL12_PixelFormat *format;
   176     int w;
   177     int h;
   178     Uint16 pitch;
   179     void *pixels;
   180     int offset;
   181     SDL_Surface *surface20; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here named "hwdata". */
   182     SDL_Rect clip_rect;
   183     Uint32 unused1;
   184     Uint32 locked;
   185     void *blitmap;
   186     unsigned int format_version;
   187     int refcount;
   188 } SDL12_Surface;
   189 
   190 typedef struct SDL12_Overlay
   191 {
   192     Uint32 format;
   193     int w;
   194     int h;
   195     int planes;
   196     Uint16 *pitches;
   197     Uint8 **pixels;
   198     void *hwfuncs;
   199     void *hwdata;
   200     Uint32 hw_overlay :1;
   201     Uint32 UnusedBits :31;
   202 } SDL12_Overlay;
   203 
   204 typedef struct
   205 {
   206     Uint32 hw_available :1;
   207     Uint32 wm_available :1;
   208     Uint32 UnusedBits1  :6;
   209     Uint32 UnusedBits2  :1;
   210     Uint32 blit_hw      :1;
   211     Uint32 blit_hw_CC   :1;
   212     Uint32 blit_hw_A    :1;
   213     Uint32 blit_sw      :1;
   214     Uint32 blit_sw_CC   :1;
   215     Uint32 blit_sw_A    :1;
   216     Uint32 blit_fill    :1;
   217     Uint32 UnusedBits3  :16;
   218     Uint32 video_mem;
   219     SDL_PixelFormat *vfmt;
   220     int current_w;
   221     int current_h;
   222 } SDL12_VideoInfo;
   223 
   224 
   225 #define SDL12_HWSURFACE 0x00000001
   226 #define SDL12_ASYNCBLIT 0x00000004
   227 #define SDL12_ANYFORMAT 0x10000000
   228 #define SDL12_HWPALETTE 0x20000000
   229 #define SDL12_DOUBLEBUF 0x40000000
   230 #define SDL12_FULLSCREEN 0x80000000
   231 #define SDL12_OPENGL 0x00000002
   232 #define SDL12_OPENGLBLIT 0x0000000A
   233 #define SDL12_RESIZABLE 0x00000010
   234 #define SDL12_NOFRAME 0x00000020
   235 #define SDL12_HWACCEL 0x00000100
   236 #define SDL12_SRCCOLORKEY 0x00001000
   237 #define SDL12_RLEACCELOK 0x00002000
   238 #define SDL12_RLEACCEL 0x00004000
   239 #define SDL12_SRCALPHA 0x00010000
   240 #define SDL12_PREALLOC 0x01000000
   241 
   242 typedef enum
   243 {
   244     SDL12_NOEVENT = 0,
   245     SDL12_ACTIVEEVENT,
   246     SDL12_KEYDOWN,
   247     SDL12_KEYUP,
   248     SDL12_MOUSEMOTION,
   249     SDL12_MOUSEBUTTONDOWN,
   250     SDL12_MOUSEBUTTONUP,
   251     SDL12_JOYAXISMOTION,
   252     SDL12_JOYBALLMOTION,
   253     SDL12_JOYHATMOTION,
   254     SDL12_JOYBUTTONDOWN,
   255     SDL12_JOYBUTTONUP,
   256     SDL12_QUIT,
   257     SDL12_SYSWMEVENT,
   258     SDL12_EVENT_RESERVEDA,
   259     SDL12_EVENT_RESERVEDB,
   260     SDL12_VIDEORESIZE,
   261     SDL12_VIDEOEXPOSE,
   262     SDL12_USEREVENT = 24,
   263     SDL12_NUMEVENTS = 32
   264 } SDL12_EventType;
   265 
   266 
   267 #define SDL12_APPMOUSEFOCUS (1<<0)
   268 #define SDL12_APPINPUTFOCUS (1<<1)
   269 #define SDL12_APPACTIVE     (1<<2)
   270 
   271 typedef struct
   272 {
   273     Uint8 type;
   274     Uint8 gain;
   275     Uint8 state;
   276 } SDL12_ActiveEvent;
   277 
   278 typedef struct
   279 {
   280     Uint8 type;
   281     Uint8 which;
   282     Uint8 state;
   283     //FIXME: SDL12_keysym keysym;
   284 } SDL12_KeyboardEvent;
   285 
   286 typedef struct
   287 {
   288     Uint8 type;
   289     Uint8 which;
   290     Uint8 state;
   291     Uint16 x, y;
   292     Sint16 xrel;
   293     Sint16 yrel;
   294 } SDL12_MouseMotionEvent;
   295 
   296 typedef struct
   297 {
   298     Uint8 type;
   299     Uint8 which;
   300     Uint8 button;
   301     Uint8 state;
   302     Uint16 x, y;
   303 } SDL12_MouseButtonEvent;
   304 
   305 typedef struct
   306 {
   307     Uint8 type;
   308     Uint8 which;
   309     Uint8 axis;
   310     Sint16 value;
   311 } SDL12_JoyAxisEvent;
   312 
   313 typedef struct
   314 {
   315     Uint8 type;
   316     Uint8 which;
   317     Uint8 ball;
   318     Sint16 xrel;
   319     Sint16 yrel;
   320 } SDL12_JoyBallEvent;
   321 
   322 typedef struct
   323 {
   324     Uint8 type;
   325     Uint8 which;
   326     Uint8 hat;
   327     Uint8 value;
   328 } SDL12_JoyHatEvent;
   329 
   330 typedef struct
   331 {
   332     Uint8 type;
   333     Uint8 which;
   334     Uint8 button;
   335     Uint8 state;
   336 } SDL12_JoyButtonEvent;
   337 
   338 typedef struct
   339 {
   340     Uint8 type;
   341     int w;
   342     int h;
   343 } SDL12_ResizeEvent;
   344 
   345 typedef struct
   346 {
   347     Uint8 type;
   348 } SDL12_ExposeEvent;
   349 
   350 typedef struct
   351 {
   352     Uint8 type;
   353 } SDL12_QuitEvent;
   354 
   355 typedef struct
   356 {
   357     Uint8 type;
   358     int code;
   359     void *data1;
   360     void *data2;
   361 } SDL12_UserEvent;
   362 
   363 typedef struct
   364 {
   365     Uint8 type;
   366     void *msg;
   367 } SDL12_SysWMEvent;
   368 
   369 typedef union
   370 {
   371     Uint8 type;
   372     SDL12_ActiveEvent active;
   373     SDL12_KeyboardEvent key;
   374     SDL12_MouseMotionEvent motion;
   375     SDL12_MouseButtonEvent button;
   376     SDL12_JoyAxisEvent jaxis;
   377     SDL12_JoyBallEvent jball;
   378     SDL12_JoyHatEvent jhat;
   379     SDL12_JoyButtonEvent jbutton;
   380     SDL12_ResizeEvent resize;
   381     SDL12_ExposeEvent expose;
   382     SDL12_QuitEvent quit;
   383     SDL12_UserEvent user;
   384     SDL12_SysWMEvent syswm;
   385 } SDL12_Event;
   386 
   387 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
   388 static int EventFilter20to12(void *data, SDL_Event *event20);
   389 
   390 typedef Uint32 (SDLCALL *SDL12_TimerCallback)(Uint32 interval);
   391 typedef SDL_TimerCallback SDL12_NewTimerCallback;
   392 
   393 typedef struct
   394 {
   395     SDL_Rect area;
   396     Sint16 hot_x;
   397     Sint16 hot_y;
   398     Uint8 *data;
   399     Uint8 *mask;
   400     Uint8 *save[2];
   401     SDL_Cursor *wm_cursor;  /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
   402 } SDL12_Cursor;
   403 
   404 typedef enum
   405 {
   406     SDL12_GL_RED_SIZE,
   407     SDL12_GL_GREEN_SIZE,
   408     SDL12_GL_BLUE_SIZE,
   409     SDL12_GL_ALPHA_SIZE,
   410     SDL12_GL_BUFFER_SIZE,
   411     SDL12_GL_DOUBLEBUFFER,
   412     SDL12_GL_DEPTH_SIZE,
   413     SDL12_GL_STENCIL_SIZE,
   414     SDL12_GL_ACCUM_RED_SIZE,
   415     SDL12_GL_ACCUM_GREEN_SIZE,
   416     SDL12_GL_ACCUM_BLUE_SIZE,
   417     SDL12_GL_ACCUM_ALPHA_SIZE,
   418     SDL12_GL_STEREO,
   419     SDL12_GL_MULTISAMPLEBUFFERS,
   420     SDL12_GL_MULTISAMPLESAMPLES,
   421     SDL12_GL_ACCELERATED_VISUAL,
   422     SDL12_GL_SWAP_CONTROL,
   423     SDL12_GL_MAX_ATTRIBUTE
   424 } SDL12_GLattr;
   425 
   426 
   427 typedef struct
   428 {
   429     Uint32 format;
   430     SDL_Rect *modeslist;
   431     SDL_Rect **modes;  /* ptrs to each item in modeslist, for SDL_ListModes() */
   432 } VideoModeList;
   433 
   434 // !!! FIXME: go through all of these.
   435 static VideoModeList *VideoModes = NULL;
   436 static int VideoModesCount = 0;
   437 static SDL12_VideoInfo VideoInfo12;
   438 static SDL_Window *VideoWindow20 = NULL;
   439 static SDL_Renderer *VideoRenderer20 = NULL;
   440 static SDL_Texture *VideoTexture20 = NULL;
   441 static SDL12_Surface *VideoSurface12 = NULL;
   442 static SDL_Surface *VideoConvertSurface20 = NULL;
   443 static SDL_GLContext *VideoGLContext20 = NULL;
   444 static char *WindowTitle = NULL;
   445 static char *WindowIconTitle = NULL;
   446 static SDL12_Surface *VideoIcon12;
   447 static int EnabledUnicode = 0;
   448 static int VideoDisplayIndex = 0;
   449 static int CDRomInit = 0;
   450 static SDL12_EventFilter EventFilter12 = NULL;
   451 static SDL12_Cursor *CurrentCursor12 = NULL;
   452 static Uint8 EventStates[SDL12_NUMEVENTS];
   453 static int SwapInterval = 0;
   454 
   455 // !!! FIXME: need a mutex for the event queue.
   456 #define SDL12_MAXEVENTS 128
   457 typedef struct EventQueueType
   458 {
   459     SDL12_Event event12;
   460     struct EventQueueType *next;
   461 } EventQueueType;
   462 
   463 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
   464 static EventQueueType *EventQueueHead = NULL;
   465 static EventQueueType *EventQueueTail = NULL;
   466 static EventQueueType *EventQueueAvailable = NULL;
   467 
   468 
   469 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   470 #if defined(_WINDOWS)
   471     #define WIN32_LEAN_AND_MEAN 1
   472     #include <windows.h>
   473     #define SDL20_LIBNAME "SDL2.dll"
   474     static HANDLE Loaded_SDL20 = NULL;
   475     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   476     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   477     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   478 #elif defined(unix) || defined(__APPLE__)
   479     #include <dlfcn.h>
   480     #ifdef __APPLE__
   481     #define SDL20_LIBNAME "libSDL2.dylib"
   482     #else
   483     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   484     #endif
   485     static void *Loaded_SDL20 = NULL;
   486     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL)) != NULL)
   487     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   488     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   489 #else
   490     #error Please define your platform.
   491 #endif
   492 
   493 static void *
   494 LoadSDL20Symbol(const char *fn, int *okay)
   495 {
   496     void *retval = NULL;
   497     if (*okay)  /* only bother trying if we haven't previously failed. */
   498     {
   499         retval = LookupSDL20Sym(fn);
   500 if (!retval) { fprintf(stderr, "WARNING: LOAD FAILED: %s\n", fn); }
   501 //        if (retval == NULL)
   502 //            *okay = 0;
   503     }
   504     return retval;
   505 }
   506 
   507 static void
   508 UnloadSDL20(void)
   509 {
   510     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   511     #include "SDL20_syms.h"
   512     CloseSDL20Library();
   513 }
   514 
   515 static int
   516 LoadSDL20(void)
   517 {
   518     int okay = 1;
   519     if (!Loaded_SDL20)
   520     {
   521         okay = LoadSDL20Library();
   522         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   523         #include "SDL20_syms.h"
   524         if (!okay)
   525             UnloadSDL20();
   526     }
   527     return okay;
   528 }
   529 
   530 DECLSPEC const SDL_version * SDLCALL
   531 SDL_Linked_Version(void)
   532 {
   533     static const SDL_version version = { 1, 2, SDL12_COMPAT_VERSION };
   534     return &version;
   535 }
   536 
   537 DECLSPEC int SDLCALL
   538 SDL_sscanf(const char *text, const char *fmt, ...)
   539 {
   540     int retval;
   541     va_list ap;
   542     va_start(ap, fmt);
   543     retval = (int) SDL20_sscanf(text, fmt, ap);
   544     va_end(ap);
   545     return retval;
   546 }
   547 
   548 DECLSPEC int SDLCALL
   549 SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
   550 {
   551     int retval;
   552     va_list ap;
   553     va_start(ap, fmt);
   554     retval = (int) SDL20_vsnprintf(text, maxlen, fmt, ap);
   555     va_end(ap);
   556     return retval;
   557 }
   558 
   559 DECLSPEC SDL_bool SDLCALL
   560 SDL_HasMMXExt(void)
   561 {
   562     /* this isn't accurate, but SDL2 doesn't have this for some reason.
   563         MMXExt is available in all SSE1 machines, except early Athlon chips,
   564         so we'll just say it's available if they have SSE1. Oh well. */
   565     return SDL20_HasSSE();
   566 }
   567 
   568 DECLSPEC SDL_bool SDLCALL
   569 SDL_Has3DNowExt(void)
   570 {
   571     FIXME("check this");
   572     return SDL20_HasSSE();
   573 }
   574 
   575 DECLSPEC int SDLCALL SDL_JoystickOpened(int device_index)
   576 {
   577     FIXME("write me");
   578     return 0;
   579 }
   580 
   581 static int
   582 GetVideoDisplay()
   583 {
   584     FIXME("cache this value during SDL_Init() so it doesn't change.");
   585     const char *variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
   586     if ( !variable ) {
   587         variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
   588     }
   589     if ( variable ) {
   590         return SDL20_atoi(variable);
   591     } else {
   592         return 0;
   593     }
   594 }
   595 
   596 /* This sets up VideoModes and VideoModesCount. You end up with arrays by pixel
   597     format, each with a value that 1.2's SDL_ListModes() can return. */
   598 static int
   599 Init12VidModes(void)
   600 {
   601     const int total = SDL20_GetNumDisplayModes(VideoDisplayIndex);
   602     VideoModeList *vmode = NULL;
   603     int num_modes = 0;
   604     void *ptr = NULL;
   605     int i, j;
   606 
   607     SDL_assert(VideoModes == NULL);
   608     SDL_assert(VideoModesCount == 0);
   609 
   610     for (i = 0; i < total; ++i) {
   611         SDL_DisplayMode mode;
   612 
   613         if (SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode) == -1) {
   614             continue;
   615         } else if (!mode.w || !mode.h) {
   616             SDL_assert(0 && "Can this actually happen?");
   617             continue;
   618         }
   619 
   620         if (!vmode || (mode.format != vmode->format)) {  // SDL20_GetDisplayMode() sorts on bpp first. We know when to change arrays.
   621             if (VideoModesCount > 0) {
   622                 VideoModes[VideoModesCount-1].modes[num_modes] = NULL;
   623             }
   624             ptr = (VideoModeList *) SDL20_realloc(VideoModes, sizeof (VideoModeList) * (VideoModesCount+1));
   625             if (!ptr) {
   626                 return SDL20_OutOfMemory();
   627             }
   628             VideoModes = (VideoModeList *) ptr;
   629             vmode = &VideoModes[VideoModesCount];
   630             vmode->format = mode.format;
   631             vmode->modeslist = NULL;
   632             vmode->modes = NULL;
   633             VideoModesCount++;
   634             num_modes = 0;
   635         }
   636 
   637         /* make sure we don't have this one already (with a different refresh rate, etc). */
   638         for (j = 0; j < num_modes; j++) {
   639             if ((vmode->modeslist[j].w == mode.w) && (vmode->modeslist[j].h == mode.h)) {
   640                 break;
   641             }
   642         }
   643 
   644         if (j < num_modes) {
   645             continue;  /* already have this one. */
   646         }
   647 
   648         ptr = SDL20_realloc(vmode->modes, sizeof (SDL_Rect *) * (num_modes + 2));
   649         if (ptr == NULL) {
   650             return SDL20_OutOfMemory();
   651         }
   652         vmode->modes = (SDL_Rect **) ptr;
   653 
   654         ptr = SDL20_realloc(vmode->modeslist, sizeof (SDL_Rect) * (num_modes + 1));
   655         if (ptr == NULL) {
   656             return SDL20_OutOfMemory();
   657         }
   658         vmode->modeslist = (SDL_Rect *) ptr;
   659 
   660         vmode->modeslist[num_modes].x = 0;
   661         vmode->modeslist[num_modes].y = 0;
   662         vmode->modeslist[num_modes].w = mode.w;
   663         vmode->modeslist[num_modes].h = mode.h;
   664 
   665         vmode->modes[num_modes] = &vmode->modeslist[num_modes];
   666 
   667         num_modes++;
   668     }
   669 
   670     if (VideoModesCount > 0) {
   671         VideoModes[VideoModesCount-1].modes[num_modes] = NULL;
   672     }
   673 
   674     return 0;
   675 }
   676 
   677 static int
   678 Init12Video(void)
   679 {
   680     int i;
   681 
   682     for (i = 0; i < SDL12_MAXEVENTS-1; i++)
   683         EventQueuePool[i].next = &EventQueuePool[i+1];
   684     EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
   685 
   686     EventQueueHead = EventQueueTail = NULL;
   687     EventQueueAvailable = EventQueuePool;
   688 
   689     SDL_memset(EventStates, SDL_ENABLE, sizeof (EventStates)); /* on by default */
   690     EventStates[SDL12_SYSWMEVENT] = SDL_IGNORE;  /* off by default. */
   691 
   692     SDL20_SetEventFilter(EventFilter20to12, NULL);
   693 
   694     VideoDisplayIndex = GetVideoDisplay();
   695     SwapInterval = 0;
   696 
   697     if (Init12VidModes() == -1) {
   698         return -1;
   699     }
   700 
   701     return 0;
   702 }
   703 
   704 
   705 DECLSPEC int SDLCALL
   706 SDL_InitSubSystem(Uint32 sdl12flags)
   707 {
   708     FIXME("there is never a parachute in SDL2, should we catch segfaults ourselves?");
   709 
   710     FIXME("support event thread where it makes sense to do so?");
   711 
   712 	if ( (sdl12flags & SDL12_INIT_EVENTTHREAD) == SDL12_INIT_EVENTTHREAD ) {
   713 		return SDL20_SetError("OS doesn't support threaded events");
   714 	}
   715 
   716     Uint32 sdl20flags = 0;
   717     int rc;
   718 
   719     if (!LoadSDL20())
   720         return -1;
   721 
   722 #ifdef __MACOSX__
   723     extern void sdl12_compat_macos_init(void);
   724     sdl12_compat_macos_init();
   725 #endif
   726 
   727     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   728     SETFLAG(TIMER);
   729     SETFLAG(AUDIO);
   730     SETFLAG(VIDEO);
   731     SETFLAG(JOYSTICK);
   732     SETFLAG(NOPARACHUTE);
   733     #undef SETFLAG
   734 
   735     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   736     if (sdl12flags & SDL12_INIT_CDROM)
   737         CDRomInit = 1;
   738 
   739     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   740 
   741     rc = SDL20_Init(sdl20flags);
   742     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO)) {
   743         if (Init12Video() == -1) {
   744             FIXME("should we deinit other subsystems?");
   745             return -1;
   746         }
   747     }
   748 
   749     return rc;
   750 }
   751 
   752 DECLSPEC int SDLCALL
   753 SDL_Init(Uint32 sdl12flags)
   754 {
   755     FIXME("what was different in 1.2?");
   756     return SDL_InitSubSystem(sdl12flags);   /* there's no difference betwee Init and InitSubSystem in SDL2. */
   757 }
   758 
   759 
   760 static void
   761 InitFlags12To20(const Uint32 flags12, Uint32 *_flags20, Uint32 *_extraflags)
   762 {
   763     Uint32 flags20 = 0;
   764     Uint32 extraflags = 0;
   765 
   766     #define SETFLAG(flag) if (flags12 & SDL12_INIT_##flag) flags20 |= SDL_INIT_##flag
   767     SETFLAG(TIMER);
   768     SETFLAG(AUDIO);
   769     SETFLAG(VIDEO);
   770     SETFLAG(JOYSTICK);
   771     SETFLAG(NOPARACHUTE);
   772     #undef SETFLAG
   773 
   774     if ((flags12 & SDL12_INIT_CDROM) && (CDRomInit)) {
   775         extraflags |= SDL12_INIT_CDROM;
   776     }
   777 
   778     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   779 
   780     *_flags20 = flags20;
   781     *_extraflags = extraflags;
   782 }
   783 
   784 static Uint32
   785 InitFlags20to12(const Uint32 flags20)
   786 {
   787     Uint32 flags12 = 0;
   788 
   789     #define SETFLAG(flag) if (flags20 & SDL_INIT_##flag) flags12 |= SDL12_INIT_##flag
   790     SETFLAG(TIMER);
   791     SETFLAG(AUDIO);
   792     SETFLAG(VIDEO);
   793     SETFLAG(JOYSTICK);
   794     SETFLAG(NOPARACHUTE);
   795     #undef SETFLAG
   796 
   797     return flags12;
   798 }
   799 
   800 
   801 DECLSPEC Uint32 SDLCALL
   802 SDL_WasInit(Uint32 sdl12flags)
   803 {
   804     Uint32 sdl20flags, extraflags;
   805     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
   806 
   807     return InitFlags20to12(SDL20_WasInit(sdl20flags)) | extraflags;
   808 }
   809 
   810 static void
   811 Quit12Video(void)
   812 {
   813     int i;
   814 
   815     for (i = 0; i < VideoModesCount; i++) {
   816         SDL20_free(VideoModes[i].modeslist);
   817         SDL20_free(VideoModes[i].modes);
   818     }
   819     SDL20_free(VideoModes);
   820 
   821     SDL20_FreeFormat(VideoInfo12.vfmt);
   822     SDL20_zero(VideoInfo12);
   823 
   824     EventFilter12 = NULL;
   825     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   826     CurrentCursor12 = NULL;
   827     VideoModes = NULL;
   828     VideoModesCount = 0;
   829 }
   830 
   831 DECLSPEC void SDLCALL
   832 SDL_QuitSubSystem(Uint32 sdl12flags)
   833 {
   834     Uint32 sdl20flags, extraflags;
   835     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
   836 
   837     if (extraflags & SDL12_INIT_CDROM) {
   838         CDRomInit = 0;
   839     }
   840 
   841     FIXME("reset a bunch of other global variables too.");
   842     if (sdl12flags & SDL12_INIT_VIDEO) {
   843         Quit12Video();
   844     }
   845 
   846     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   847     SDL20_QuitSubSystem(sdl20flags);
   848 
   849     if ((SDL20_WasInit(0) == 0) && (!CDRomInit)) {
   850         SDL20_Quit();
   851         UnloadSDL20();
   852     }
   853 }
   854 
   855 DECLSPEC void SDLCALL
   856 SDL_Quit(void)
   857 {
   858     SDL_QuitSubSystem(SDL_WasInit(0) | SDL12_INIT_CDROM);
   859 }
   860 
   861 DECLSPEC void SDLCALL
   862 SDL_SetError(const char *fmt, ...)
   863 {
   864     char ch;
   865     char *str = NULL;
   866     size_t len = 0;
   867     va_list ap;
   868     va_start(ap, fmt);
   869     len = SDL20_vsnprintf(&ch, 1, fmt, ap);
   870     va_end(ap);
   871 
   872     str = (char *) SDL20_malloc(len + 1);
   873     if (!str)
   874         SDL20_OutOfMemory();
   875     else
   876     {
   877         va_start(ap, fmt);
   878         SDL20_vsnprintf(str, len + 1, fmt, ap);
   879         va_end(ap);
   880         SDL20_SetError("%s", str);
   881         SDL20_free(str);
   882     }
   883 }
   884 
   885 DECLSPEC const char * SDLCALL
   886 SDL_GetError(void)
   887 {
   888     if (SDL20_GetError == NULL)
   889     {
   890         static const char noload_errstr[] = "The SDL 2.0 library that the 1.2 compatibility layer needs isn't loaded";
   891         return noload_errstr;
   892     }
   893     return SDL20_GetError();
   894 }
   895 
   896 
   897 static const char *
   898 GetDriverName(const char *name, char *namebuf, int maxlen)
   899 {
   900     if (name) {
   901         if (namebuf) {
   902             SDL20_strlcpy(namebuf, name, maxlen);
   903             return namebuf;
   904         } else {
   905             return name;
   906         }
   907     }
   908     return NULL;
   909 }
   910 
   911 DECLSPEC const char * SDLCALL
   912 SDL_AudioDriverName(char *namebuf, int maxlen)
   913 {
   914     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   915 }
   916 
   917 DECLSPEC const char * SDLCALL
   918 SDL_VideoDriverName(char *namebuf, int maxlen)
   919 {
   920     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   921 }
   922 
   923 DECLSPEC int SDLCALL
   924 SDL_PollEvent(SDL12_Event *event12)
   925 {
   926     EventQueueType *next;
   927 
   928     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   929 
   930     if (EventQueueHead == NULL)
   931         return 0;  /* no events at the moment. */
   932 
   933     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   934     next = EventQueueHead->next;
   935     EventQueueHead->next = EventQueueAvailable;
   936     EventQueueAvailable = EventQueueHead;
   937     EventQueueHead = next;
   938     return 1;
   939 }
   940 
   941 DECLSPEC int SDLCALL
   942 SDL_PushEvent(SDL12_Event *event12)
   943 {
   944     EventQueueType *item = EventQueueAvailable;
   945     if (item == NULL)
   946         return -1;  /* no space available at the moment. */
   947 
   948     EventQueueAvailable = item->next;
   949     if (EventQueueTail)
   950         EventQueueTail->next = item;
   951     else
   952         EventQueueHead = EventQueueTail = item;
   953     item->next = NULL;
   954 
   955     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   956     return 0;
   957 }
   958 
   959 DECLSPEC int SDLCALL
   960 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   961 {
   962     if (action == SDL_ADDEVENT)
   963     {
   964         int i;
   965         for (i = 0; i < numevents; i++)
   966         {
   967             if (SDL_PushEvent(&events12[i]) == -1)
   968                 break;  /* out of space for more events. */
   969         }
   970         return i;
   971     }
   972     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   973     {
   974         const SDL_bool isGet = (action == SDL_GETEVENT);
   975         EventQueueType *prev = NULL;
   976         EventQueueType *item = EventQueueHead;
   977         EventQueueType *next = NULL;
   978         int chosen = 0;
   979         while (chosen < numevents)
   980         {
   981             EventQueueType *nextPrev = item;
   982             if (!item)
   983                 break;  /* no more events at the moment. */
   984 
   985             next = item->next;  /* copy, since we might overwrite item->next */
   986 
   987             if (mask & (1<<item->event12.type))
   988             {
   989                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   990                 if (isGet)  /* remove from list? */
   991                 {
   992                     if (prev != NULL)
   993                         prev->next = next;
   994                     if (item == EventQueueHead)
   995                         EventQueueHead = next;
   996                     if (item == EventQueueTail)
   997                         EventQueueTail = prev;
   998 
   999                     /* put it back in the free pool. */
  1000                     item->next = EventQueueAvailable;
  1001                     EventQueueAvailable = item;
  1002                     nextPrev = prev;  /* previous item doesn't change. */
  1003                 }
  1004             }
  1005 
  1006             item = next;
  1007             prev = nextPrev;
  1008         }
  1009         return chosen;
  1010     }
  1011 
  1012     return 0;
  1013 }
  1014 
  1015 DECLSPEC int SDLCALL
  1016 SDL_WaitEvent(SDL12_Event *event12)
  1017 {
  1018     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1019     while (!SDL_PollEvent(event12))
  1020         SDL20_Delay(10);
  1021     return 1;
  1022 }
  1023 
  1024 static SDL_bool
  1025 PushEventIfNotFiltered(SDL12_Event *event12)
  1026 {
  1027     if (event12->type != SDL12_NOEVENT)
  1028     {
  1029         if (EventStates[event12->type] != SDL_IGNORE)
  1030         {
  1031             if ((!EventFilter12) || (EventFilter12(event12)))
  1032                 return (SDL_PushEvent(event12) == 0);
  1033         }
  1034     }
  1035     return SDL_FALSE;
  1036 }
  1037 
  1038 DECLSPEC Uint8 SDLCALL
  1039 SDL_EventState(Uint8 type, int state)
  1040 {
  1041     /* the values of "state" match between 1.2 and 2.0 */
  1042     const Uint8 retval = EventStates[type];
  1043     SDL12_Event e;
  1044 
  1045     if (state != SDL_QUERY)
  1046         EventStates[type] = state;
  1047     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1048         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1049 
  1050     return retval;
  1051 }
  1052 
  1053 DECLSPEC Uint8 SDLCALL
  1054 SDL_GetMouseState(int *x, int *y)
  1055 {
  1056     const Uint32 state20 = SDL20_GetMouseState(x, y);
  1057     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1058 
  1059     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1060     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  1061         retval |= (1<<5);
  1062     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  1063         retval |= (1<<6);
  1064 
  1065     return retval;
  1066 }
  1067 
  1068 static int
  1069 EventFilter20to12(void *data, SDL_Event *event20)
  1070 {
  1071     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1072     SDL12_Event event12;
  1073     int x, y;
  1074 
  1075     SDL_assert(data == NULL);  /* currently unused. */
  1076 
  1077     SDL20_zero(event12);
  1078 
  1079     switch (event20->type)
  1080     {
  1081         case SDL_QUIT:
  1082             event12.type = SDL12_QUIT;
  1083             break;
  1084 
  1085         case SDL_WINDOWEVENT:
  1086             switch (event20->window.event)
  1087             {
  1088                 case SDL_WINDOWEVENT_CLOSE:
  1089                     event12.type = SDL12_QUIT;
  1090                     break;
  1091 
  1092                 case SDL_WINDOWEVENT_SHOWN:
  1093                 case SDL_WINDOWEVENT_EXPOSED:
  1094                     event12.type = SDL12_VIDEOEXPOSE;
  1095                     break;
  1096 
  1097                 case SDL_WINDOWEVENT_RESIZED:
  1098                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1099                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1100                     event12.type = SDL12_VIDEORESIZE;
  1101                     event12.resize.w = event20->window.data1;
  1102                     event12.resize.h = event20->window.data2;
  1103                     break;
  1104 
  1105                 case SDL_WINDOWEVENT_MINIMIZED:
  1106                     event12.type = SDL12_ACTIVEEVENT;
  1107                     event12.active.gain = 0;
  1108                     event12.active.state = SDL12_APPACTIVE;
  1109                     break;
  1110 
  1111                 case SDL_WINDOWEVENT_RESTORED:
  1112                     event12.type = SDL12_ACTIVEEVENT;
  1113                     event12.active.gain = 1;
  1114                     event12.active.state = SDL12_APPACTIVE;
  1115                     break;
  1116 
  1117                 case SDL_WINDOWEVENT_ENTER:
  1118                     event12.type = SDL12_ACTIVEEVENT;
  1119                     event12.active.gain = 1;
  1120                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1121                     break;
  1122 
  1123                 case SDL_WINDOWEVENT_LEAVE:
  1124                     event12.type = SDL12_ACTIVEEVENT;
  1125                     event12.active.gain = 0;
  1126                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1127                     break;
  1128 
  1129                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1130                     event12.type = SDL12_ACTIVEEVENT;
  1131                     event12.active.gain = 1;
  1132                     event12.active.state = SDL12_APPINPUTFOCUS;
  1133                     break;
  1134 
  1135                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1136                     event12.type = SDL12_ACTIVEEVENT;
  1137                     event12.active.gain = 0;
  1138                     event12.active.state = SDL12_APPINPUTFOCUS;
  1139                     break;
  1140             }
  1141             break;
  1142 
  1143         // !!! FIXME: this is sort of a mess to convert.
  1144         //case SDL_SYSWMEVENT:
  1145 
  1146         case SDL_KEYDOWN: FIXME("write me"); return 0;
  1147         case SDL_KEYUP: FIXME("write me"); return 0;
  1148 
  1149         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  1150         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  1151 
  1152         case SDL_MOUSEMOTION:
  1153         	event12.type = SDL12_MOUSEMOTION;
  1154             event12.motion.which = (Uint8) event20->motion.which;
  1155             event12.motion.state = event20->motion.state;
  1156             event12.motion.x = (Uint16) event20->motion.x;
  1157             event12.motion.y = (Uint16) event20->motion.y;
  1158             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1159             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1160             break;
  1161 
  1162         case SDL_MOUSEBUTTONDOWN:
  1163         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1164             event12.button.which = (Uint8) event20->button.which;
  1165             event12.button.button = event20->button.button;
  1166             event12.button.state = event20->button.state;
  1167             event12.button.x = (Uint16) event20->button.x;
  1168             event12.button.y = (Uint16) event20->button.y;
  1169             break;
  1170 
  1171         case SDL_MOUSEBUTTONUP:
  1172         	event12.type = SDL12_MOUSEBUTTONUP;
  1173             event12.button.which = (Uint8) event20->button.which;
  1174             event12.button.button = event20->button.button;
  1175             event12.button.state = event20->button.state;
  1176             event12.button.x = (Uint16) event20->button.x;
  1177             event12.button.y = (Uint16) event20->button.y;
  1178             break;
  1179 
  1180         case SDL_MOUSEWHEEL:
  1181             if (event20->wheel.y == 0)
  1182                 break;  /* don't support horizontal wheels in 1.2. */
  1183 
  1184             event12.type = SDL12_MOUSEBUTTONDOWN;
  1185             event12.button.which = (Uint8) event20->wheel.which;
  1186             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1187             event12.button.state = SDL_GetMouseState(&x, &y);
  1188             event12.button.x = (Uint16) x;
  1189             event12.button.y = (Uint16) y;
  1190             PushEventIfNotFiltered(&event12);
  1191 
  1192             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1193             break;
  1194 
  1195         case SDL_JOYAXISMOTION:
  1196             event12.type = SDL12_JOYAXISMOTION;
  1197             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1198             event12.jaxis.axis = event20->jaxis.axis;
  1199             event12.jaxis.value = event20->jaxis.value;
  1200             break;
  1201 
  1202         case SDL_JOYBALLMOTION:
  1203             event12.type = SDL12_JOYBALLMOTION;
  1204             event12.jball.which = (Uint8) event20->jball.which;
  1205             event12.jball.ball = event20->jball.ball;
  1206             event12.jball.xrel = event20->jball.xrel;
  1207             event12.jball.yrel = event20->jball.yrel;
  1208             break;
  1209 
  1210         case SDL_JOYHATMOTION:
  1211             event12.type = SDL12_JOYHATMOTION;
  1212             event12.jhat.which = (Uint8) event20->jhat.which;
  1213             event12.jhat.hat = event20->jhat.hat;
  1214             event12.jhat.value = event20->jhat.value;
  1215             break;
  1216 
  1217         case SDL_JOYBUTTONDOWN:
  1218             event12.type = SDL12_JOYBUTTONDOWN;
  1219             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1220             event12.jbutton.button = event20->jbutton.button;
  1221             event12.jbutton.state = event20->jbutton.state;
  1222             break;
  1223 
  1224         case SDL_JOYBUTTONUP:
  1225             event12.type = SDL12_JOYBUTTONUP;
  1226             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1227             event12.jbutton.button = event20->jbutton.button;
  1228             event12.jbutton.state = event20->jbutton.state;
  1229             break;
  1230 
  1231         //case SDL_JOYDEVICEADDED:
  1232         //case SDL_JOYDEVICEREMOVED:
  1233 	    //case SDL_CONTROLLERAXISMOTION:
  1234 	    //case SDL_CONTROLLERBUTTONDOWN:
  1235 	    //case SDL_CONTROLLERBUTTONUP:
  1236 	    //case SDL_CONTROLLERDEVICEADDED:
  1237 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1238 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1239         //case SDL_FINGERDOWN:
  1240         //case SDL_FINGERUP:
  1241         //case SDL_FINGERMOTION:
  1242         //case SDL_DOLLARGESTURE:
  1243         //case SDL_DOLLARRECORD:
  1244         //case SDL_MULTIGESTURE:
  1245         //case SDL_CLIPBOARDUPDATE:
  1246         //case SDL_DROPFILE:
  1247 
  1248         default:
  1249             return 0;  /* drop everything else. */
  1250     }
  1251 
  1252     PushEventIfNotFiltered(&event12);
  1253 
  1254     return 0;  /* always drop it from the 2.0 event queue. */
  1255 }
  1256 
  1257 DECLSPEC void SDLCALL
  1258 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1259 {
  1260     /* We always have a filter installed, but will call the app's too. */
  1261     EventFilter12 = filter12;
  1262 }
  1263 
  1264 DECLSPEC SDL12_EventFilter SDLCALL
  1265 SDL_GetEventFilter(void)
  1266 {
  1267     return EventFilter12;
  1268 }
  1269 
  1270 
  1271 static SDL12_Surface *
  1272 Surface20to12(SDL_Surface *surface20)
  1273 {
  1274     SDL12_Surface *surface12 = NULL;
  1275     SDL12_Palette *palette12 = NULL;
  1276     SDL12_PixelFormat *format12 = NULL;
  1277     Uint32 flags = 0;
  1278 
  1279     if (!surface20)
  1280         return NULL;
  1281 
  1282     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1283     if (!surface12)
  1284         goto failed;
  1285 
  1286     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1287     if (!palette12)
  1288         goto failed;
  1289 
  1290     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1291     if (!format12)
  1292         goto failed;
  1293 
  1294     SDL20_zerop(palette12);
  1295     palette12->ncolors = surface20->format->palette->ncolors;
  1296     palette12->colors = surface20->format->palette->colors;
  1297 
  1298     SDL20_zerop(format12);
  1299     format12->palette = palette12;
  1300     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1301     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1302     format12->Rloss = surface20->format->Rloss;
  1303     format12->Gloss = surface20->format->Gloss;
  1304     format12->Bloss = surface20->format->Bloss;
  1305     format12->Aloss = surface20->format->Aloss;
  1306     format12->Rshift = surface20->format->Rshift;
  1307     format12->Gshift = surface20->format->Gshift;
  1308     format12->Bshift = surface20->format->Bshift;
  1309     format12->Ashift = surface20->format->Ashift;
  1310     format12->Rmask = surface20->format->Rmask;
  1311     format12->Gmask = surface20->format->Gmask;
  1312     format12->Bmask = surface20->format->Bmask;
  1313     format12->Amask = surface20->format->Amask;
  1314     FIXME("format12->colorkey");
  1315     FIXME("format12->alpha");
  1316 
  1317     SDL20_zerop(surface12);
  1318     flags = surface20->flags;
  1319     #ifdef SDL_SIMD_ALIGNED
  1320     flags &= ~SDL_SIMD_ALIGNED;  /* we don't need to map this to 1.2 */
  1321     #endif
  1322     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1323     MAPSURFACEFLAGS(PREALLOC);
  1324     MAPSURFACEFLAGS(RLEACCEL);
  1325     /*MAPSURFACEFLAGS(DONTFREE);*/
  1326     #undef MAPSURFACEFLAGS
  1327     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1328 
  1329     surface12->format = format12;
  1330     surface12->w = surface20->w;
  1331     surface12->h = surface20->h;
  1332     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  1333     surface12->pixels = surface20->pixels;
  1334     surface12->offset = 0;
  1335     surface12->surface20 = surface20;
  1336     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
  1337     surface12->refcount = surface20->refcount;
  1338 
  1339     return surface12;
  1340 
  1341 failed:
  1342     SDL20_free(surface12);
  1343     SDL20_free(palette12);
  1344     SDL20_free(format12);
  1345     return NULL;
  1346 }
  1347 
  1348 DECLSPEC SDL12_Surface * SDLCALL
  1349 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1350 {
  1351     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1352     SDL12_Surface *surface12 = Surface20to12(surface20);
  1353     if (!surface12) {
  1354         SDL20_FreeSurface(surface20);
  1355         return NULL;
  1356     }
  1357 
  1358     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1359     return surface12;
  1360 }
  1361 
  1362 DECLSPEC SDL12_Surface * SDLCALL
  1363 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1364 {
  1365     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1366     SDL12_Surface *surface12 = Surface20to12(surface20);
  1367     if (!surface12) {
  1368         SDL20_FreeSurface(surface20);
  1369         return NULL;
  1370     }
  1371 
  1372     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1373     return surface12;
  1374 }
  1375 
  1376 DECLSPEC void SDLCALL
  1377 SDL_FreeSurface(SDL12_Surface *surface12)
  1378 {
  1379     if (surface12) {
  1380         SDL20_FreeSurface(surface12->surface20);
  1381         if (surface12->format) {
  1382             SDL20_free(surface12->format->palette);
  1383             SDL20_free(surface12->format);
  1384         }
  1385         SDL20_free(surface12);
  1386     }
  1387 }
  1388 
  1389 DECLSPEC void SDLCALL
  1390 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1391 {
  1392     if (surface12 && rect)
  1393 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1394 }
  1395 
  1396 DECLSPEC SDL_bool SDLCALL
  1397 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1398 {
  1399     SDL_bool retval = SDL_FALSE;
  1400     if (surface12)
  1401     {
  1402         retval = SDL20_SetClipRect(surface12->surface20, rect);
  1403         SDL20_GetClipRect(surface12->surface20, &surface12->clip_rect);
  1404     }
  1405     return retval;
  1406 }
  1407 
  1408 DECLSPEC int SDLCALL
  1409 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1410 {
  1411     const int retval = SDL20_FillRect(dst->surface20, dstrect, color);
  1412     if (retval != -1)
  1413     {
  1414         if (dstrect) {  /* 1.2 stores the clip intersection in dstrect */
  1415             const SDL_Rect orig_dstrect = *dstrect;
  1416             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1417         }
  1418     }
  1419     return retval;
  1420 }
  1421 
  1422 
  1423 static SDL_PixelFormat *
  1424 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1425 {
  1426     palette20->ncolors = format12->palette->ncolors;
  1427     palette20->colors = format12->palette->colors;
  1428     palette20->version = 1;
  1429     palette20->refcount = 1;
  1430     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1431     format20->palette = palette20;
  1432     format20->BitsPerPixel = format12->BitsPerPixel;
  1433     format20->BytesPerPixel = format12->BytesPerPixel;
  1434     format20->Rmask = format12->Rmask;
  1435     format20->Gmask = format12->Gmask;
  1436     format20->Bmask = format12->Bmask;
  1437     format20->Amask = format12->Amask;
  1438     format20->Rloss = format12->Rloss;
  1439     format20->Gloss = format12->Gloss;
  1440     format20->Bloss = format12->Bloss;
  1441     format20->Aloss = format12->Aloss;
  1442     format20->Rshift = format12->Rshift;
  1443     format20->Gshift = format12->Gshift;
  1444     format20->Bshift = format12->Bshift;
  1445     format20->Ashift = format12->Ashift;
  1446     format20->refcount = 1;
  1447     format20->next = NULL;
  1448     return format20;
  1449 }
  1450 
  1451 DECLSPEC Uint32 SDLCALL
  1452 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1453 {
  1454     /* This is probably way slower than apps expect. */
  1455     SDL_PixelFormat format20;
  1456     SDL_Palette palette20;
  1457     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1458 }
  1459 
  1460 DECLSPEC Uint32 SDLCALL
  1461 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1462 {
  1463     /* This is probably way slower than apps expect. */
  1464     SDL_PixelFormat format20;
  1465     SDL_Palette palette20;
  1466     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1467 }
  1468 
  1469 DECLSPEC void SDLCALL
  1470 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1471 {
  1472     /* This is probably way slower than apps expect. */
  1473     SDL_PixelFormat format20;
  1474     SDL_Palette palette20;
  1475     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1476 }
  1477 
  1478 DECLSPEC void SDLCALL
  1479 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1480 {
  1481     /* This is probably way slower than apps expect. */
  1482     SDL_PixelFormat format20;
  1483     SDL_Palette palette20;
  1484     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1485 }
  1486 
  1487 DECLSPEC const SDL12_VideoInfo * SDLCALL
  1488 SDL_GetVideoInfo(void)
  1489 {
  1490     SDL_DisplayMode mode;
  1491 
  1492     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  1493 
  1494     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1495         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  1496         VideoInfo12.current_w = mode.w;
  1497         VideoInfo12.current_h = mode.h;
  1498         FIXME("vidinfo details commented out");
  1499         //VideoInfo12.wm_available = 1;
  1500         //VideoInfo12.video_mem = 1024 * 256;
  1501     }
  1502     return &VideoInfo12;
  1503 }
  1504 
  1505 DECLSPEC int SDLCALL
  1506 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1507 {
  1508     int i, nummodes, actual_bpp = 0;
  1509 
  1510     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1511         return 0;
  1512     }
  1513 
  1514     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1515         SDL_DisplayMode mode;
  1516         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1517         return SDL_BITSPERPIXEL(mode.format);
  1518     }
  1519 
  1520     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1521     for (i = 0; i < nummodes; ++i) {
  1522         SDL_DisplayMode mode;
  1523         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1524         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1525             if (!mode.format) {
  1526                 return bpp;
  1527             }
  1528             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1529                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1530             }
  1531         }
  1532     }
  1533     return actual_bpp;
  1534 }
  1535 
  1536 DECLSPEC SDL_Rect ** SDLCALL
  1537 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  1538 {
  1539     Uint32 fmt;
  1540     int i;
  1541 
  1542     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1543         return NULL;
  1544     }
  1545 
  1546     if ((!format12) && (!VideoInfo12.vfmt)) {
  1547         SDL20_SetError("No pixel format specified");
  1548         return NULL;
  1549     }
  1550 
  1551     if (!(flags & SDL12_FULLSCREEN)) {
  1552         return (SDL_Rect **) (-1);  /* any resolution is fine. */
  1553     }
  1554 
  1555     if (format12) {
  1556         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1557     } else {
  1558         fmt = VideoInfo12.vfmt->format;
  1559     }
  1560 
  1561     for (i = 0; i < VideoModesCount; i++) {
  1562         VideoModeList *modes = &VideoModes[i];
  1563         if (modes->format == fmt) {
  1564             return modes->modes;
  1565         }
  1566     }
  1567 
  1568     SDL20_SetError("No modes support requested pixel format");
  1569     return NULL;
  1570 }
  1571 
  1572 DECLSPEC void SDLCALL
  1573 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1574 {
  1575     if (cursor12) {
  1576         if (cursor12->wm_cursor)
  1577             SDL20_FreeCursor(cursor12->wm_cursor);
  1578         SDL20_free(cursor12->data);
  1579         SDL20_free(cursor12->mask);
  1580         SDL20_free(cursor12);
  1581     }
  1582 }
  1583 
  1584 DECLSPEC SDL12_Cursor * SDLCALL
  1585 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1586 {
  1587     const size_t datasize = h * (w / 8);
  1588     SDL_Cursor *cursor20 = NULL;
  1589     SDL12_Cursor *retval = NULL;
  1590 
  1591     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1592     if (!retval)
  1593         goto outofmem;
  1594 
  1595     SDL20_zerop(retval);
  1596 
  1597     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1598     if (!retval->data)
  1599         goto outofmem;
  1600 
  1601     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1602     if (!retval->mask)
  1603         goto outofmem;
  1604 
  1605     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1606     if (!cursor20)
  1607         goto failed;
  1608 
  1609     retval->area.w = w;
  1610     retval->area.h = h;
  1611     retval->hot_x = hot_x;
  1612     retval->hot_y = hot_y;
  1613     retval->wm_cursor = cursor20;
  1614     /* we always leave retval->save as null pointers. */
  1615 
  1616     SDL20_memcpy(retval->data, data, datasize);
  1617     SDL20_memcpy(retval->mask, mask, datasize);
  1618 
  1619     return retval;
  1620 
  1621 outofmem:
  1622     SDL20_OutOfMemory();
  1623 
  1624 failed:
  1625     SDL_FreeCursor(retval);
  1626     return NULL;
  1627 }
  1628 
  1629 DECLSPEC void SDLCALL
  1630 SDL_SetCursor(SDL12_Cursor *cursor)
  1631 {
  1632     CurrentCursor12 = cursor;
  1633     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1634 }
  1635 
  1636 DECLSPEC SDL12_Cursor * SDLCALL
  1637 SDL_GetCursor(void)
  1638 {
  1639     return CurrentCursor12;
  1640 }
  1641 
  1642 static void
  1643 GetEnvironmentWindowPosition(int *x, int *y)
  1644 {
  1645     int display = VideoDisplayIndex;
  1646     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  1647     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  1648     if (window) {
  1649         if (SDL20_strcmp(window, "center") == 0) {
  1650             center = window;
  1651         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  1652             return;
  1653         }
  1654     }
  1655 
  1656     if (center) {
  1657         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1658         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1659     }
  1660 }
  1661 
  1662 static void
  1663 SetupScreenSaver(const int flags12)
  1664 {
  1665     const char *env;
  1666     SDL_bool allow_screensaver;
  1667 
  1668     /* Allow environment override of screensaver disable */
  1669     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1670     if (env) {
  1671         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1672     } else if (flags12 & SDL12_FULLSCREEN) {
  1673         allow_screensaver = SDL_FALSE;
  1674     } else {
  1675         allow_screensaver = SDL_TRUE;
  1676     }
  1677     if (allow_screensaver) {
  1678         SDL20_EnableScreenSaver();
  1679     } else {
  1680         SDL20_DisableScreenSaver();
  1681     }
  1682 }
  1683 
  1684 
  1685 static SDL12_Surface *
  1686 EndVidModeCreate(void)
  1687 {
  1688     if (VideoTexture20) {
  1689         SDL20_DestroyTexture(VideoTexture20);
  1690         VideoTexture20 = NULL;
  1691     }
  1692     if (VideoRenderer20) {
  1693         SDL20_DestroyRenderer(VideoRenderer20);
  1694         VideoRenderer20 = NULL;
  1695     }
  1696     if (VideoGLContext20) {
  1697         SDL20_GL_MakeCurrent(NULL, NULL);
  1698         SDL20_GL_DeleteContext(VideoGLContext20);
  1699         VideoGLContext20 = NULL;
  1700     }
  1701     if (VideoWindow20) {
  1702         SDL20_DestroyWindow(VideoWindow20);
  1703         VideoWindow20 = NULL;
  1704     }
  1705     if (VideoSurface12) {
  1706         SDL20_free(VideoSurface12->pixels);
  1707         VideoSurface12->pixels = NULL;
  1708         SDL_FreeSurface(VideoSurface12);
  1709         VideoSurface12 = NULL;
  1710     }
  1711     if (VideoConvertSurface20) {
  1712         SDL20_FreeSurface(VideoConvertSurface20);
  1713         VideoConvertSurface20 = NULL;
  1714     }
  1715     return NULL;
  1716 }
  1717 
  1718 
  1719 static SDL12_Surface *
  1720 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  1721 {
  1722     Uint32 rmask, gmask, bmask, amask;
  1723     int bpp;
  1724     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  1725         return NULL;
  1726     }
  1727     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  1728 }
  1729 
  1730 static SDL_Surface *
  1731 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  1732 {
  1733     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  1734     if (surface20) {
  1735         surface20->flags |= SDL_PREALLOC;
  1736         surface20->pixels = NULL;
  1737         surface20->w = width;
  1738         surface20->h = height;
  1739         surface20->pitch = 0;
  1740         SDL20_SetClipRect(surface20, NULL);
  1741     }
  1742     return surface20;
  1743 }
  1744 
  1745 
  1746 DECLSPEC SDL12_Surface * SDLCALL
  1747 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1748 {
  1749     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  1750     SDL_DisplayMode dmode;
  1751     Uint32 fullscreen_flags20 = 0;
  1752     Uint32 appfmt;
  1753 
  1754     /* SDL_SetVideoMode() implicitly inits if necessary. */
  1755     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  1756         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  1757             return NULL;
  1758         }
  1759     }
  1760 
  1761     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  1762         FIXME("No OPENGLBLIT support at the moment");
  1763         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  1764         return NULL;
  1765     }
  1766 
  1767     FIXME("handle SDL_ANYFORMAT");
  1768 
  1769     if ((width < 0) || (height < 0)) {
  1770         SDL20_SetError("Invalid width or height");
  1771         return NULL;
  1772     }
  1773 
  1774     FIXME("There's an environment variable to choose a display");
  1775     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  1776         return NULL;
  1777     }
  1778 
  1779     if (width == 0) {
  1780         width = dmode.w;
  1781     }
  1782 
  1783     if (height == 0) {
  1784         height = dmode.h;
  1785     }
  1786 
  1787     if (bpp == 0) {
  1788         bpp = SDL_BITSPERPIXEL(dmode.format);
  1789     }
  1790 
  1791     switch (bpp) {
  1792         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  1793         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  1794         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  1795         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  1796         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  1797     }
  1798 
  1799     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  1800 
  1801     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  1802     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  1803 
  1804     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  1805         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  1806     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  1807         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  1808     } else if (VideoGLContext20) {
  1809         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  1810         SDL20_GL_MakeCurrent(NULL, NULL);
  1811         SDL20_GL_DeleteContext(VideoGLContext20);
  1812         VideoGLContext20 = NULL;
  1813     }
  1814 
  1815     if (flags12 & SDL12_FULLSCREEN) {
  1816         // OpenGL tries to force the real resolution requested, but for
  1817         //  software rendering, we're just going to push it off onto the
  1818         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  1819         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  1820         if (flags12 & SDL12_OPENGL) {
  1821             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  1822         } else {
  1823             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  1824         }
  1825     }
  1826 
  1827     if (!VideoWindow20) {  /* create it */
  1828         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  1829         Uint32 flags20 = fullscreen_flags20;
  1830         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  1831         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  1832         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  1833 
  1834         /* most platforms didn't check these environment variables, but the major
  1835            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  1836         GetEnvironmentWindowPosition(&x, &y);
  1837 
  1838         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  1839         if (!VideoWindow20) {
  1840             return EndVidModeCreate();
  1841         }
  1842     } else {  /* resize it */
  1843         SDL20_SetWindowSize(VideoWindow20, width, height);
  1844         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  1845         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  1846         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  1847     }
  1848 
  1849     if (VideoSurface12) {
  1850         SDL20_free(VideoSurface12->pixels);
  1851     } else {
  1852         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  1853         if (!VideoSurface12) {
  1854             return EndVidModeCreate();
  1855         }
  1856     }
  1857 
  1858     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  1859     VideoSurface12->flags |= SDL12_PREALLOC;
  1860     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  1861     VideoSurface12->w = VideoSurface12->surface20->w = width;
  1862     VideoSurface12->h = VideoSurface12->surface20->h = height;
  1863     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  1864     SDL_SetClipRect(VideoSurface12, NULL);
  1865 
  1866     if (flags12 & SDL12_OPENGL) {
  1867         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  1868         SDL_assert(!VideoRenderer20);
  1869         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  1870         if (!VideoGLContext20) {
  1871             return EndVidModeCreate();
  1872         }
  1873 
  1874         VideoSurface12->flags |= SDL12_OPENGL;
  1875     } else {
  1876         /* always use a renderer for non-OpenGL windows. */
  1877         SDL_RendererInfo rinfo;
  1878         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  1879         if (!VideoRenderer20) {
  1880             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  1881         }
  1882         if (!VideoRenderer20) {
  1883             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_PRESENTVSYNC);
  1884         }
  1885         if (!VideoRenderer20) {
  1886             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  1887         }
  1888         if (!VideoRenderer20) {
  1889             return EndVidModeCreate();
  1890         }
  1891 
  1892         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  1893         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  1894         SDL20_RenderClear(VideoRenderer20);
  1895         SDL20_RenderPresent(VideoRenderer20);
  1896         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  1897 
  1898         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  1899             return EndVidModeCreate();
  1900         }
  1901 
  1902         if (VideoTexture20) {
  1903             SDL20_DestroyTexture(VideoTexture20);
  1904         }
  1905 
  1906         if (VideoConvertSurface20) {
  1907             SDL20_FreeSurface(VideoConvertSurface20);
  1908             VideoConvertSurface20 = NULL;
  1909         }
  1910 
  1911         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  1912         if (!VideoTexture20) {
  1913             return EndVidModeCreate();
  1914         }
  1915 
  1916         if (rinfo.texture_formats[0] != appfmt) {
  1917             /* need to convert between app's format and texture format */
  1918             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  1919             if (!VideoConvertSurface20) {
  1920                 return EndVidModeCreate();
  1921             }
  1922         }
  1923 
  1924         VideoSurface12->flags &= ~SDL12_OPENGL;
  1925         VideoSurface12->flags |= SDL12_DOUBLEBUF;
  1926         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  1927         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  1928         if (!VideoSurface12->pixels) {
  1929             SDL20_OutOfMemory();
  1930             return EndVidModeCreate();
  1931         }
  1932 
  1933         /* fill in the same default palette that SDL 1.2 does... */
  1934         if (VideoSurface12->format->BitsPerPixel == 8) {
  1935             int i;
  1936             SDL_Color *color = VideoSurface12->format->palette->colors;
  1937             for (i = 0; i < 256; i++, color++) {
  1938                 { const int x = i & 0xe0; color->r = x >> 3 | x >> 6; }
  1939                 { const int x = (i << 3) & 0xe0; color->g = x >> 3 | x >> 6; }
  1940                 { const int x = (i & 0x3) | (i & 0x3 << 2); color->b = x | x << 4; }
  1941                 color->a = 255;
  1942             }
  1943         }
  1944     }
  1945 
  1946     FIXME("setup screen saver");
  1947 
  1948     return VideoSurface12;
  1949 }
  1950 
  1951 DECLSPEC SDL12_Surface * SDLCALL
  1952 SDL_GetVideoSurface(void)
  1953 {
  1954     return VideoSurface12;
  1955 }
  1956 
  1957 DECLSPEC int SDLCALL
  1958 SDL_UpperBlit(SDL12_Surface *src, SDL_Rect *srcrect, SDL12_Surface *dst, SDL_Rect *dstrect)
  1959 {
  1960     return SDL20_UpperBlit(src->surface20, srcrect, dst->surface20, dstrect);
  1961 }
  1962 
  1963 DECLSPEC int SDLCALL
  1964 SDL_LowerBlit(SDL12_Surface *src, SDL_Rect *srcrect, SDL12_Surface *dst, SDL_Rect *dstrect)
  1965 {
  1966     return SDL20_LowerBlit(src->surface20, srcrect, dst->surface20, dstrect);
  1967 }
  1968 
  1969 DECLSPEC int SDLCALL
  1970 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  1971 {
  1972     FIXME("write me");
  1973     return SDL20_Unsupported();
  1974 }
  1975 
  1976 DECLSPEC SDL12_Surface * SDLCALL
  1977 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
  1978 {
  1979     Uint32 flags20 = 0;
  1980     SDL_PixelFormat format20;
  1981     SDL_Palette palette20;
  1982     SDL_Surface *surface20;
  1983     SDL12_Surface *retval = NULL;
  1984 
  1985     if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
  1986     if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
  1987 
  1988     surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
  1989     if (surface20) {
  1990         retval = Surface20to12(surface20);
  1991         if (!retval) {
  1992             SDL20_FreeSurface(surface20);
  1993         }
  1994     }
  1995     return retval;
  1996 }
  1997 
  1998 DECLSPEC SDL12_Surface * SDLCALL
  1999 SDL_DisplayFormat(SDL12_Surface *surface12)
  2000 {
  2001     const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
  2002     return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
  2003 }
  2004 
  2005 DECLSPEC SDL12_Surface * SDLCALL
  2006 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  2007 {
  2008     FIXME("write me");
  2009     SDL20_Unsupported();
  2010     return NULL;
  2011 }
  2012 
  2013 static void
  2014 PresentScreen(void)
  2015 {
  2016     void *pixels = NULL;
  2017     int pitch = 0;
  2018 
  2019     SDL_assert(VideoSurface12 != NULL);
  2020 
  2021     if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
  2022         return;  /* oh well */
  2023     }
  2024 
  2025     FIXME("Maybe lock texture always, until present, if no conversion needed?");
  2026     VideoConvertSurface20->pixels = pixels;
  2027     VideoConvertSurface20->pitch = pitch;
  2028     SDL20_UpperBlit(VideoSurface12->surface20, NULL, VideoConvertSurface20, NULL);
  2029     VideoConvertSurface20->pixels = NULL;
  2030     VideoConvertSurface20->pitch = 0;
  2031 
  2032     SDL20_UnlockTexture(VideoTexture20);
  2033     SDL20_RenderCopy(VideoRenderer20, VideoTexture20, NULL, NULL);
  2034     SDL20_RenderPresent(VideoRenderer20);
  2035 }
  2036 
  2037 DECLSPEC void SDLCALL
  2038 SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL_Rect *rects)
  2039 {
  2040     /* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
  2041     /* (UpdateRect, singular, does...) */
  2042     if (surface12->flags & SDL12_OPENGL) {
  2043         SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2044         return;
  2045     }
  2046 
  2047     /* everything else is marked SDL12_DOUBLEBUF and is a no-op here. */
  2048 }
  2049 
  2050 DECLSPEC void SDLCALL
  2051 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  2052 {
  2053     if (screen12) {
  2054         SDL_Rect rect;
  2055         rect.x = (int) x;
  2056         rect.y = (int) y;
  2057         rect.w = (int) (w ? w : screen12->w);
  2058         rect.h = (int) (h ? h : screen12->h);
  2059         SDL_UpdateRects(screen12, 1, &rect);
  2060     }
  2061 }
  2062 
  2063 DECLSPEC int SDLCALL
  2064 SDL_Flip(SDL12_Surface *surface12)
  2065 {
  2066     if (surface12->flags & SDL12_OPENGL) {
  2067         return SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2068     }
  2069 
  2070     if (surface12 == VideoSurface12) {
  2071         PresentScreen();
  2072     }
  2073 
  2074     return 0;
  2075 }
  2076 
  2077 DECLSPEC void SDLCALL
  2078 SDL_WM_SetCaption(const char *title, const char *icon)
  2079 {
  2080     if (WindowTitle) {
  2081         SDL20_free(WindowTitle);
  2082     }
  2083     if (WindowIconTitle) {
  2084         SDL20_free(WindowIconTitle);
  2085     }
  2086     WindowTitle = title ? SDL_strdup(title) : NULL;
  2087     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  2088     if (VideoWindow20) {
  2089         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  2090     }
  2091 }
  2092 
  2093 DECLSPEC void SDLCALL
  2094 SDL_WM_GetCaption(const char **title, const char **icon)
  2095 {
  2096     if (title) {
  2097         *title = WindowTitle;
  2098     }
  2099     if (icon) {
  2100         *icon = WindowIconTitle;
  2101     }
  2102 }
  2103 
  2104 DECLSPEC void SDLCALL
  2105 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2106 {
  2107     FIXME("write me");
  2108     SDL20_Unsupported();
  2109 }
  2110 
  2111 DECLSPEC int SDLCALL
  2112 SDL_WM_IconifyWindow(void)
  2113 {
  2114     SDL20_MinimizeWindow(VideoWindow20);
  2115     return 0;
  2116 }
  2117 
  2118 DECLSPEC int SDLCALL
  2119 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  2120 {
  2121     FIXME("write me");
  2122     return SDL20_Unsupported();
  2123 }
  2124 
  2125 typedef enum
  2126 {
  2127     SDL12_GRAB_QUERY = -1,
  2128     SDL12_GRAB_OFF = 0,
  2129     SDL12_GRAB_ON = 1
  2130 } SDL12_GrabMode;
  2131 
  2132 DECLSPEC SDL12_GrabMode SDLCALL
  2133 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2134 {
  2135     if (mode != SDL12_GRAB_QUERY) {
  2136         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2137     }
  2138     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2139 }
  2140 
  2141 DECLSPEC void SDLCALL
  2142 SDL_WarpMouse(Uint16 x, Uint16 y)
  2143 {
  2144     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2145 }
  2146 
  2147 DECLSPEC Uint8 SDLCALL
  2148 SDL_GetAppState(void)
  2149 {
  2150     Uint8 state12 = 0;
  2151     Uint32 flags20 = 0;
  2152 
  2153     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2154     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2155         state12 |= SDL12_APPACTIVE;
  2156     }
  2157     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2158         state12 |= SDL12_APPINPUTFOCUS;
  2159     }
  2160     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2161         state12 |= SDL12_APPMOUSEFOCUS;
  2162     }
  2163     return state12;
  2164 }
  2165 
  2166 DECLSPEC int SDLCALL
  2167 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2168                int firstcolor, int ncolors)
  2169 {
  2170     FIXME("write me");
  2171     return SDL20_Unsupported();
  2172 }
  2173 
  2174 DECLSPEC int SDLCALL
  2175 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2176               int ncolors)
  2177 {
  2178     FIXME("write me");
  2179     return SDL20_Unsupported();
  2180 }
  2181 
  2182 DECLSPEC int SDLCALL
  2183 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2184 {
  2185     FIXME("write me");
  2186     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  2187     return SDL20_Unsupported();
  2188 }
  2189 
  2190 DECLSPEC SDL12_Overlay * SDLCALL
  2191 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2192 {
  2193     FIXME("write me");
  2194     SDL20_Unsupported();
  2195     return NULL;
  2196 }
  2197 
  2198 DECLSPEC int SDLCALL
  2199 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  2200 {
  2201     FIXME("write me");
  2202     return SDL20_Unsupported();
  2203 }
  2204 
  2205 DECLSPEC void SDLCALL
  2206 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  2207 {
  2208     FIXME("write me");
  2209 }
  2210 
  2211 DECLSPEC int SDLCALL
  2212 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL_Rect * dstrect)
  2213 {
  2214     FIXME("write me");
  2215     return SDL20_Unsupported();
  2216 }
  2217 
  2218 DECLSPEC void SDLCALL
  2219 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  2220 {
  2221     FIXME("write me");
  2222 }
  2223 
  2224 DECLSPEC int SDLCALL
  2225 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2226 {
  2227     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2228         return SDL20_SetError("Unknown GL attribute");
  2229 
  2230     /* swap control was moved out of this API, everything else lines up. */
  2231     if (attr == SDL12_GL_SWAP_CONTROL)
  2232     {
  2233         SwapInterval = value;
  2234         FIXME("Actually set swap interval somewhere");
  2235         return 0;
  2236     }
  2237 
  2238     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2239 }
  2240 
  2241 DECLSPEC int SDLCALL
  2242 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2243 {
  2244     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2245         return SDL20_SetError("Unknown GL attribute");
  2246 
  2247     /* swap control was moved out of this API, everything else lines up. */
  2248     if (attr == SDL12_GL_SWAP_CONTROL)
  2249     {
  2250         *value = SDL20_GL_GetSwapInterval();
  2251         return 0;
  2252     }
  2253 
  2254     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2255 }
  2256 
  2257 
  2258 DECLSPEC void SDLCALL
  2259 SDL_GL_SwapBuffers(void)
  2260 {
  2261     if (VideoWindow20)
  2262         SDL20_GL_SwapWindow(VideoWindow20);
  2263 }
  2264 
  2265 DECLSPEC int SDLCALL
  2266 SDL_SetGamma(float red, float green, float blue)
  2267 {
  2268     Uint16 red_ramp[256];
  2269     Uint16 green_ramp[256];
  2270     Uint16 blue_ramp[256];
  2271 
  2272     SDL20_CalculateGammaRamp(red, red_ramp);
  2273     if (green == red) {
  2274         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2275     } else {
  2276         SDL20_CalculateGammaRamp(green, green_ramp);
  2277     }
  2278     if (blue == red) {
  2279         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2280     } else if (blue == green) {
  2281         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2282     } else {
  2283         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2284     }
  2285     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2286 }
  2287 
  2288 DECLSPEC int SDLCALL
  2289 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2290 {
  2291     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2292 }
  2293 
  2294 DECLSPEC int SDLCALL
  2295 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2296 {
  2297     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2298 }
  2299 
  2300 DECLSPEC int SDLCALL
  2301 SDL_EnableKeyRepeat(int delay, int interval)
  2302 {
  2303     return 0;
  2304 }
  2305 
  2306 DECLSPEC void SDLCALL
  2307 SDL_GetKeyRepeat(int *delay, int *interval)
  2308 {
  2309     if (delay) {
  2310         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2311     }
  2312     if (interval) {
  2313         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2314     }
  2315 }
  2316 
  2317 DECLSPEC int SDLCALL
  2318 SDL_EnableUNICODE(int enable)
  2319 {
  2320     FIXME("write me");
  2321     return SDL20_Unsupported();
  2322 }
  2323 
  2324 static Uint32
  2325 SetTimerOld_Callback(Uint32 interval, void* param)
  2326 {
  2327     return ((SDL12_TimerCallback)param)(interval);
  2328 }
  2329 
  2330 DECLSPEC int SDLCALL
  2331 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2332 {
  2333     static SDL_TimerID compat_timer;
  2334 
  2335     if (compat_timer) {
  2336         SDL20_RemoveTimer(compat_timer);
  2337         compat_timer = 0;
  2338     }
  2339 
  2340     if (interval && callback) {
  2341         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2342         if (!compat_timer) {
  2343             return -1;
  2344         }
  2345     }
  2346     return 0;
  2347 }
  2348 
  2349 DECLSPEC int SDLCALL
  2350 SDL_putenv(const char *_var)
  2351 {
  2352     char *ptr = NULL;
  2353     char *var = SDL20_strdup(_var);
  2354     if (var == NULL) {
  2355         return -1;  /* we don't set errno. */
  2356     }
  2357 
  2358     ptr = SDL20_strchr(var, '=');
  2359     if (ptr == NULL) {
  2360         SDL20_free(var);
  2361         return -1;
  2362     }
  2363 
  2364     *ptr = '\0';  /* split the string into name and value. */
  2365     SDL20_setenv(var, ptr + 1, 1);
  2366     SDL20_free(var);
  2367     return 0;
  2368 }
  2369 
  2370 
  2371 
  2372 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2373 
  2374 typedef void *SDL12_CD;  /* close enough.  :) */
  2375 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2376 
  2377 DECLSPEC int SDLCALL
  2378 SDL_CDNumDrives(void)
  2379 {
  2380     FIXME("should return -1 without SDL_INIT_CDROM");
  2381     return 0;
  2382 }
  2383 
  2384 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2385 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2386 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2387 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2388 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2389 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2390 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2391 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2392 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2393 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  2394 
  2395 
  2396 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2397 DECLSPEC SDL_Thread * SDLCALL
  2398 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2399 {
  2400     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2401 }
  2402 #else
  2403 DECLSPEC SDL_Thread * SDLCALL
  2404 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2405 {
  2406     return SDL20_CreateThread(fn, NULL, data);
  2407 }
  2408 #endif
  2409 
  2410 DECLSPEC int SDLCALL
  2411 SDL_mutexP(SDL_mutex *mutex)
  2412 {
  2413     return SDL20_LockMutex(mutex);
  2414 }
  2415 
  2416 DECLSPEC int SDLCALL
  2417 SDL_mutexV(SDL_mutex *mutex)
  2418 {
  2419     return SDL20_UnlockMutex(mutex);
  2420 }
  2421 
  2422 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
  2423 {
  2424     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  2425     fprintf(stderr,
  2426         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  2427         "This program should be fixed. No thread was actually harmed.\n");
  2428 }
  2429 
  2430 /* This changed from an opaque pointer to an int in 2.0. */
  2431 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2432 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2433 
  2434 
  2435 DECLSPEC SDL12_TimerID SDLCALL
  2436 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2437 {
  2438     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2439 }
  2440 
  2441 DECLSPEC SDL_bool SDLCALL
  2442 SDL_RemoveTimer(SDL12_TimerID id)
  2443 {
  2444     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2445 }
  2446 
  2447 
  2448 typedef struct SDL12_RWops {
  2449     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2450     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2451     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2452     int (SDLCALL *close)(struct SDL12_RWops *context);
  2453     Uint32 type;
  2454     void *padding[8];
  2455     SDL_RWops *rwops20;
  2456 } SDL12_RWops;
  2457 
  2458 
  2459 DECLSPEC SDL12_RWops * SDLCALL
  2460 SDL_AllocRW(void)
  2461 {
  2462     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2463     if (!rwops)
  2464         SDL20_OutOfMemory();
  2465     return rwops;
  2466 }
  2467 
  2468 DECLSPEC void SDLCALL
  2469 SDL_FreeRW(SDL12_RWops *rwops12)
  2470 {
  2471     SDL20_free(rwops12);
  2472 }
  2473 
  2474 static int SDLCALL
  2475 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2476 {
  2477     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2478 }
  2479 
  2480 static int SDLCALL
  2481 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2482 {
  2483     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2484 }
  2485 
  2486 static int SDLCALL
  2487 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2488 {
  2489     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2490 }
  2491 
  2492 static int SDLCALL
  2493 RWops20to12_close(struct SDL12_RWops *rwops12)
  2494 {
  2495     int rc = 0;
  2496     if (rwops12)
  2497     {
  2498         rc = rwops12->rwops20->close(rwops12->rwops20);
  2499         if (rc == 0)
  2500             SDL_FreeRW(rwops12);
  2501     }
  2502     return rc;
  2503 }
  2504 
  2505 static SDL12_RWops *
  2506 RWops20to12(SDL_RWops *rwops20)
  2507 {
  2508     SDL12_RWops *rwops12;
  2509 
  2510     if (!rwops20)
  2511         return NULL;
  2512 
  2513     rwops12 = SDL_AllocRW();
  2514     if (!rwops12)
  2515         return NULL;
  2516 
  2517     SDL20_zerop(rwops12);
  2518     rwops12->type = rwops20->type;
  2519     rwops12->rwops20 = rwops20;
  2520     rwops12->seek = RWops20to12_seek;
  2521     rwops12->read = RWops20to12_read;
  2522     rwops12->write = RWops20to12_write;
  2523     rwops12->close = RWops20to12_close;
  2524 
  2525     return rwops12;
  2526 }
  2527 
  2528 DECLSPEC SDL12_RWops * SDLCALL
  2529 SDL_RWFromFile(const char *file, const char *mode)
  2530 {
  2531     return RWops20to12(SDL20_RWFromFile(file, mode));
  2532 }
  2533 
  2534 DECLSPEC SDL12_RWops * SDLCALL
  2535 SDL_RWFromFP(FILE *io, int autoclose)
  2536 {
  2537     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  2538 }
  2539 
  2540 DECLSPEC SDL12_RWops * SDLCALL
  2541 SDL_RWFromMem(void *mem, int size)
  2542 {
  2543     return RWops20to12(SDL20_RWFromMem(mem, size));
  2544 }
  2545 
  2546 DECLSPEC SDL12_RWops * SDLCALL
  2547 SDL_RWFromConstMem(const void *mem, int size)
  2548 {
  2549     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  2550 }
  2551 
  2552 #define READ_AND_BYTESWAP(endian, bits) \
  2553     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2554         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2555         return SDL_Swap##endian##bits(val); \
  2556     }
  2557 
  2558 READ_AND_BYTESWAP(LE,16)
  2559 READ_AND_BYTESWAP(BE,16)
  2560 READ_AND_BYTESWAP(LE,32)
  2561 READ_AND_BYTESWAP(BE,32)
  2562 READ_AND_BYTESWAP(LE,64)
  2563 READ_AND_BYTESWAP(BE,64)
  2564 #undef READ_AND_BYTESWAP
  2565 
  2566 #define BYTESWAP_AND_WRITE(endian, bits) \
  2567     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  2568         val = SDL_Swap##endian##bits(val); \
  2569         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2570     }
  2571 BYTESWAP_AND_WRITE(LE,16)
  2572 BYTESWAP_AND_WRITE(BE,16)
  2573 BYTESWAP_AND_WRITE(LE,32)
  2574 BYTESWAP_AND_WRITE(BE,32)
  2575 BYTESWAP_AND_WRITE(LE,64)
  2576 BYTESWAP_AND_WRITE(BE,64)
  2577 #undef BYTESWAP_AND_WRITE
  2578 
  2579 
  2580 static Sint64 SDLCALL
  2581 RWops12to20_size(struct SDL_RWops *rwops20)
  2582 {
  2583     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2584     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  2585     int pos;
  2586 
  2587     if (size != -1)
  2588         return size;
  2589 
  2590     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2591     if (pos == -1)
  2592         return -1;
  2593 
  2594     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  2595     if (size == -1)
  2596         return -1;
  2597 
  2598     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  2599     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  2600     return size;
  2601 }
  2602 
  2603 static Sint64 SDLCALL
  2604 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  2605 {
  2606     FIXME("fail if (offset) is too big");
  2607     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2608     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  2609 }
  2610 
  2611 static size_t SDLCALL
  2612 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  2613 {
  2614     FIXME("fail if (size) or (maxnum) is too big");
  2615     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2616     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  2617 }
  2618 
  2619 static size_t SDLCALL
  2620 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  2621 {
  2622     FIXME("fail if (size) or (maxnum) is too big");
  2623     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2624     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  2625 }
  2626 
  2627 static int SDLCALL
  2628 RWops12to20_close(struct SDL_RWops *rwops20)
  2629 {
  2630     int rc = 0;
  2631     if (rwops20)
  2632     {
  2633         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2634         rc = rwops12->close(rwops12);
  2635         if (rc == 0)
  2636             SDL20_FreeRW(rwops20);
  2637     }
  2638     return rc;
  2639 }
  2640 
  2641 static SDL_RWops *
  2642 RWops12to20(SDL12_RWops *rwops12)
  2643 {
  2644     SDL_RWops *rwops20;
  2645 
  2646     if (!rwops12)
  2647         return NULL;
  2648 
  2649     rwops20 = SDL20_AllocRW();
  2650     if (!rwops20)
  2651         return NULL;
  2652 
  2653     SDL20_zerop(rwops20);
  2654     rwops20->type = rwops12->type;
  2655     rwops20->hidden.unknown.data1 = rwops12;
  2656     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  2657     rwops20->size = RWops12to20_size;
  2658     rwops20->seek = RWops12to20_seek;
  2659     rwops20->read = RWops12to20_read;
  2660     rwops20->write = RWops12to20_write;
  2661     rwops20->close = RWops12to20_close;
  2662     return rwops20;
  2663 }
  2664 
  2665 DECLSPEC SDL12_Surface * SDLCALL
  2666 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  2667 {
  2668     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2669     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  2670     SDL12_Surface *surface12 = Surface20to12(surface20);
  2671     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2672         SDL20_FreeRW(rwops20);
  2673     if ((!surface12) && (surface20))
  2674         SDL20_FreeSurface(surface20);
  2675     return surface12;
  2676 }
  2677 
  2678 DECLSPEC int SDLCALL
  2679 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  2680 {
  2681     FIXME("wrap surface");
  2682     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2683     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  2684     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2685         SDL20_FreeRW(rwops20);
  2686     return retval;
  2687 }
  2688 
  2689 DECLSPEC SDL_AudioSpec * SDLCALL
  2690 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  2691                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  2692 {
  2693     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2694     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  2695     FIXME("deal with non-1.2 formats, like float32");
  2696     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2697         SDL20_FreeRW(rwops20);
  2698     return retval;
  2699 }
  2700 
  2701 /* vi: set ts=4 sw=4 expandtab: */