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