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