src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 13 Feb 2019 20:56:09 -0500
changeset 60 76cf0dc4bce4
parent 59 39067b54d1b0
child 61 832594ced260
permissions -rw-r--r--
Fixed some symbols that aren't actually available in SDL 2.0.
     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_ConvertSurface
    54 // !!! IMPLEMENT_ME SDL_CreateYUVOverlay
    55 
    56 // !!! IMPLEMENT_ME SDL_DisplayFormat
    57 // !!! IMPLEMENT_ME SDL_DisplayFormatAlpha
    58 // !!! IMPLEMENT_ME SDL_DisplayYUVOverlay
    59 // !!! IMPLEMENT_ME SDL_EnableKeyRepeat
    60 // !!! IMPLEMENT_ME SDL_EnableUNICODE
    61 // !!! IMPLEMENT_ME SDL_FreeYUVOverlay
    62 
    63 // !!! IMPLEMENT_ME SDL_GL_Lock
    64 // !!! IMPLEMENT_ME SDL_GL_Unlock
    65 // !!! IMPLEMENT_ME SDL_GL_UpdateRects
    66 
    67 // !!! IMPLEMENT_ME SDL_GetKeyName
    68 // !!! IMPLEMENT_ME SDL_GetKeyState
    69 // !!! IMPLEMENT_ME SDL_GetModState
    70 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    71 
    72 // !!! IMPLEMENT_ME SDL_GetVideoSurface
    73 // !!! IMPLEMENT_ME SDL_GetWMInfo
    74 
    75 // !!! IMPLEMENT_ME SDL_LockSurface
    76 // !!! IMPLEMENT_ME SDL_LockYUVOverlay
    77 // !!! IMPLEMENT_ME SDL_LowerBlit
    78 
    79 // !!! IMPLEMENT_ME SDL_SetAlpha
    80 // !!! IMPLEMENT_ME SDL_SetColorKey
    81 // !!! IMPLEMENT_ME SDL_SetColors
    82 
    83 // !!! IMPLEMENT_ME SDL_SetModState
    84 // !!! IMPLEMENT_ME SDL_SetPalette
    85 // !!! IMPLEMENT_ME SDL_SetVideoMode
    86 // !!! IMPLEMENT_ME SDL_SoftStretch
    87 // !!! IMPLEMENT_ME SDL_UnlockSurface
    88 // !!! IMPLEMENT_ME SDL_UnlockYUVOverlay
    89 // !!! IMPLEMENT_ME SDL_UpdateRects
    90 // !!! IMPLEMENT_ME SDL_UpperBlit
    91 
    92 // !!! FIXME: should SDL_VideoInit really be a passthrough?
    93 // !!! FIXME: should SDL_VideoQuit really be a passthrough?
    94 
    95 // !!! IMPLEMENT_ME SDL_WM_SetIcon
    96 // !!! IMPLEMENT_ME SDL_WM_ToggleFullScreen
    97 
    98 // !!! IMPLEMENT_ME X11_KeyToUnicode
    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     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   723     SETFLAG(TIMER);
   724     SETFLAG(AUDIO);
   725     SETFLAG(VIDEO);
   726     SETFLAG(JOYSTICK);
   727     SETFLAG(NOPARACHUTE);
   728     #undef SETFLAG
   729 
   730     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   731     if (sdl12flags & SDL12_INIT_CDROM)
   732         CDRomInit = 1;
   733 
   734     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   735 
   736     rc = SDL20_Init(sdl20flags);
   737     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO)) {
   738         if (Init12Video() == -1) {
   739             FIXME("should we deinit other subsystems?");
   740             return -1;
   741         }
   742     }
   743 
   744     return rc;
   745 }
   746 
   747 DECLSPEC int SDLCALL
   748 SDL_Init(Uint32 sdl12flags)
   749 {
   750     FIXME("what was different in 1.2?");
   751     return SDL_InitSubSystem(sdl12flags);   /* there's no difference betwee Init and InitSubSystem in SDL2. */
   752 }
   753 
   754 
   755 static void
   756 InitFlags12To20(const Uint32 flags12, Uint32 *_flags20, Uint32 *_extraflags)
   757 {
   758     Uint32 flags20 = 0;
   759     Uint32 extraflags = 0;
   760 
   761     #define SETFLAG(flag) if (flags12 & SDL12_INIT_##flag) flags20 |= SDL_INIT_##flag
   762     SETFLAG(TIMER);
   763     SETFLAG(AUDIO);
   764     SETFLAG(VIDEO);
   765     SETFLAG(JOYSTICK);
   766     SETFLAG(NOPARACHUTE);
   767     #undef SETFLAG
   768 
   769     if ((flags12 & SDL12_INIT_CDROM) && (CDRomInit)) {
   770         extraflags |= SDL12_INIT_CDROM;
   771     }
   772 
   773     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   774 
   775     *_flags20 = flags20;
   776     *_extraflags = extraflags;
   777 }
   778 
   779 static Uint32
   780 InitFlags20to12(const Uint32 flags20)
   781 {
   782     Uint32 flags12 = 0;
   783 
   784     #define SETFLAG(flag) if (flags20 & SDL_INIT_##flag) flags12 |= SDL12_INIT_##flag
   785     SETFLAG(TIMER);
   786     SETFLAG(AUDIO);
   787     SETFLAG(VIDEO);
   788     SETFLAG(JOYSTICK);
   789     SETFLAG(NOPARACHUTE);
   790     #undef SETFLAG
   791 
   792     return flags12;
   793 }
   794 
   795 
   796 DECLSPEC Uint32 SDLCALL
   797 SDL_WasInit(Uint32 sdl12flags)
   798 {
   799     Uint32 sdl20flags, extraflags;
   800     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
   801 
   802     return InitFlags20to12(SDL20_WasInit(sdl20flags)) | extraflags;
   803 }
   804 
   805 static void
   806 Quit12Video(void)
   807 {
   808     int i;
   809 
   810     for (i = 0; i < VideoModesCount; i++) {
   811         SDL20_free(VideoModes[i].modeslist);
   812         SDL20_free(VideoModes[i].modes);
   813     }
   814     SDL20_free(VideoModes);
   815 
   816     SDL20_FreeFormat(VideoInfo12.vfmt);
   817     SDL20_zero(VideoInfo12);
   818 
   819     EventFilter12 = NULL;
   820     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   821     CurrentCursor12 = NULL;
   822     VideoModes = NULL;
   823     VideoModesCount = 0;
   824 }
   825 
   826 DECLSPEC void SDLCALL
   827 SDL_QuitSubSystem(Uint32 sdl12flags)
   828 {
   829     Uint32 sdl20flags, extraflags;
   830     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
   831 
   832     if (extraflags & SDL12_INIT_CDROM) {
   833         CDRomInit = 0;
   834     }
   835 
   836     FIXME("reset a bunch of other global variables too.");
   837     if (sdl12flags & SDL12_INIT_VIDEO) {
   838         Quit12Video();
   839     }
   840 
   841     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   842     SDL20_QuitSubSystem(sdl20flags);
   843 
   844     if ((SDL20_WasInit(0) == 0) && (!CDRomInit)) {
   845         SDL20_Quit();
   846         UnloadSDL20();
   847     }
   848 }
   849 
   850 DECLSPEC void SDLCALL
   851 SDL_Quit(void)
   852 {
   853     SDL_QuitSubSystem(SDL_WasInit(0) | SDL12_INIT_CDROM);
   854 }
   855 
   856 DECLSPEC void SDLCALL
   857 SDL_SetError(const char *fmt, ...)
   858 {
   859     char ch;
   860     char *str = NULL;
   861     size_t len = 0;
   862     va_list ap;
   863     va_start(ap, fmt);
   864     len = SDL20_vsnprintf(&ch, 1, fmt, ap);
   865     va_end(ap);
   866 
   867     str = (char *) SDL20_malloc(len + 1);
   868     if (!str)
   869         SDL20_OutOfMemory();
   870     else
   871     {
   872         va_start(ap, fmt);
   873         SDL20_vsnprintf(str, len + 1, fmt, ap);
   874         va_end(ap);
   875         SDL20_SetError("%s", str);
   876         SDL20_free(str);
   877     }
   878 }
   879 
   880 DECLSPEC const char * SDLCALL
   881 SDL_GetError(void)
   882 {
   883     if (SDL20_GetError == NULL)
   884     {
   885         static const char noload_errstr[] = "The SDL 2.0 library that the 1.2 compatibility layer needs isn't loaded";
   886         return noload_errstr;
   887     }
   888     return SDL20_GetError();
   889 }
   890 
   891 
   892 static const char *
   893 GetDriverName(const char *name, char *namebuf, int maxlen)
   894 {
   895     if (name) {
   896         if (namebuf) {
   897             SDL20_strlcpy(namebuf, name, maxlen);
   898             return namebuf;
   899         } else {
   900             return name;
   901         }
   902     }
   903     return NULL;
   904 }
   905 
   906 DECLSPEC const char * SDLCALL
   907 SDL_AudioDriverName(char *namebuf, int maxlen)
   908 {
   909     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   910 }
   911 
   912 DECLSPEC const char * SDLCALL
   913 SDL_VideoDriverName(char *namebuf, int maxlen)
   914 {
   915     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   916 }
   917 
   918 DECLSPEC int SDLCALL
   919 SDL_PollEvent(SDL12_Event *event12)
   920 {
   921     EventQueueType *next;
   922 
   923     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   924 
   925     if (EventQueueHead == NULL)
   926         return 0;  /* no events at the moment. */
   927 
   928     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   929     next = EventQueueHead->next;
   930     EventQueueHead->next = EventQueueAvailable;
   931     EventQueueAvailable = EventQueueHead;
   932     EventQueueHead = next;
   933     return 1;
   934 }
   935 
   936 DECLSPEC int SDLCALL
   937 SDL_PushEvent(SDL12_Event *event12)
   938 {
   939     EventQueueType *item = EventQueueAvailable;
   940     if (item == NULL)
   941         return -1;  /* no space available at the moment. */
   942 
   943     EventQueueAvailable = item->next;
   944     if (EventQueueTail)
   945         EventQueueTail->next = item;
   946     else
   947         EventQueueHead = EventQueueTail = item;
   948     item->next = NULL;
   949 
   950     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   951     return 0;
   952 }
   953 
   954 DECLSPEC int SDLCALL
   955 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   956 {
   957     if (action == SDL_ADDEVENT)
   958     {
   959         int i;
   960         for (i = 0; i < numevents; i++)
   961         {
   962             if (SDL_PushEvent(&events12[i]) == -1)
   963                 break;  /* out of space for more events. */
   964         }
   965         return i;
   966     }
   967     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   968     {
   969         const SDL_bool isGet = (action == SDL_GETEVENT);
   970         EventQueueType *prev = NULL;
   971         EventQueueType *item = EventQueueHead;
   972         EventQueueType *next = NULL;
   973         int chosen = 0;
   974         while (chosen < numevents)
   975         {
   976             EventQueueType *nextPrev = item;
   977             if (!item)
   978                 break;  /* no more events at the moment. */
   979 
   980             next = item->next;  /* copy, since we might overwrite item->next */
   981 
   982             if (mask & (1<<item->event12.type))
   983             {
   984                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   985                 if (isGet)  /* remove from list? */
   986                 {
   987                     if (prev != NULL)
   988                         prev->next = next;
   989                     if (item == EventQueueHead)
   990                         EventQueueHead = next;
   991                     if (item == EventQueueTail)
   992                         EventQueueTail = prev;
   993 
   994                     /* put it back in the free pool. */
   995                     item->next = EventQueueAvailable;
   996                     EventQueueAvailable = item;
   997                     nextPrev = prev;  /* previous item doesn't change. */
   998                 }
   999             }
  1000 
  1001             item = next;
  1002             prev = nextPrev;
  1003         }
  1004         return chosen;
  1005     }
  1006 
  1007     return 0;
  1008 }
  1009 
  1010 DECLSPEC int SDLCALL
  1011 SDL_WaitEvent(SDL12_Event *event12)
  1012 {
  1013     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1014     while (!SDL_PollEvent(event12))
  1015         SDL20_Delay(10);
  1016     return 1;
  1017 }
  1018 
  1019 static SDL_bool
  1020 PushEventIfNotFiltered(SDL12_Event *event12)
  1021 {
  1022     if (event12->type != SDL12_NOEVENT)
  1023     {
  1024         if (EventStates[event12->type] != SDL_IGNORE)
  1025         {
  1026             if ((!EventFilter12) || (EventFilter12(event12)))
  1027                 return (SDL_PushEvent(event12) == 0);
  1028         }
  1029     }
  1030     return SDL_FALSE;
  1031 }
  1032 
  1033 DECLSPEC Uint8 SDLCALL
  1034 SDL_EventState(Uint8 type, int state)
  1035 {
  1036     /* the values of "state" match between 1.2 and 2.0 */
  1037     const Uint8 retval = EventStates[type];
  1038     SDL12_Event e;
  1039 
  1040     if (state != SDL_QUERY)
  1041         EventStates[type] = state;
  1042     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1043         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1044 
  1045     return retval;
  1046 }
  1047 
  1048 DECLSPEC Uint8 SDLCALL
  1049 SDL_GetMouseState(int *x, int *y)
  1050 {
  1051     const Uint32 state20 = SDL20_GetMouseState(x, y);
  1052     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1053 
  1054     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1055     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  1056         retval |= (1<<5);
  1057     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  1058         retval |= (1<<6);
  1059 
  1060     return retval;
  1061 }
  1062 
  1063 static int
  1064 EventFilter20to12(void *data, SDL_Event *event20)
  1065 {
  1066     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1067     SDL12_Event event12;
  1068     int x, y;
  1069 
  1070     SDL_assert(data == NULL);  /* currently unused. */
  1071 
  1072     SDL20_zero(event12);
  1073 
  1074     switch (event20->type)
  1075     {
  1076         case SDL_QUIT:
  1077             event12.type = SDL12_QUIT;
  1078             break;
  1079 
  1080         case SDL_WINDOWEVENT:
  1081             switch (event20->window.event)
  1082             {
  1083                 case SDL_WINDOWEVENT_CLOSE:
  1084                     event12.type = SDL12_QUIT;
  1085                     break;
  1086 
  1087                 case SDL_WINDOWEVENT_SHOWN:
  1088                 case SDL_WINDOWEVENT_EXPOSED:
  1089                     event12.type = SDL12_VIDEOEXPOSE;
  1090                     break;
  1091 
  1092                 case SDL_WINDOWEVENT_RESIZED:
  1093                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1094                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1095                     event12.type = SDL12_VIDEORESIZE;
  1096                     event12.resize.w = event20->window.data1;
  1097                     event12.resize.h = event20->window.data2;
  1098                     break;
  1099 
  1100                 case SDL_WINDOWEVENT_MINIMIZED:
  1101                     event12.type = SDL12_ACTIVEEVENT;
  1102                     event12.active.gain = 0;
  1103                     event12.active.state = SDL12_APPACTIVE;
  1104                     break;
  1105 
  1106                 case SDL_WINDOWEVENT_RESTORED:
  1107                     event12.type = SDL12_ACTIVEEVENT;
  1108                     event12.active.gain = 1;
  1109                     event12.active.state = SDL12_APPACTIVE;
  1110                     break;
  1111 
  1112                 case SDL_WINDOWEVENT_ENTER:
  1113                     event12.type = SDL12_ACTIVEEVENT;
  1114                     event12.active.gain = 1;
  1115                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1116                     break;
  1117 
  1118                 case SDL_WINDOWEVENT_LEAVE:
  1119                     event12.type = SDL12_ACTIVEEVENT;
  1120                     event12.active.gain = 0;
  1121                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1122                     break;
  1123 
  1124                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1125                     event12.type = SDL12_ACTIVEEVENT;
  1126                     event12.active.gain = 1;
  1127                     event12.active.state = SDL12_APPINPUTFOCUS;
  1128                     break;
  1129 
  1130                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1131                     event12.type = SDL12_ACTIVEEVENT;
  1132                     event12.active.gain = 0;
  1133                     event12.active.state = SDL12_APPINPUTFOCUS;
  1134                     break;
  1135             }
  1136             break;
  1137 
  1138         // !!! FIXME: this is sort of a mess to convert.
  1139         //case SDL_SYSWMEVENT:
  1140 
  1141         case SDL_KEYDOWN: FIXME("write me"); return 0;
  1142         case SDL_KEYUP: FIXME("write me"); return 0;
  1143 
  1144         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  1145         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  1146 
  1147         case SDL_MOUSEMOTION:
  1148         	event12.type = SDL12_MOUSEMOTION;
  1149             event12.motion.which = (Uint8) event20->motion.which;
  1150             event12.motion.state = event20->motion.state;
  1151             event12.motion.x = (Uint16) event20->motion.x;
  1152             event12.motion.y = (Uint16) event20->motion.y;
  1153             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1154             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1155             break;
  1156 
  1157         case SDL_MOUSEBUTTONDOWN:
  1158         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1159             event12.button.which = (Uint8) event20->button.which;
  1160             event12.button.button = event20->button.button;
  1161             event12.button.state = event20->button.state;
  1162             event12.button.x = (Uint16) event20->button.x;
  1163             event12.button.y = (Uint16) event20->button.y;
  1164             break;
  1165 
  1166         case SDL_MOUSEBUTTONUP:
  1167         	event12.type = SDL12_MOUSEBUTTONUP;
  1168             event12.button.which = (Uint8) event20->button.which;
  1169             event12.button.button = event20->button.button;
  1170             event12.button.state = event20->button.state;
  1171             event12.button.x = (Uint16) event20->button.x;
  1172             event12.button.y = (Uint16) event20->button.y;
  1173             break;
  1174 
  1175         case SDL_MOUSEWHEEL:
  1176             if (event20->wheel.y == 0)
  1177                 break;  /* don't support horizontal wheels in 1.2. */
  1178 
  1179             event12.type = SDL12_MOUSEBUTTONDOWN;
  1180             event12.button.which = (Uint8) event20->wheel.which;
  1181             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1182             event12.button.state = SDL_GetMouseState(&x, &y);
  1183             event12.button.x = (Uint16) x;
  1184             event12.button.y = (Uint16) y;
  1185             PushEventIfNotFiltered(&event12);
  1186 
  1187             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1188             break;
  1189 
  1190         case SDL_JOYAXISMOTION:
  1191             event12.type = SDL12_JOYAXISMOTION;
  1192             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1193             event12.jaxis.axis = event20->jaxis.axis;
  1194             event12.jaxis.value = event20->jaxis.value;
  1195             break;
  1196 
  1197         case SDL_JOYBALLMOTION:
  1198             event12.type = SDL12_JOYBALLMOTION;
  1199             event12.jball.which = (Uint8) event20->jball.which;
  1200             event12.jball.ball = event20->jball.ball;
  1201             event12.jball.xrel = event20->jball.xrel;
  1202             event12.jball.yrel = event20->jball.yrel;
  1203             break;
  1204 
  1205         case SDL_JOYHATMOTION:
  1206             event12.type = SDL12_JOYHATMOTION;
  1207             event12.jhat.which = (Uint8) event20->jhat.which;
  1208             event12.jhat.hat = event20->jhat.hat;
  1209             event12.jhat.value = event20->jhat.value;
  1210             break;
  1211 
  1212         case SDL_JOYBUTTONDOWN:
  1213             event12.type = SDL12_JOYBUTTONDOWN;
  1214             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1215             event12.jbutton.button = event20->jbutton.button;
  1216             event12.jbutton.state = event20->jbutton.state;
  1217             break;
  1218 
  1219         case SDL_JOYBUTTONUP:
  1220             event12.type = SDL12_JOYBUTTONUP;
  1221             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1222             event12.jbutton.button = event20->jbutton.button;
  1223             event12.jbutton.state = event20->jbutton.state;
  1224             break;
  1225 
  1226         //case SDL_JOYDEVICEADDED:
  1227         //case SDL_JOYDEVICEREMOVED:
  1228 	    //case SDL_CONTROLLERAXISMOTION:
  1229 	    //case SDL_CONTROLLERBUTTONDOWN:
  1230 	    //case SDL_CONTROLLERBUTTONUP:
  1231 	    //case SDL_CONTROLLERDEVICEADDED:
  1232 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1233 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1234         //case SDL_FINGERDOWN:
  1235         //case SDL_FINGERUP:
  1236         //case SDL_FINGERMOTION:
  1237         //case SDL_DOLLARGESTURE:
  1238         //case SDL_DOLLARRECORD:
  1239         //case SDL_MULTIGESTURE:
  1240         //case SDL_CLIPBOARDUPDATE:
  1241         //case SDL_DROPFILE:
  1242 
  1243         default:
  1244             return 0;  /* drop everything else. */
  1245     }
  1246 
  1247     PushEventIfNotFiltered(&event12);
  1248 
  1249     return 0;  /* always drop it from the 2.0 event queue. */
  1250 }
  1251 
  1252 DECLSPEC void SDLCALL
  1253 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1254 {
  1255     /* We always have a filter installed, but will call the app's too. */
  1256     EventFilter12 = filter12;
  1257 }
  1258 
  1259 DECLSPEC SDL12_EventFilter SDLCALL
  1260 SDL_GetEventFilter(void)
  1261 {
  1262     return EventFilter12;
  1263 }
  1264 
  1265 
  1266 static SDL12_Surface *
  1267 Surface20to12(SDL_Surface *surface20)
  1268 {
  1269     SDL12_Surface *surface12 = NULL;
  1270     SDL12_Palette *palette12 = NULL;
  1271     SDL12_PixelFormat *format12 = NULL;
  1272     Uint32 flags = 0;
  1273 
  1274     if (!surface20)
  1275         return NULL;
  1276 
  1277     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1278     if (!surface12)
  1279         goto failed;
  1280 
  1281     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1282     if (!palette12)
  1283         goto failed;
  1284 
  1285     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1286     if (!format12)
  1287         goto failed;
  1288 
  1289     SDL20_zerop(palette12);
  1290     palette12->ncolors = surface20->format->palette->ncolors;
  1291     palette12->colors = surface20->format->palette->colors;
  1292 
  1293     SDL20_zerop(format12);
  1294     format12->palette = palette12;
  1295     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1296     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1297     format12->Rloss = surface20->format->Rloss;
  1298     format12->Gloss = surface20->format->Gloss;
  1299     format12->Bloss = surface20->format->Bloss;
  1300     format12->Aloss = surface20->format->Aloss;
  1301     format12->Rshift = surface20->format->Rshift;
  1302     format12->Gshift = surface20->format->Gshift;
  1303     format12->Bshift = surface20->format->Bshift;
  1304     format12->Ashift = surface20->format->Ashift;
  1305     format12->Rmask = surface20->format->Rmask;
  1306     format12->Gmask = surface20->format->Gmask;
  1307     format12->Bmask = surface20->format->Bmask;
  1308     format12->Amask = surface20->format->Amask;
  1309     FIXME("format12->colorkey");
  1310     FIXME("format12->alpha");
  1311 
  1312     SDL20_zerop(surface12);
  1313     flags = surface20->flags;
  1314     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1315     MAPSURFACEFLAGS(PREALLOC);
  1316     MAPSURFACEFLAGS(RLEACCEL);
  1317     /*MAPSURFACEFLAGS(DONTFREE);*/
  1318     #undef MAPSURFACEFLAGS
  1319     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1320 
  1321     surface12->format = format12;
  1322     surface12->w = surface20->w;
  1323     surface12->h = surface20->h;
  1324     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  1325     surface12->pixels = surface20->pixels;
  1326     surface12->offset = 0;
  1327     surface12->surface20 = surface20;
  1328     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
  1329     surface12->refcount = surface20->refcount;
  1330 
  1331     return surface12;
  1332 
  1333 failed:
  1334     SDL20_free(surface12);
  1335     SDL20_free(palette12);
  1336     SDL20_free(format12);
  1337     return NULL;
  1338 }
  1339 
  1340 DECLSPEC SDL12_Surface * SDLCALL
  1341 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1342 {
  1343     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1344     SDL12_Surface *surface12 = Surface20to12(surface20);
  1345     if (!surface12) {
  1346         SDL20_FreeSurface(surface20);
  1347         return NULL;
  1348     }
  1349 
  1350     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1351     return surface12;
  1352 }
  1353 
  1354 DECLSPEC SDL12_Surface * SDLCALL
  1355 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1356 {
  1357     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1358     SDL12_Surface *surface12 = Surface20to12(surface20);
  1359     if (!surface12) {
  1360         SDL20_FreeSurface(surface20);
  1361         return NULL;
  1362     }
  1363 
  1364     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1365     return surface12;
  1366 }
  1367 
  1368 DECLSPEC void SDLCALL
  1369 SDL_FreeSurface(SDL12_Surface *surface12)
  1370 {
  1371     if (surface12) {
  1372         SDL20_FreeSurface(surface12->surface20);
  1373         if (surface12->format) {
  1374             SDL20_free(surface12->format->palette);
  1375             SDL20_free(surface12->format);
  1376         }
  1377         SDL20_free(surface12);
  1378     }
  1379 }
  1380 
  1381 DECLSPEC void SDLCALL
  1382 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1383 {
  1384     if (surface12 && rect)
  1385 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1386 }
  1387 
  1388 DECLSPEC SDL_bool SDLCALL
  1389 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1390 {
  1391     SDL_bool retval = SDL_FALSE;
  1392     if (surface12)
  1393     {
  1394         retval = SDL20_SetClipRect(surface12->surface20, rect);
  1395         SDL20_GetClipRect(surface12->surface20, &surface12->clip_rect);
  1396     }
  1397     return retval;
  1398 }
  1399 
  1400 DECLSPEC int SDLCALL
  1401 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1402 {
  1403     const SDL_Rect orig_dstrect = *dstrect;
  1404     const int retval = SDL20_FillRect(dst->surface20, &orig_dstrect, color);
  1405     if (retval != -1)
  1406     {
  1407         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1408             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1409     }
  1410     return retval;
  1411 }
  1412 
  1413 
  1414 static SDL_PixelFormat *
  1415 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1416 {
  1417     palette20->ncolors = format12->palette->ncolors;
  1418     palette20->colors = format12->palette->colors;
  1419     palette20->version = 1;
  1420     palette20->refcount = 1;
  1421     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1422     format20->palette = palette20;
  1423     format20->BitsPerPixel = format12->BitsPerPixel;
  1424     format20->BytesPerPixel = format12->BytesPerPixel;
  1425     format20->Rmask = format12->Rmask;
  1426     format20->Gmask = format12->Gmask;
  1427     format20->Bmask = format12->Bmask;
  1428     format20->Amask = format12->Amask;
  1429     format20->Rloss = format12->Rloss;
  1430     format20->Gloss = format12->Gloss;
  1431     format20->Bloss = format12->Bloss;
  1432     format20->Aloss = format12->Aloss;
  1433     format20->Rshift = format12->Rshift;
  1434     format20->Gshift = format12->Gshift;
  1435     format20->Bshift = format12->Bshift;
  1436     format20->Ashift = format12->Ashift;
  1437     format20->refcount = 1;
  1438     format20->next = NULL;
  1439     return format20;
  1440 }
  1441 
  1442 DECLSPEC Uint32 SDLCALL
  1443 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1444 {
  1445     /* This is probably way slower than apps expect. */
  1446     SDL_PixelFormat format20;
  1447     SDL_Palette palette20;
  1448     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1449 }
  1450 
  1451 DECLSPEC Uint32 SDLCALL
  1452 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1453 {
  1454     /* This is probably way slower than apps expect. */
  1455     SDL_PixelFormat format20;
  1456     SDL_Palette palette20;
  1457     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1458 }
  1459 
  1460 DECLSPEC void SDLCALL
  1461 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1462 {
  1463     /* This is probably way slower than apps expect. */
  1464     SDL_PixelFormat format20;
  1465     SDL_Palette palette20;
  1466     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1467 }
  1468 
  1469 DECLSPEC void SDLCALL
  1470 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1471 {
  1472     /* This is probably way slower than apps expect. */
  1473     SDL_PixelFormat format20;
  1474     SDL_Palette palette20;
  1475     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1476 }
  1477 
  1478 DECLSPEC const SDL12_VideoInfo * SDLCALL
  1479 SDL_GetVideoInfo(void)
  1480 {
  1481     SDL_DisplayMode mode;
  1482 
  1483     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  1484 
  1485     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1486         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  1487         VideoInfo12.current_w = mode.w;
  1488         VideoInfo12.current_h = mode.h;
  1489         FIXME("vidinfo details commented out");
  1490         //VideoInfo12.wm_available = 1;
  1491         //VideoInfo12.video_mem = 1024 * 256;
  1492     }
  1493     return &VideoInfo12;
  1494 }
  1495 
  1496 DECLSPEC int SDLCALL
  1497 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1498 {
  1499     int i, nummodes, actual_bpp = 0;
  1500 
  1501     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1502         return 0;
  1503     }
  1504 
  1505     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1506         SDL_DisplayMode mode;
  1507         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1508         return SDL_BITSPERPIXEL(mode.format);
  1509     }
  1510 
  1511     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1512     for (i = 0; i < nummodes; ++i) {
  1513         SDL_DisplayMode mode;
  1514         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1515         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1516             if (!mode.format) {
  1517                 return bpp;
  1518             }
  1519             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1520                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1521             }
  1522         }
  1523     }
  1524     return actual_bpp;
  1525 }
  1526 
  1527 DECLSPEC SDL_Rect ** SDLCALL
  1528 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  1529 {
  1530     Uint32 fmt;
  1531     int i;
  1532 
  1533     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1534         return NULL;
  1535     }
  1536 
  1537     if ((!format12) && (!VideoInfo12.vfmt)) {
  1538         SDL20_SetError("No pixel format specified");
  1539         return NULL;
  1540     }
  1541 
  1542     if (!(flags & SDL12_FULLSCREEN)) {
  1543         return (SDL_Rect **) (-1);  /* any resolution is fine. */
  1544     }
  1545 
  1546     if (format12) {
  1547         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1548     } else {
  1549         fmt = VideoInfo12.vfmt->format;
  1550     }
  1551 
  1552     for (i = 0; i < VideoModesCount; i++) {
  1553         VideoModeList *modes = &VideoModes[i];
  1554         if (modes->format == fmt) {
  1555             return modes->modes;
  1556         }
  1557     }
  1558 
  1559     SDL20_SetError("No modes support requested pixel format");
  1560     return NULL;
  1561 }
  1562 
  1563 DECLSPEC void SDLCALL
  1564 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1565 {
  1566     if (cursor12) {
  1567         if (cursor12->wm_cursor)
  1568             SDL20_FreeCursor(cursor12->wm_cursor);
  1569         SDL20_free(cursor12->data);
  1570         SDL20_free(cursor12->mask);
  1571         SDL20_free(cursor12);
  1572     }
  1573 }
  1574 
  1575 DECLSPEC SDL12_Cursor * SDLCALL
  1576 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1577 {
  1578     const size_t datasize = h * (w / 8);
  1579     SDL_Cursor *cursor20 = NULL;
  1580     SDL12_Cursor *retval = NULL;
  1581 
  1582     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1583     if (!retval)
  1584         goto outofmem;
  1585 
  1586     SDL20_zerop(retval);
  1587 
  1588     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1589     if (!retval->data)
  1590         goto outofmem;
  1591 
  1592     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1593     if (!retval->mask)
  1594         goto outofmem;
  1595 
  1596     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1597     if (!cursor20)
  1598         goto failed;
  1599 
  1600     retval->area.w = w;
  1601     retval->area.h = h;
  1602     retval->hot_x = hot_x;
  1603     retval->hot_y = hot_y;
  1604     retval->wm_cursor = cursor20;
  1605     /* we always leave retval->save as null pointers. */
  1606 
  1607     SDL20_memcpy(retval->data, data, datasize);
  1608     SDL20_memcpy(retval->mask, mask, datasize);
  1609 
  1610     return retval;
  1611 
  1612 outofmem:
  1613     SDL20_OutOfMemory();
  1614 
  1615 failed:
  1616     SDL_FreeCursor(retval);
  1617     return NULL;
  1618 }
  1619 
  1620 DECLSPEC void SDLCALL
  1621 SDL_SetCursor(SDL12_Cursor *cursor)
  1622 {
  1623     CurrentCursor12 = cursor;
  1624     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1625 }
  1626 
  1627 DECLSPEC SDL12_Cursor * SDLCALL
  1628 SDL_GetCursor(void)
  1629 {
  1630     return CurrentCursor12;
  1631 }
  1632 
  1633 static void
  1634 GetEnvironmentWindowPosition(int *x, int *y)
  1635 {
  1636     int display = VideoDisplayIndex;
  1637     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  1638     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  1639     if (window) {
  1640         if (SDL20_strcmp(window, "center") == 0) {
  1641             center = window;
  1642         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  1643             return;
  1644         }
  1645     }
  1646 
  1647     if (center) {
  1648         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1649         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1650     }
  1651 }
  1652 
  1653 static void
  1654 SetupScreenSaver(const int flags12)
  1655 {
  1656     const char *env;
  1657     SDL_bool allow_screensaver;
  1658 
  1659     /* Allow environment override of screensaver disable */
  1660     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1661     if (env) {
  1662         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1663     } else if (flags12 & SDL12_FULLSCREEN) {
  1664         allow_screensaver = SDL_FALSE;
  1665     } else {
  1666         allow_screensaver = SDL_TRUE;
  1667     }
  1668     if (allow_screensaver) {
  1669         SDL20_EnableScreenSaver();
  1670     } else {
  1671         SDL20_DisableScreenSaver();
  1672     }
  1673 }
  1674 
  1675 
  1676 static SDL12_Surface *
  1677 EndVidModeCreate(void)
  1678 {
  1679     if (VideoTexture20) {
  1680         SDL20_DestroyTexture(VideoTexture20);
  1681         VideoTexture20 = NULL;
  1682     }
  1683     if (VideoRenderer20) {
  1684         SDL20_DestroyRenderer(VideoRenderer20);
  1685         VideoRenderer20 = NULL;
  1686     }
  1687     if (VideoGLContext20) {
  1688         SDL20_GL_MakeCurrent(NULL, NULL);
  1689         SDL20_GL_DeleteContext(VideoGLContext20);
  1690         VideoGLContext20 = NULL;
  1691     }
  1692     if (VideoWindow20) {
  1693         SDL20_DestroyWindow(VideoWindow20);
  1694         VideoWindow20 = NULL;
  1695     }
  1696     if (VideoSurface12) {
  1697         SDL20_free(VideoSurface12->pixels);
  1698         VideoSurface12->pixels = NULL;
  1699         SDL_FreeSurface(VideoSurface12);
  1700         VideoSurface12 = NULL;
  1701     }
  1702     if (VideoConvertSurface20) {
  1703         SDL20_FreeSurface(VideoConvertSurface20);
  1704         VideoConvertSurface20 = NULL;
  1705     }
  1706     return NULL;
  1707 }
  1708 
  1709 
  1710 static SDL12_Surface *
  1711 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  1712 {
  1713     Uint32 rmask, gmask, bmask, amask;
  1714     int bpp;
  1715     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  1716         return NULL;
  1717     }
  1718     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  1719 }
  1720 
  1721 static SDL_Surface *
  1722 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  1723 {
  1724     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  1725     if (surface20) {
  1726         surface20->flags |= SDL_PREALLOC;
  1727         surface20->pixels = NULL;
  1728         surface20->w = width;
  1729         surface20->h = height;
  1730         surface20->pitch = 0;
  1731         SDL20_SetClipRect(surface20, NULL);
  1732     }
  1733     return surface20;
  1734 }
  1735 
  1736 
  1737 DECLSPEC SDL12_Surface * SDLCALL
  1738 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1739 {
  1740     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  1741     SDL_DisplayMode dmode;
  1742     Uint32 fullscreen_flags20 = 0;
  1743     Uint32 appfmt;
  1744 
  1745     /* SDL_SetVideoMode() implicitly inits if necessary. */
  1746     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  1747         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  1748             return NULL;
  1749         }
  1750     }
  1751 
  1752     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  1753         FIXME("No OPENGLBLIT support at the moment");
  1754         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  1755         return NULL;
  1756     }
  1757 
  1758     FIXME("handle SDL_ANYFORMAT");
  1759 
  1760     if ((width < 0) || (height < 0)) {
  1761         SDL20_SetError("Invalid width or height");
  1762         return NULL;
  1763     }
  1764 
  1765     FIXME("There's an environment variable to choose a display");
  1766     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  1767         return NULL;
  1768     }
  1769 
  1770     if (width == 0) {
  1771         width = dmode.w;
  1772     }
  1773 
  1774     if (height == 0) {
  1775         height = dmode.h;
  1776     }
  1777 
  1778     if (bpp == 0) {
  1779         bpp = SDL_BITSPERPIXEL(dmode.format);
  1780     }
  1781 
  1782     switch (bpp) {
  1783         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  1784         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  1785         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  1786         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  1787         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  1788     }
  1789 
  1790     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  1791 
  1792     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  1793     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  1794 
  1795     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  1796         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  1797     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  1798         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  1799     } else if (VideoGLContext20) {
  1800         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  1801         SDL20_GL_MakeCurrent(NULL, NULL);
  1802         SDL20_GL_DeleteContext(VideoGLContext20);
  1803         VideoGLContext20 = NULL;
  1804     }
  1805 
  1806     if (flags12 & SDL12_FULLSCREEN) {
  1807         // OpenGL tries to force the real resolution requested, but for
  1808         //  software rendering, we're just going to push it off onto the
  1809         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  1810         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  1811         if (flags12 & SDL12_OPENGL) {
  1812             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  1813         } else {
  1814             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  1815         }
  1816     }
  1817 
  1818     if (!VideoWindow20) {  /* create it */
  1819         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  1820         Uint32 flags20 = fullscreen_flags20;
  1821         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  1822         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  1823         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  1824 
  1825         /* most platforms didn't check these environment variables, but the major
  1826            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  1827         GetEnvironmentWindowPosition(&x, &y);
  1828 
  1829         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  1830         if (!VideoWindow20) {
  1831             return EndVidModeCreate();
  1832         }
  1833     } else {  /* resize it */
  1834         SDL20_SetWindowSize(VideoWindow20, width, height);
  1835         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  1836         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  1837         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  1838     }
  1839 
  1840     if (VideoSurface12) {
  1841         SDL20_free(VideoSurface12->pixels);
  1842     } else {
  1843         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  1844         if (!VideoSurface12) {
  1845             return EndVidModeCreate();
  1846         }
  1847     }
  1848 
  1849     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  1850     VideoSurface12->flags |= SDL12_PREALLOC;
  1851     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  1852     VideoSurface12->w = VideoSurface12->surface20->w = width;
  1853     VideoSurface12->h = VideoSurface12->surface20->h = height;
  1854     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  1855     SDL_SetClipRect(VideoSurface12, NULL);
  1856 
  1857     if (flags12 & SDL12_OPENGL) {
  1858         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  1859         SDL_assert(!VideoRenderer20);
  1860         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  1861         if (!VideoGLContext20) {
  1862             return EndVidModeCreate();
  1863         }
  1864 
  1865         VideoSurface12->flags |= SDL12_OPENGL;
  1866     } else {
  1867         /* always use a renderer for non-OpenGL windows. */
  1868         SDL_RendererInfo rinfo;
  1869         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  1870         if (!VideoRenderer20) {
  1871             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  1872             if (!VideoRenderer20) {
  1873                 return EndVidModeCreate();
  1874             }
  1875         }
  1876 
  1877         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  1878         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  1879         SDL20_RenderClear(VideoRenderer20);
  1880         SDL20_RenderPresent(VideoRenderer20);
  1881         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  1882 
  1883         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  1884             return EndVidModeCreate();
  1885         }
  1886 
  1887         if (VideoTexture20) {
  1888             SDL20_DestroyTexture(VideoTexture20);
  1889         }
  1890 
  1891         if (VideoConvertSurface20) {
  1892             SDL20_FreeSurface(VideoConvertSurface20);
  1893             VideoConvertSurface20 = NULL;
  1894         }
  1895 
  1896         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  1897         if (!VideoTexture20) {
  1898             return EndVidModeCreate();
  1899         }
  1900 
  1901         if (rinfo.texture_formats[0] != appfmt) {
  1902             /* need to convert between app's format and texture format */
  1903             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  1904             if (!VideoConvertSurface20) {
  1905                 return EndVidModeCreate();
  1906             }
  1907         }
  1908 
  1909         VideoSurface12->flags &= ~SDL12_OPENGL;
  1910         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  1911         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  1912         if (!VideoSurface12->pixels) {
  1913             SDL20_OutOfMemory();
  1914             return EndVidModeCreate();
  1915         }
  1916     }
  1917 
  1918     FIXME("setup screen saver");
  1919 
  1920     return VideoSurface12;
  1921 }
  1922 
  1923 DECLSPEC SDL12_Surface * SDLCALL
  1924 SDL_GetVideoSurface(void)
  1925 {
  1926     return VideoSurface12;
  1927 }
  1928 
  1929 DECLSPEC int SDLCALL
  1930 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  1931 {
  1932     FIXME("write me");
  1933     return SDL20_Unsupported();
  1934 }
  1935 
  1936 DECLSPEC SDL12_Surface * SDLCALL
  1937 SDL_DisplayFormat(SDL12_Surface *surface12)
  1938 {
  1939     FIXME("write me");
  1940     SDL20_Unsupported();
  1941     return NULL;
  1942 }
  1943 
  1944 DECLSPEC SDL12_Surface * SDLCALL
  1945 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1946 {
  1947     FIXME("write me");
  1948     SDL20_Unsupported();
  1949     return NULL;
  1950 }
  1951 
  1952 DECLSPEC void SDLCALL
  1953 SDL_UpdateRects(SDL12_Surface * screen12, int numrects, SDL_Rect * rects)
  1954 {
  1955     FIXME("write me");
  1956     SDL20_Unsupported();
  1957 }
  1958 
  1959 DECLSPEC void SDLCALL
  1960 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1961 {
  1962     if (screen12) {
  1963         SDL_Rect rect;
  1964         rect.x = (int) x;
  1965         rect.y = (int) y;
  1966         rect.w = (int) (w ? w : screen12->w);
  1967         rect.h = (int) (h ? h : screen12->h);
  1968         SDL_UpdateRects(screen12, 1, &rect);
  1969     }
  1970 }
  1971 
  1972 DECLSPEC int SDLCALL
  1973 SDL_Flip(SDL12_Surface *screen12)
  1974 {
  1975     SDL_UpdateRect(screen12, 0, 0, 0, 0);
  1976     return 0;
  1977 }
  1978 
  1979 DECLSPEC void SDLCALL
  1980 SDL_WM_SetCaption(const char *title, const char *icon)
  1981 {
  1982     if (WindowTitle) {
  1983         SDL20_free(WindowTitle);
  1984     }
  1985     if (WindowIconTitle) {
  1986         SDL20_free(WindowIconTitle);
  1987     }
  1988     WindowTitle = title ? SDL_strdup(title) : NULL;
  1989     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  1990     if (VideoWindow20) {
  1991         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  1992     }
  1993 }
  1994 
  1995 DECLSPEC void SDLCALL
  1996 SDL_WM_GetCaption(const char **title, const char **icon)
  1997 {
  1998     if (title) {
  1999         *title = WindowTitle;
  2000     }
  2001     if (icon) {
  2002         *icon = WindowIconTitle;
  2003     }
  2004 }
  2005 
  2006 DECLSPEC void SDLCALL
  2007 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2008 {
  2009     FIXME("write me");
  2010     SDL20_Unsupported();
  2011 }
  2012 
  2013 DECLSPEC int SDLCALL
  2014 SDL_WM_IconifyWindow(void)
  2015 {
  2016     SDL20_MinimizeWindow(VideoWindow20);
  2017     return 0;
  2018 }
  2019 
  2020 DECLSPEC int SDLCALL
  2021 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  2022 {
  2023     FIXME("write me");
  2024     return SDL20_Unsupported();
  2025 }
  2026 
  2027 typedef enum
  2028 {
  2029     SDL12_GRAB_QUERY = -1,
  2030     SDL12_GRAB_OFF = 0,
  2031     SDL12_GRAB_ON = 1
  2032 } SDL12_GrabMode;
  2033 
  2034 DECLSPEC SDL12_GrabMode SDLCALL
  2035 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2036 {
  2037     if (mode != SDL12_GRAB_QUERY) {
  2038         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2039     }
  2040     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2041 }
  2042 
  2043 DECLSPEC void SDLCALL
  2044 SDL_WarpMouse(Uint16 x, Uint16 y)
  2045 {
  2046     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2047 }
  2048 
  2049 DECLSPEC Uint8 SDLCALL
  2050 SDL_GetAppState(void)
  2051 {
  2052     Uint8 state12 = 0;
  2053     Uint32 flags20 = 0;
  2054 
  2055     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2056     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2057         state12 |= SDL12_APPACTIVE;
  2058     }
  2059     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2060         state12 |= SDL12_APPINPUTFOCUS;
  2061     }
  2062     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2063         state12 |= SDL12_APPMOUSEFOCUS;
  2064     }
  2065     return state12;
  2066 }
  2067 
  2068 DECLSPEC int SDLCALL
  2069 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2070                int firstcolor, int ncolors)
  2071 {
  2072     FIXME("write me");
  2073     return SDL20_Unsupported();
  2074 }
  2075 
  2076 DECLSPEC int SDLCALL
  2077 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2078               int ncolors)
  2079 {
  2080     FIXME("write me");
  2081     return SDL20_Unsupported();
  2082 }
  2083 
  2084 DECLSPEC int SDLCALL
  2085 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2086 {
  2087     FIXME("write me");
  2088     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  2089     return SDL20_Unsupported();
  2090 }
  2091 
  2092 DECLSPEC SDL12_Overlay * SDLCALL
  2093 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2094 {
  2095     FIXME("write me");
  2096     SDL20_Unsupported();
  2097     return NULL;
  2098 }
  2099 
  2100 DECLSPEC int SDLCALL
  2101 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  2102 {
  2103     FIXME("write me");
  2104     return SDL20_Unsupported();
  2105 }
  2106 
  2107 DECLSPEC void SDLCALL
  2108 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  2109 {
  2110     FIXME("write me");
  2111 }
  2112 
  2113 DECLSPEC int SDLCALL
  2114 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL_Rect * dstrect)
  2115 {
  2116     FIXME("write me");
  2117     return SDL20_Unsupported();
  2118 }
  2119 
  2120 DECLSPEC void SDLCALL
  2121 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  2122 {
  2123     FIXME("write me");
  2124 }
  2125 
  2126 DECLSPEC int SDLCALL
  2127 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2128 {
  2129     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2130         return SDL20_SetError("Unknown GL attribute");
  2131 
  2132     /* swap control was moved out of this API, everything else lines up. */
  2133     if (attr == SDL12_GL_SWAP_CONTROL)
  2134     {
  2135         SwapInterval = value;
  2136         FIXME("Actually set swap interval somewhere");
  2137         return 0;
  2138     }
  2139 
  2140     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2141 }
  2142 
  2143 DECLSPEC int SDLCALL
  2144 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2145 {
  2146     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2147         return SDL20_SetError("Unknown GL attribute");
  2148 
  2149     /* swap control was moved out of this API, everything else lines up. */
  2150     if (attr == SDL12_GL_SWAP_CONTROL)
  2151     {
  2152         *value = SDL20_GL_GetSwapInterval();
  2153         return 0;
  2154     }
  2155 
  2156     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2157 }
  2158 
  2159 
  2160 DECLSPEC void SDLCALL
  2161 SDL_GL_SwapBuffers(void)
  2162 {
  2163     if (VideoWindow20)
  2164         SDL20_GL_SwapWindow(VideoWindow20);
  2165 }
  2166 
  2167 DECLSPEC int SDLCALL
  2168 SDL_SetGamma(float red, float green, float blue)
  2169 {
  2170     Uint16 red_ramp[256];
  2171     Uint16 green_ramp[256];
  2172     Uint16 blue_ramp[256];
  2173 
  2174     SDL20_CalculateGammaRamp(red, red_ramp);
  2175     if (green == red) {
  2176         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2177     } else {
  2178         SDL20_CalculateGammaRamp(green, green_ramp);
  2179     }
  2180     if (blue == red) {
  2181         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2182     } else if (blue == green) {
  2183         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2184     } else {
  2185         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2186     }
  2187     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2188 }
  2189 
  2190 DECLSPEC int SDLCALL
  2191 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2192 {
  2193     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2194 }
  2195 
  2196 DECLSPEC int SDLCALL
  2197 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2198 {
  2199     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2200 }
  2201 
  2202 DECLSPEC int SDLCALL
  2203 SDL_EnableKeyRepeat(int delay, int interval)
  2204 {
  2205     return 0;
  2206 }
  2207 
  2208 DECLSPEC void SDLCALL
  2209 SDL_GetKeyRepeat(int *delay, int *interval)
  2210 {
  2211     if (delay) {
  2212         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2213     }
  2214     if (interval) {
  2215         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2216     }
  2217 }
  2218 
  2219 DECLSPEC int SDLCALL
  2220 SDL_EnableUNICODE(int enable)
  2221 {
  2222     FIXME("write me");
  2223     return SDL20_Unsupported();
  2224 }
  2225 
  2226 static Uint32
  2227 SetTimerOld_Callback(Uint32 interval, void* param)
  2228 {
  2229     return ((SDL12_TimerCallback)param)(interval);
  2230 }
  2231 
  2232 DECLSPEC int SDLCALL
  2233 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2234 {
  2235     static SDL_TimerID compat_timer;
  2236 
  2237     if (compat_timer) {
  2238         SDL20_RemoveTimer(compat_timer);
  2239         compat_timer = 0;
  2240     }
  2241 
  2242     if (interval && callback) {
  2243         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2244         if (!compat_timer) {
  2245             return -1;
  2246         }
  2247     }
  2248     return 0;
  2249 }
  2250 
  2251 DECLSPEC int SDLCALL
  2252 SDL_putenv(const char *_var)
  2253 {
  2254     char *ptr = NULL;
  2255     char *var = SDL20_strdup(_var);
  2256     if (var == NULL) {
  2257         return -1;  /* we don't set errno. */
  2258     }
  2259 
  2260     ptr = SDL20_strchr(var, '=');
  2261     if (ptr == NULL) {
  2262         SDL20_free(var);
  2263         return -1;
  2264     }
  2265 
  2266     *ptr = '\0';  /* split the string into name and value. */
  2267     SDL20_setenv(var, ptr + 1, 1);
  2268     SDL20_free(var);
  2269     return 0;
  2270 }
  2271 
  2272 
  2273 
  2274 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2275 
  2276 typedef void *SDL12_CD;  /* close enough.  :) */
  2277 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2278 
  2279 DECLSPEC int SDLCALL
  2280 SDL_CDNumDrives(void)
  2281 {
  2282     FIXME("should return -1 without SDL_INIT_CDROM");
  2283     return 0;
  2284 }
  2285 
  2286 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2287 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2288 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2289 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2290 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2291 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2292 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2293 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2294 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2295 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  2296 
  2297 
  2298 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2299 DECLSPEC SDL_Thread * SDLCALL
  2300 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2301 {
  2302     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2303 }
  2304 #else
  2305 DECLSPEC SDL_Thread * SDLCALL
  2306 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2307 {
  2308     return SDL20_CreateThread(fn, NULL, data);
  2309 }
  2310 #endif
  2311 
  2312 DECLSPEC int SDLCALL
  2313 SDL_mutexP(SDL_mutex *mutex)
  2314 {
  2315     return SDL20_LockMutex(mutex);
  2316 }
  2317 
  2318 DECLSPEC int SDLCALL
  2319 SDL_mutexV(SDL_mutex *mutex)
  2320 {
  2321     return SDL20_UnlockMutex(mutex);
  2322 }
  2323 
  2324 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
  2325 {
  2326     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  2327     fprintf(stderr,
  2328         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  2329         "This program should be fixed. No thread was actually harmed.\n");
  2330 }
  2331 
  2332 /* This changed from an opaque pointer to an int in 2.0. */
  2333 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2334 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2335 
  2336 
  2337 DECLSPEC SDL12_TimerID SDLCALL
  2338 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2339 {
  2340     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2341 }
  2342 
  2343 DECLSPEC SDL_bool SDLCALL
  2344 SDL_RemoveTimer(SDL12_TimerID id)
  2345 {
  2346     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2347 }
  2348 
  2349 
  2350 typedef struct SDL12_RWops {
  2351     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2352     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2353     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2354     int (SDLCALL *close)(struct SDL12_RWops *context);
  2355     Uint32 type;
  2356     void *padding[8];
  2357     SDL_RWops *rwops20;
  2358 } SDL12_RWops;
  2359 
  2360 
  2361 DECLSPEC SDL12_RWops * SDLCALL
  2362 SDL_AllocRW(void)
  2363 {
  2364     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2365     if (!rwops)
  2366         SDL20_OutOfMemory();
  2367     return rwops;
  2368 }
  2369 
  2370 DECLSPEC void SDLCALL
  2371 SDL_FreeRW(SDL12_RWops *rwops12)
  2372 {
  2373     SDL20_free(rwops12);
  2374 }
  2375 
  2376 static int SDLCALL
  2377 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2378 {
  2379     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2380 }
  2381 
  2382 static int SDLCALL
  2383 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2384 {
  2385     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2386 }
  2387 
  2388 static int SDLCALL
  2389 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2390 {
  2391     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2392 }
  2393 
  2394 static int SDLCALL
  2395 RWops20to12_close(struct SDL12_RWops *rwops12)
  2396 {
  2397     int rc = 0;
  2398     if (rwops12)
  2399     {
  2400         rc = rwops12->rwops20->close(rwops12->rwops20);
  2401         if (rc == 0)
  2402             SDL_FreeRW(rwops12);
  2403     }
  2404     return rc;
  2405 }
  2406 
  2407 static SDL12_RWops *
  2408 RWops20to12(SDL_RWops *rwops20)
  2409 {
  2410     SDL12_RWops *rwops12;
  2411 
  2412     if (!rwops20)
  2413         return NULL;
  2414 
  2415     rwops12 = SDL_AllocRW();
  2416     if (!rwops12)
  2417         return NULL;
  2418 
  2419     SDL20_zerop(rwops12);
  2420     rwops12->type = rwops20->type;
  2421     rwops12->rwops20 = rwops20;
  2422     rwops12->seek = RWops20to12_seek;
  2423     rwops12->read = RWops20to12_read;
  2424     rwops12->write = RWops20to12_write;
  2425     rwops12->close = RWops20to12_close;
  2426 
  2427     return rwops12;
  2428 }
  2429 
  2430 DECLSPEC SDL12_RWops * SDLCALL
  2431 SDL_RWFromFile(const char *file, const char *mode)
  2432 {
  2433     return RWops20to12(SDL20_RWFromFile(file, mode));
  2434 }
  2435 
  2436 DECLSPEC SDL12_RWops * SDLCALL
  2437 SDL_RWFromFP(FILE *io, int autoclose)
  2438 {
  2439     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  2440 }
  2441 
  2442 DECLSPEC SDL12_RWops * SDLCALL
  2443 SDL_RWFromMem(void *mem, int size)
  2444 {
  2445     return RWops20to12(SDL20_RWFromMem(mem, size));
  2446 }
  2447 
  2448 DECLSPEC SDL12_RWops * SDLCALL
  2449 SDL_RWFromConstMem(const void *mem, int size)
  2450 {
  2451     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  2452 }
  2453 
  2454 #define READ_AND_BYTESWAP(endian, bits) \
  2455     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2456         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2457         return SDL_Swap##endian##bits(val); \
  2458     }
  2459 
  2460 READ_AND_BYTESWAP(LE,16)
  2461 READ_AND_BYTESWAP(BE,16)
  2462 READ_AND_BYTESWAP(LE,32)
  2463 READ_AND_BYTESWAP(BE,32)
  2464 READ_AND_BYTESWAP(LE,64)
  2465 READ_AND_BYTESWAP(BE,64)
  2466 #undef READ_AND_BYTESWAP
  2467 
  2468 #define BYTESWAP_AND_WRITE(endian, bits) \
  2469     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  2470         val = SDL_Swap##endian##bits(val); \
  2471         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2472     }
  2473 BYTESWAP_AND_WRITE(LE,16)
  2474 BYTESWAP_AND_WRITE(BE,16)
  2475 BYTESWAP_AND_WRITE(LE,32)
  2476 BYTESWAP_AND_WRITE(BE,32)
  2477 BYTESWAP_AND_WRITE(LE,64)
  2478 BYTESWAP_AND_WRITE(BE,64)
  2479 #undef BYTESWAP_AND_WRITE
  2480 
  2481 
  2482 static Sint64 SDLCALL
  2483 RWops12to20_size(struct SDL_RWops *rwops20)
  2484 {
  2485     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2486     int size = rwops20->hidden.unknown.data2;
  2487     int pos;
  2488 
  2489     if (size != -1)
  2490         return size;
  2491 
  2492     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2493     if (pos == -1)
  2494         return -1;
  2495 
  2496     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  2497     if (size == -1)
  2498         return -1;
  2499 
  2500     rwops12->seek(rwops12, pos, SEEK_SET);  /* !!! FIXME: and if this fails? */
  2501     rwops20->hidden.unknown.data2 = size;
  2502     return size;
  2503 }
  2504 
  2505 static Sint64 SDLCALL
  2506 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  2507 {
  2508     FIXME("fail if (offset) is too big");
  2509     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2510     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  2511 }
  2512 
  2513 static size_t SDLCALL
  2514 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  2515 {
  2516     FIXME("fail if (size) or (maxnum) is too big");
  2517     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2518     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  2519 }
  2520 
  2521 static size_t SDLCALL
  2522 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  2523 {
  2524     FIXME("fail if (size) or (maxnum) is too big");
  2525     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2526     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  2527 }
  2528 
  2529 static int SDLCALL
  2530 RWops12to20_close(struct SDL_RWops *rwops20)
  2531 {
  2532     int rc = 0;
  2533     if (rwops20)
  2534     {
  2535         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2536         rc = rwops12->close(rwops12);
  2537         if (rc == 0)
  2538             SDL20_FreeRW(rwops20);
  2539     }
  2540     return rc;
  2541 }
  2542 
  2543 static SDL_RWops *
  2544 RWops12to20(SDL12_RWops *rwops12)
  2545 {
  2546     SDL_RWops *rwops20;
  2547 
  2548     if (!rwops12)
  2549         return NULL;
  2550 
  2551     rwops20 = SDL20_AllocRW();
  2552     if (!rwops20)
  2553         return NULL;
  2554 
  2555     SDL20_zerop(rwops20);
  2556     rwops20->type = rwops12->type;
  2557     rwops20->hidden.unknown.data1 = rwops12;
  2558     rwops20->hidden.unknown.data2 = -1;  /* cached size of stream */
  2559     rwops20->size = RWops12to20_size;
  2560     rwops20->seek = RWops12to20_seek;
  2561     rwops20->read = RWops12to20_read;
  2562     rwops20->write = RWops12to20_write;
  2563     rwops20->close = RWops12to20_close;
  2564     return rwops20;
  2565 }
  2566 
  2567 DECLSPEC SDL12_Surface * SDLCALL
  2568 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  2569 {
  2570     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2571     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  2572     SDL12_Surface *surface12 = Surface20to12(surface20);
  2573     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2574         SDL20_FreeRW(rwops20);
  2575     if ((!surface12) && (surface20))
  2576         SDL20_FreeSurface(surface20);
  2577     return surface12;
  2578 }
  2579 
  2580 DECLSPEC int SDLCALL
  2581 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  2582 {
  2583     FIXME("wrap surface");
  2584     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2585     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  2586     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2587         SDL20_FreeRW(rwops20);
  2588     return retval;
  2589 }
  2590 
  2591 DECLSPEC SDL_AudioSpec * SDLCALL
  2592 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  2593                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  2594 {
  2595     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2596     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  2597     FIXME("deal with non-1.2 formats, like float32");
  2598     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2599         SDL20_FreeRW(rwops20);
  2600     return retval;
  2601 }
  2602 
  2603 /* vi: set ts=4 sw=4 expandtab: */