src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 18 Feb 2019 00:25:14 -0500
changeset 66 5cd0103f58ca
parent 65 68cb13eba09d
child 67 4df59270e628
permissions -rw-r--r--
Ignore new SDL_SIMD_ALIGNED flag for now.
     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 SDL_Rect orig_dstrect = *dstrect;
  1412     const int retval = SDL20_FillRect(dst->surface20, &orig_dstrect, color);
  1413     if (retval != -1)
  1414     {
  1415         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1416             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1417     }
  1418     return retval;
  1419 }
  1420 
  1421 
  1422 static SDL_PixelFormat *
  1423 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1424 {
  1425     palette20->ncolors = format12->palette->ncolors;
  1426     palette20->colors = format12->palette->colors;
  1427     palette20->version = 1;
  1428     palette20->refcount = 1;
  1429     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1430     format20->palette = palette20;
  1431     format20->BitsPerPixel = format12->BitsPerPixel;
  1432     format20->BytesPerPixel = format12->BytesPerPixel;
  1433     format20->Rmask = format12->Rmask;
  1434     format20->Gmask = format12->Gmask;
  1435     format20->Bmask = format12->Bmask;
  1436     format20->Amask = format12->Amask;
  1437     format20->Rloss = format12->Rloss;
  1438     format20->Gloss = format12->Gloss;
  1439     format20->Bloss = format12->Bloss;
  1440     format20->Aloss = format12->Aloss;
  1441     format20->Rshift = format12->Rshift;
  1442     format20->Gshift = format12->Gshift;
  1443     format20->Bshift = format12->Bshift;
  1444     format20->Ashift = format12->Ashift;
  1445     format20->refcount = 1;
  1446     format20->next = NULL;
  1447     return format20;
  1448 }
  1449 
  1450 DECLSPEC Uint32 SDLCALL
  1451 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1452 {
  1453     /* This is probably way slower than apps expect. */
  1454     SDL_PixelFormat format20;
  1455     SDL_Palette palette20;
  1456     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1457 }
  1458 
  1459 DECLSPEC Uint32 SDLCALL
  1460 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1461 {
  1462     /* This is probably way slower than apps expect. */
  1463     SDL_PixelFormat format20;
  1464     SDL_Palette palette20;
  1465     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1466 }
  1467 
  1468 DECLSPEC void SDLCALL
  1469 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1470 {
  1471     /* This is probably way slower than apps expect. */
  1472     SDL_PixelFormat format20;
  1473     SDL_Palette palette20;
  1474     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1475 }
  1476 
  1477 DECLSPEC void SDLCALL
  1478 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1479 {
  1480     /* This is probably way slower than apps expect. */
  1481     SDL_PixelFormat format20;
  1482     SDL_Palette palette20;
  1483     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1484 }
  1485 
  1486 DECLSPEC const SDL12_VideoInfo * SDLCALL
  1487 SDL_GetVideoInfo(void)
  1488 {
  1489     SDL_DisplayMode mode;
  1490 
  1491     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  1492 
  1493     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1494         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  1495         VideoInfo12.current_w = mode.w;
  1496         VideoInfo12.current_h = mode.h;
  1497         FIXME("vidinfo details commented out");
  1498         //VideoInfo12.wm_available = 1;
  1499         //VideoInfo12.video_mem = 1024 * 256;
  1500     }
  1501     return &VideoInfo12;
  1502 }
  1503 
  1504 DECLSPEC int SDLCALL
  1505 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1506 {
  1507     int i, nummodes, actual_bpp = 0;
  1508 
  1509     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1510         return 0;
  1511     }
  1512 
  1513     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1514         SDL_DisplayMode mode;
  1515         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1516         return SDL_BITSPERPIXEL(mode.format);
  1517     }
  1518 
  1519     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1520     for (i = 0; i < nummodes; ++i) {
  1521         SDL_DisplayMode mode;
  1522         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1523         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1524             if (!mode.format) {
  1525                 return bpp;
  1526             }
  1527             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1528                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1529             }
  1530         }
  1531     }
  1532     return actual_bpp;
  1533 }
  1534 
  1535 DECLSPEC SDL_Rect ** SDLCALL
  1536 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  1537 {
  1538     Uint32 fmt;
  1539     int i;
  1540 
  1541     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1542         return NULL;
  1543     }
  1544 
  1545     if ((!format12) && (!VideoInfo12.vfmt)) {
  1546         SDL20_SetError("No pixel format specified");
  1547         return NULL;
  1548     }
  1549 
  1550     if (!(flags & SDL12_FULLSCREEN)) {
  1551         return (SDL_Rect **) (-1);  /* any resolution is fine. */
  1552     }
  1553 
  1554     if (format12) {
  1555         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1556     } else {
  1557         fmt = VideoInfo12.vfmt->format;
  1558     }
  1559 
  1560     for (i = 0; i < VideoModesCount; i++) {
  1561         VideoModeList *modes = &VideoModes[i];
  1562         if (modes->format == fmt) {
  1563             return modes->modes;
  1564         }
  1565     }
  1566 
  1567     SDL20_SetError("No modes support requested pixel format");
  1568     return NULL;
  1569 }
  1570 
  1571 DECLSPEC void SDLCALL
  1572 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1573 {
  1574     if (cursor12) {
  1575         if (cursor12->wm_cursor)
  1576             SDL20_FreeCursor(cursor12->wm_cursor);
  1577         SDL20_free(cursor12->data);
  1578         SDL20_free(cursor12->mask);
  1579         SDL20_free(cursor12);
  1580     }
  1581 }
  1582 
  1583 DECLSPEC SDL12_Cursor * SDLCALL
  1584 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1585 {
  1586     const size_t datasize = h * (w / 8);
  1587     SDL_Cursor *cursor20 = NULL;
  1588     SDL12_Cursor *retval = NULL;
  1589 
  1590     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1591     if (!retval)
  1592         goto outofmem;
  1593 
  1594     SDL20_zerop(retval);
  1595 
  1596     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1597     if (!retval->data)
  1598         goto outofmem;
  1599 
  1600     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1601     if (!retval->mask)
  1602         goto outofmem;
  1603 
  1604     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1605     if (!cursor20)
  1606         goto failed;
  1607 
  1608     retval->area.w = w;
  1609     retval->area.h = h;
  1610     retval->hot_x = hot_x;
  1611     retval->hot_y = hot_y;
  1612     retval->wm_cursor = cursor20;
  1613     /* we always leave retval->save as null pointers. */
  1614 
  1615     SDL20_memcpy(retval->data, data, datasize);
  1616     SDL20_memcpy(retval->mask, mask, datasize);
  1617 
  1618     return retval;
  1619 
  1620 outofmem:
  1621     SDL20_OutOfMemory();
  1622 
  1623 failed:
  1624     SDL_FreeCursor(retval);
  1625     return NULL;
  1626 }
  1627 
  1628 DECLSPEC void SDLCALL
  1629 SDL_SetCursor(SDL12_Cursor *cursor)
  1630 {
  1631     CurrentCursor12 = cursor;
  1632     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1633 }
  1634 
  1635 DECLSPEC SDL12_Cursor * SDLCALL
  1636 SDL_GetCursor(void)
  1637 {
  1638     return CurrentCursor12;
  1639 }
  1640 
  1641 static void
  1642 GetEnvironmentWindowPosition(int *x, int *y)
  1643 {
  1644     int display = VideoDisplayIndex;
  1645     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  1646     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  1647     if (window) {
  1648         if (SDL20_strcmp(window, "center") == 0) {
  1649             center = window;
  1650         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  1651             return;
  1652         }
  1653     }
  1654 
  1655     if (center) {
  1656         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1657         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1658     }
  1659 }
  1660 
  1661 static void
  1662 SetupScreenSaver(const int flags12)
  1663 {
  1664     const char *env;
  1665     SDL_bool allow_screensaver;
  1666 
  1667     /* Allow environment override of screensaver disable */
  1668     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1669     if (env) {
  1670         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1671     } else if (flags12 & SDL12_FULLSCREEN) {
  1672         allow_screensaver = SDL_FALSE;
  1673     } else {
  1674         allow_screensaver = SDL_TRUE;
  1675     }
  1676     if (allow_screensaver) {
  1677         SDL20_EnableScreenSaver();
  1678     } else {
  1679         SDL20_DisableScreenSaver();
  1680     }
  1681 }
  1682 
  1683 
  1684 static SDL12_Surface *
  1685 EndVidModeCreate(void)
  1686 {
  1687     if (VideoTexture20) {
  1688         SDL20_DestroyTexture(VideoTexture20);
  1689         VideoTexture20 = NULL;
  1690     }
  1691     if (VideoRenderer20) {
  1692         SDL20_DestroyRenderer(VideoRenderer20);
  1693         VideoRenderer20 = NULL;
  1694     }
  1695     if (VideoGLContext20) {
  1696         SDL20_GL_MakeCurrent(NULL, NULL);
  1697         SDL20_GL_DeleteContext(VideoGLContext20);
  1698         VideoGLContext20 = NULL;
  1699     }
  1700     if (VideoWindow20) {
  1701         SDL20_DestroyWindow(VideoWindow20);
  1702         VideoWindow20 = NULL;
  1703     }
  1704     if (VideoSurface12) {
  1705         SDL20_free(VideoSurface12->pixels);
  1706         VideoSurface12->pixels = NULL;
  1707         SDL_FreeSurface(VideoSurface12);
  1708         VideoSurface12 = NULL;
  1709     }
  1710     if (VideoConvertSurface20) {
  1711         SDL20_FreeSurface(VideoConvertSurface20);
  1712         VideoConvertSurface20 = NULL;
  1713     }
  1714     return NULL;
  1715 }
  1716 
  1717 
  1718 static SDL12_Surface *
  1719 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  1720 {
  1721     Uint32 rmask, gmask, bmask, amask;
  1722     int bpp;
  1723     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  1724         return NULL;
  1725     }
  1726     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  1727 }
  1728 
  1729 static SDL_Surface *
  1730 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  1731 {
  1732     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  1733     if (surface20) {
  1734         surface20->flags |= SDL_PREALLOC;
  1735         surface20->pixels = NULL;
  1736         surface20->w = width;
  1737         surface20->h = height;
  1738         surface20->pitch = 0;
  1739         SDL20_SetClipRect(surface20, NULL);
  1740     }
  1741     return surface20;
  1742 }
  1743 
  1744 
  1745 DECLSPEC SDL12_Surface * SDLCALL
  1746 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1747 {
  1748     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  1749     SDL_DisplayMode dmode;
  1750     Uint32 fullscreen_flags20 = 0;
  1751     Uint32 appfmt;
  1752 
  1753     /* SDL_SetVideoMode() implicitly inits if necessary. */
  1754     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  1755         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  1756             return NULL;
  1757         }
  1758     }
  1759 
  1760     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  1761         FIXME("No OPENGLBLIT support at the moment");
  1762         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  1763         return NULL;
  1764     }
  1765 
  1766     FIXME("handle SDL_ANYFORMAT");
  1767 
  1768     if ((width < 0) || (height < 0)) {
  1769         SDL20_SetError("Invalid width or height");
  1770         return NULL;
  1771     }
  1772 
  1773     FIXME("There's an environment variable to choose a display");
  1774     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  1775         return NULL;
  1776     }
  1777 
  1778     if (width == 0) {
  1779         width = dmode.w;
  1780     }
  1781 
  1782     if (height == 0) {
  1783         height = dmode.h;
  1784     }
  1785 
  1786     if (bpp == 0) {
  1787         bpp = SDL_BITSPERPIXEL(dmode.format);
  1788     }
  1789 
  1790     switch (bpp) {
  1791         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  1792         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  1793         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  1794         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  1795         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  1796     }
  1797 
  1798     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  1799 
  1800     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  1801     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  1802 
  1803     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  1804         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  1805     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  1806         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  1807     } else if (VideoGLContext20) {
  1808         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  1809         SDL20_GL_MakeCurrent(NULL, NULL);
  1810         SDL20_GL_DeleteContext(VideoGLContext20);
  1811         VideoGLContext20 = NULL;
  1812     }
  1813 
  1814     if (flags12 & SDL12_FULLSCREEN) {
  1815         // OpenGL tries to force the real resolution requested, but for
  1816         //  software rendering, we're just going to push it off onto the
  1817         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  1818         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  1819         if (flags12 & SDL12_OPENGL) {
  1820             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  1821         } else {
  1822             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  1823         }
  1824     }
  1825 
  1826     if (!VideoWindow20) {  /* create it */
  1827         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  1828         Uint32 flags20 = fullscreen_flags20;
  1829         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  1830         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  1831         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  1832 
  1833         /* most platforms didn't check these environment variables, but the major
  1834            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  1835         GetEnvironmentWindowPosition(&x, &y);
  1836 
  1837         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  1838         if (!VideoWindow20) {
  1839             return EndVidModeCreate();
  1840         }
  1841     } else {  /* resize it */
  1842         SDL20_SetWindowSize(VideoWindow20, width, height);
  1843         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  1844         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  1845         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  1846     }
  1847 
  1848     if (VideoSurface12) {
  1849         SDL20_free(VideoSurface12->pixels);
  1850     } else {
  1851         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  1852         if (!VideoSurface12) {
  1853             return EndVidModeCreate();
  1854         }
  1855     }
  1856 
  1857     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  1858     VideoSurface12->flags |= SDL12_PREALLOC;
  1859     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  1860     VideoSurface12->w = VideoSurface12->surface20->w = width;
  1861     VideoSurface12->h = VideoSurface12->surface20->h = height;
  1862     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  1863     SDL_SetClipRect(VideoSurface12, NULL);
  1864 
  1865     if (flags12 & SDL12_OPENGL) {
  1866         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  1867         SDL_assert(!VideoRenderer20);
  1868         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  1869         if (!VideoGLContext20) {
  1870             return EndVidModeCreate();
  1871         }
  1872 
  1873         VideoSurface12->flags |= SDL12_OPENGL;
  1874     } else {
  1875         /* always use a renderer for non-OpenGL windows. */
  1876         SDL_RendererInfo rinfo;
  1877         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  1878         if (!VideoRenderer20) {
  1879             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  1880             if (!VideoRenderer20) {
  1881                 return EndVidModeCreate();
  1882             }
  1883         }
  1884 
  1885         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  1886         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  1887         SDL20_RenderClear(VideoRenderer20);
  1888         SDL20_RenderPresent(VideoRenderer20);
  1889         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  1890 
  1891         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  1892             return EndVidModeCreate();
  1893         }
  1894 
  1895         if (VideoTexture20) {
  1896             SDL20_DestroyTexture(VideoTexture20);
  1897         }
  1898 
  1899         if (VideoConvertSurface20) {
  1900             SDL20_FreeSurface(VideoConvertSurface20);
  1901             VideoConvertSurface20 = NULL;
  1902         }
  1903 
  1904         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  1905         if (!VideoTexture20) {
  1906             return EndVidModeCreate();
  1907         }
  1908 
  1909         if (rinfo.texture_formats[0] != appfmt) {
  1910             /* need to convert between app's format and texture format */
  1911             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  1912             if (!VideoConvertSurface20) {
  1913                 return EndVidModeCreate();
  1914             }
  1915         }
  1916 
  1917         VideoSurface12->flags &= ~SDL12_OPENGL;
  1918         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  1919         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  1920         if (!VideoSurface12->pixels) {
  1921             SDL20_OutOfMemory();
  1922             return EndVidModeCreate();
  1923         }
  1924     }
  1925 
  1926     FIXME("setup screen saver");
  1927 
  1928     return VideoSurface12;
  1929 }
  1930 
  1931 DECLSPEC SDL12_Surface * SDLCALL
  1932 SDL_GetVideoSurface(void)
  1933 {
  1934     return VideoSurface12;
  1935 }
  1936 
  1937 DECLSPEC int SDLCALL
  1938 SDL_UpperBlit(SDL12_Surface *src, SDL_Rect *srcrect, SDL12_Surface *dst, SDL_Rect *dstrect)
  1939 {
  1940     return SDL20_UpperBlit(src->surface20, srcrect, dst->surface20, dstrect);
  1941 }
  1942 
  1943 DECLSPEC int SDLCALL
  1944 SDL_LowerBlit(SDL12_Surface *src, SDL_Rect *srcrect, SDL12_Surface *dst, SDL_Rect *dstrect)
  1945 {
  1946     return SDL20_LowerBlit(src->surface20, srcrect, dst->surface20, dstrect);
  1947 }
  1948 
  1949 DECLSPEC int SDLCALL
  1950 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  1951 {
  1952     FIXME("write me");
  1953     return SDL20_Unsupported();
  1954 }
  1955 
  1956 DECLSPEC SDL12_Surface * SDLCALL
  1957 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
  1958 {
  1959     Uint32 flags20 = 0;
  1960     SDL_PixelFormat format20;
  1961     SDL_Palette palette20;
  1962     SDL_Surface *surface20;
  1963     SDL12_Surface *retval = NULL;
  1964 
  1965     if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
  1966     if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
  1967 
  1968     surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
  1969     if (surface20) {
  1970         retval = Surface20to12(surface20);
  1971         if (!retval) {
  1972             SDL20_FreeSurface(surface20);
  1973         }
  1974     }
  1975     return retval;
  1976 }
  1977 
  1978 DECLSPEC SDL12_Surface * SDLCALL
  1979 SDL_DisplayFormat(SDL12_Surface *surface12)
  1980 {
  1981     const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
  1982     return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
  1983 }
  1984 
  1985 DECLSPEC SDL12_Surface * SDLCALL
  1986 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1987 {
  1988     FIXME("write me");
  1989     SDL20_Unsupported();
  1990     return NULL;
  1991 }
  1992 
  1993 DECLSPEC void SDLCALL
  1994 SDL_UpdateRects(SDL12_Surface * screen12, int numrects, SDL_Rect * rects)
  1995 {
  1996     FIXME("write me");
  1997     SDL20_Unsupported();
  1998 }
  1999 
  2000 DECLSPEC void SDLCALL
  2001 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  2002 {
  2003     if (screen12) {
  2004         SDL_Rect rect;
  2005         rect.x = (int) x;
  2006         rect.y = (int) y;
  2007         rect.w = (int) (w ? w : screen12->w);
  2008         rect.h = (int) (h ? h : screen12->h);
  2009         SDL_UpdateRects(screen12, 1, &rect);
  2010     }
  2011 }
  2012 
  2013 DECLSPEC int SDLCALL
  2014 SDL_Flip(SDL12_Surface *screen12)
  2015 {
  2016     SDL_UpdateRect(screen12, 0, 0, 0, 0);
  2017     return 0;
  2018 }
  2019 
  2020 DECLSPEC void SDLCALL
  2021 SDL_WM_SetCaption(const char *title, const char *icon)
  2022 {
  2023     if (WindowTitle) {
  2024         SDL20_free(WindowTitle);
  2025     }
  2026     if (WindowIconTitle) {
  2027         SDL20_free(WindowIconTitle);
  2028     }
  2029     WindowTitle = title ? SDL_strdup(title) : NULL;
  2030     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  2031     if (VideoWindow20) {
  2032         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  2033     }
  2034 }
  2035 
  2036 DECLSPEC void SDLCALL
  2037 SDL_WM_GetCaption(const char **title, const char **icon)
  2038 {
  2039     if (title) {
  2040         *title = WindowTitle;
  2041     }
  2042     if (icon) {
  2043         *icon = WindowIconTitle;
  2044     }
  2045 }
  2046 
  2047 DECLSPEC void SDLCALL
  2048 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2049 {
  2050     FIXME("write me");
  2051     SDL20_Unsupported();
  2052 }
  2053 
  2054 DECLSPEC int SDLCALL
  2055 SDL_WM_IconifyWindow(void)
  2056 {
  2057     SDL20_MinimizeWindow(VideoWindow20);
  2058     return 0;
  2059 }
  2060 
  2061 DECLSPEC int SDLCALL
  2062 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  2063 {
  2064     FIXME("write me");
  2065     return SDL20_Unsupported();
  2066 }
  2067 
  2068 typedef enum
  2069 {
  2070     SDL12_GRAB_QUERY = -1,
  2071     SDL12_GRAB_OFF = 0,
  2072     SDL12_GRAB_ON = 1
  2073 } SDL12_GrabMode;
  2074 
  2075 DECLSPEC SDL12_GrabMode SDLCALL
  2076 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2077 {
  2078     if (mode != SDL12_GRAB_QUERY) {
  2079         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2080     }
  2081     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2082 }
  2083 
  2084 DECLSPEC void SDLCALL
  2085 SDL_WarpMouse(Uint16 x, Uint16 y)
  2086 {
  2087     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2088 }
  2089 
  2090 DECLSPEC Uint8 SDLCALL
  2091 SDL_GetAppState(void)
  2092 {
  2093     Uint8 state12 = 0;
  2094     Uint32 flags20 = 0;
  2095 
  2096     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2097     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2098         state12 |= SDL12_APPACTIVE;
  2099     }
  2100     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2101         state12 |= SDL12_APPINPUTFOCUS;
  2102     }
  2103     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2104         state12 |= SDL12_APPMOUSEFOCUS;
  2105     }
  2106     return state12;
  2107 }
  2108 
  2109 DECLSPEC int SDLCALL
  2110 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2111                int firstcolor, int ncolors)
  2112 {
  2113     FIXME("write me");
  2114     return SDL20_Unsupported();
  2115 }
  2116 
  2117 DECLSPEC int SDLCALL
  2118 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2119               int ncolors)
  2120 {
  2121     FIXME("write me");
  2122     return SDL20_Unsupported();
  2123 }
  2124 
  2125 DECLSPEC int SDLCALL
  2126 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2127 {
  2128     FIXME("write me");
  2129     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  2130     return SDL20_Unsupported();
  2131 }
  2132 
  2133 DECLSPEC SDL12_Overlay * SDLCALL
  2134 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2135 {
  2136     FIXME("write me");
  2137     SDL20_Unsupported();
  2138     return NULL;
  2139 }
  2140 
  2141 DECLSPEC int SDLCALL
  2142 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  2143 {
  2144     FIXME("write me");
  2145     return SDL20_Unsupported();
  2146 }
  2147 
  2148 DECLSPEC void SDLCALL
  2149 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  2150 {
  2151     FIXME("write me");
  2152 }
  2153 
  2154 DECLSPEC int SDLCALL
  2155 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL_Rect * dstrect)
  2156 {
  2157     FIXME("write me");
  2158     return SDL20_Unsupported();
  2159 }
  2160 
  2161 DECLSPEC void SDLCALL
  2162 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  2163 {
  2164     FIXME("write me");
  2165 }
  2166 
  2167 DECLSPEC int SDLCALL
  2168 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2169 {
  2170     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2171         return SDL20_SetError("Unknown GL attribute");
  2172 
  2173     /* swap control was moved out of this API, everything else lines up. */
  2174     if (attr == SDL12_GL_SWAP_CONTROL)
  2175     {
  2176         SwapInterval = value;
  2177         FIXME("Actually set swap interval somewhere");
  2178         return 0;
  2179     }
  2180 
  2181     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2182 }
  2183 
  2184 DECLSPEC int SDLCALL
  2185 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2186 {
  2187     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2188         return SDL20_SetError("Unknown GL attribute");
  2189 
  2190     /* swap control was moved out of this API, everything else lines up. */
  2191     if (attr == SDL12_GL_SWAP_CONTROL)
  2192     {
  2193         *value = SDL20_GL_GetSwapInterval();
  2194         return 0;
  2195     }
  2196 
  2197     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2198 }
  2199 
  2200 
  2201 DECLSPEC void SDLCALL
  2202 SDL_GL_SwapBuffers(void)
  2203 {
  2204     if (VideoWindow20)
  2205         SDL20_GL_SwapWindow(VideoWindow20);
  2206 }
  2207 
  2208 DECLSPEC int SDLCALL
  2209 SDL_SetGamma(float red, float green, float blue)
  2210 {
  2211     Uint16 red_ramp[256];
  2212     Uint16 green_ramp[256];
  2213     Uint16 blue_ramp[256];
  2214 
  2215     SDL20_CalculateGammaRamp(red, red_ramp);
  2216     if (green == red) {
  2217         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2218     } else {
  2219         SDL20_CalculateGammaRamp(green, green_ramp);
  2220     }
  2221     if (blue == red) {
  2222         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2223     } else if (blue == green) {
  2224         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2225     } else {
  2226         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2227     }
  2228     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2229 }
  2230 
  2231 DECLSPEC int SDLCALL
  2232 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2233 {
  2234     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2235 }
  2236 
  2237 DECLSPEC int SDLCALL
  2238 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2239 {
  2240     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2241 }
  2242 
  2243 DECLSPEC int SDLCALL
  2244 SDL_EnableKeyRepeat(int delay, int interval)
  2245 {
  2246     return 0;
  2247 }
  2248 
  2249 DECLSPEC void SDLCALL
  2250 SDL_GetKeyRepeat(int *delay, int *interval)
  2251 {
  2252     if (delay) {
  2253         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2254     }
  2255     if (interval) {
  2256         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2257     }
  2258 }
  2259 
  2260 DECLSPEC int SDLCALL
  2261 SDL_EnableUNICODE(int enable)
  2262 {
  2263     FIXME("write me");
  2264     return SDL20_Unsupported();
  2265 }
  2266 
  2267 static Uint32
  2268 SetTimerOld_Callback(Uint32 interval, void* param)
  2269 {
  2270     return ((SDL12_TimerCallback)param)(interval);
  2271 }
  2272 
  2273 DECLSPEC int SDLCALL
  2274 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2275 {
  2276     static SDL_TimerID compat_timer;
  2277 
  2278     if (compat_timer) {
  2279         SDL20_RemoveTimer(compat_timer);
  2280         compat_timer = 0;
  2281     }
  2282 
  2283     if (interval && callback) {
  2284         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2285         if (!compat_timer) {
  2286             return -1;
  2287         }
  2288     }
  2289     return 0;
  2290 }
  2291 
  2292 DECLSPEC int SDLCALL
  2293 SDL_putenv(const char *_var)
  2294 {
  2295     char *ptr = NULL;
  2296     char *var = SDL20_strdup(_var);
  2297     if (var == NULL) {
  2298         return -1;  /* we don't set errno. */
  2299     }
  2300 
  2301     ptr = SDL20_strchr(var, '=');
  2302     if (ptr == NULL) {
  2303         SDL20_free(var);
  2304         return -1;
  2305     }
  2306 
  2307     *ptr = '\0';  /* split the string into name and value. */
  2308     SDL20_setenv(var, ptr + 1, 1);
  2309     SDL20_free(var);
  2310     return 0;
  2311 }
  2312 
  2313 
  2314 
  2315 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2316 
  2317 typedef void *SDL12_CD;  /* close enough.  :) */
  2318 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2319 
  2320 DECLSPEC int SDLCALL
  2321 SDL_CDNumDrives(void)
  2322 {
  2323     FIXME("should return -1 without SDL_INIT_CDROM");
  2324     return 0;
  2325 }
  2326 
  2327 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2328 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2329 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2330 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2331 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2332 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2333 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2334 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2335 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2336 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  2337 
  2338 
  2339 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2340 DECLSPEC SDL_Thread * SDLCALL
  2341 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2342 {
  2343     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2344 }
  2345 #else
  2346 DECLSPEC SDL_Thread * SDLCALL
  2347 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2348 {
  2349     return SDL20_CreateThread(fn, NULL, data);
  2350 }
  2351 #endif
  2352 
  2353 DECLSPEC int SDLCALL
  2354 SDL_mutexP(SDL_mutex *mutex)
  2355 {
  2356     return SDL20_LockMutex(mutex);
  2357 }
  2358 
  2359 DECLSPEC int SDLCALL
  2360 SDL_mutexV(SDL_mutex *mutex)
  2361 {
  2362     return SDL20_UnlockMutex(mutex);
  2363 }
  2364 
  2365 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
  2366 {
  2367     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  2368     fprintf(stderr,
  2369         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  2370         "This program should be fixed. No thread was actually harmed.\n");
  2371 }
  2372 
  2373 /* This changed from an opaque pointer to an int in 2.0. */
  2374 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2375 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2376 
  2377 
  2378 DECLSPEC SDL12_TimerID SDLCALL
  2379 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2380 {
  2381     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2382 }
  2383 
  2384 DECLSPEC SDL_bool SDLCALL
  2385 SDL_RemoveTimer(SDL12_TimerID id)
  2386 {
  2387     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2388 }
  2389 
  2390 
  2391 typedef struct SDL12_RWops {
  2392     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2393     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2394     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2395     int (SDLCALL *close)(struct SDL12_RWops *context);
  2396     Uint32 type;
  2397     void *padding[8];
  2398     SDL_RWops *rwops20;
  2399 } SDL12_RWops;
  2400 
  2401 
  2402 DECLSPEC SDL12_RWops * SDLCALL
  2403 SDL_AllocRW(void)
  2404 {
  2405     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2406     if (!rwops)
  2407         SDL20_OutOfMemory();
  2408     return rwops;
  2409 }
  2410 
  2411 DECLSPEC void SDLCALL
  2412 SDL_FreeRW(SDL12_RWops *rwops12)
  2413 {
  2414     SDL20_free(rwops12);
  2415 }
  2416 
  2417 static int SDLCALL
  2418 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2419 {
  2420     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2421 }
  2422 
  2423 static int SDLCALL
  2424 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2425 {
  2426     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2427 }
  2428 
  2429 static int SDLCALL
  2430 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2431 {
  2432     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2433 }
  2434 
  2435 static int SDLCALL
  2436 RWops20to12_close(struct SDL12_RWops *rwops12)
  2437 {
  2438     int rc = 0;
  2439     if (rwops12)
  2440     {
  2441         rc = rwops12->rwops20->close(rwops12->rwops20);
  2442         if (rc == 0)
  2443             SDL_FreeRW(rwops12);
  2444     }
  2445     return rc;
  2446 }
  2447 
  2448 static SDL12_RWops *
  2449 RWops20to12(SDL_RWops *rwops20)
  2450 {
  2451     SDL12_RWops *rwops12;
  2452 
  2453     if (!rwops20)
  2454         return NULL;
  2455 
  2456     rwops12 = SDL_AllocRW();
  2457     if (!rwops12)
  2458         return NULL;
  2459 
  2460     SDL20_zerop(rwops12);
  2461     rwops12->type = rwops20->type;
  2462     rwops12->rwops20 = rwops20;
  2463     rwops12->seek = RWops20to12_seek;
  2464     rwops12->read = RWops20to12_read;
  2465     rwops12->write = RWops20to12_write;
  2466     rwops12->close = RWops20to12_close;
  2467 
  2468     return rwops12;
  2469 }
  2470 
  2471 DECLSPEC SDL12_RWops * SDLCALL
  2472 SDL_RWFromFile(const char *file, const char *mode)
  2473 {
  2474     return RWops20to12(SDL20_RWFromFile(file, mode));
  2475 }
  2476 
  2477 DECLSPEC SDL12_RWops * SDLCALL
  2478 SDL_RWFromFP(FILE *io, int autoclose)
  2479 {
  2480     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  2481 }
  2482 
  2483 DECLSPEC SDL12_RWops * SDLCALL
  2484 SDL_RWFromMem(void *mem, int size)
  2485 {
  2486     return RWops20to12(SDL20_RWFromMem(mem, size));
  2487 }
  2488 
  2489 DECLSPEC SDL12_RWops * SDLCALL
  2490 SDL_RWFromConstMem(const void *mem, int size)
  2491 {
  2492     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  2493 }
  2494 
  2495 #define READ_AND_BYTESWAP(endian, bits) \
  2496     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2497         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2498         return SDL_Swap##endian##bits(val); \
  2499     }
  2500 
  2501 READ_AND_BYTESWAP(LE,16)
  2502 READ_AND_BYTESWAP(BE,16)
  2503 READ_AND_BYTESWAP(LE,32)
  2504 READ_AND_BYTESWAP(BE,32)
  2505 READ_AND_BYTESWAP(LE,64)
  2506 READ_AND_BYTESWAP(BE,64)
  2507 #undef READ_AND_BYTESWAP
  2508 
  2509 #define BYTESWAP_AND_WRITE(endian, bits) \
  2510     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  2511         val = SDL_Swap##endian##bits(val); \
  2512         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2513     }
  2514 BYTESWAP_AND_WRITE(LE,16)
  2515 BYTESWAP_AND_WRITE(BE,16)
  2516 BYTESWAP_AND_WRITE(LE,32)
  2517 BYTESWAP_AND_WRITE(BE,32)
  2518 BYTESWAP_AND_WRITE(LE,64)
  2519 BYTESWAP_AND_WRITE(BE,64)
  2520 #undef BYTESWAP_AND_WRITE
  2521 
  2522 
  2523 static Sint64 SDLCALL
  2524 RWops12to20_size(struct SDL_RWops *rwops20)
  2525 {
  2526     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2527     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  2528     int pos;
  2529 
  2530     if (size != -1)
  2531         return size;
  2532 
  2533     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2534     if (pos == -1)
  2535         return -1;
  2536 
  2537     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  2538     if (size == -1)
  2539         return -1;
  2540 
  2541     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  2542     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  2543     return size;
  2544 }
  2545 
  2546 static Sint64 SDLCALL
  2547 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  2548 {
  2549     FIXME("fail if (offset) is too big");
  2550     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2551     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  2552 }
  2553 
  2554 static size_t SDLCALL
  2555 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  2556 {
  2557     FIXME("fail if (size) or (maxnum) is too big");
  2558     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2559     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  2560 }
  2561 
  2562 static size_t SDLCALL
  2563 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  2564 {
  2565     FIXME("fail if (size) or (maxnum) is too big");
  2566     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2567     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  2568 }
  2569 
  2570 static int SDLCALL
  2571 RWops12to20_close(struct SDL_RWops *rwops20)
  2572 {
  2573     int rc = 0;
  2574     if (rwops20)
  2575     {
  2576         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2577         rc = rwops12->close(rwops12);
  2578         if (rc == 0)
  2579             SDL20_FreeRW(rwops20);
  2580     }
  2581     return rc;
  2582 }
  2583 
  2584 static SDL_RWops *
  2585 RWops12to20(SDL12_RWops *rwops12)
  2586 {
  2587     SDL_RWops *rwops20;
  2588 
  2589     if (!rwops12)
  2590         return NULL;
  2591 
  2592     rwops20 = SDL20_AllocRW();
  2593     if (!rwops20)
  2594         return NULL;
  2595 
  2596     SDL20_zerop(rwops20);
  2597     rwops20->type = rwops12->type;
  2598     rwops20->hidden.unknown.data1 = rwops12;
  2599     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  2600     rwops20->size = RWops12to20_size;
  2601     rwops20->seek = RWops12to20_seek;
  2602     rwops20->read = RWops12to20_read;
  2603     rwops20->write = RWops12to20_write;
  2604     rwops20->close = RWops12to20_close;
  2605     return rwops20;
  2606 }
  2607 
  2608 DECLSPEC SDL12_Surface * SDLCALL
  2609 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  2610 {
  2611     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2612     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  2613     SDL12_Surface *surface12 = Surface20to12(surface20);
  2614     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2615         SDL20_FreeRW(rwops20);
  2616     if ((!surface12) && (surface20))
  2617         SDL20_FreeSurface(surface20);
  2618     return surface12;
  2619 }
  2620 
  2621 DECLSPEC int SDLCALL
  2622 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  2623 {
  2624     FIXME("wrap surface");
  2625     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2626     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  2627     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2628         SDL20_FreeRW(rwops20);
  2629     return retval;
  2630 }
  2631 
  2632 DECLSPEC SDL_AudioSpec * SDLCALL
  2633 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  2634                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  2635 {
  2636     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2637     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  2638     FIXME("deal with non-1.2 formats, like float32");
  2639     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2640         SDL20_FreeRW(rwops20);
  2641     return retval;
  2642 }
  2643 
  2644 /* vi: set ts=4 sw=4 expandtab: */