src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 03 Apr 2019 23:37:14 -0400
changeset 120 dc55edfe5d2f
parent 119 8d4f708adba1
permissions -rw-r--r--
Some minor (and not entirely correct) palette fixes.

Restores the missing 3D Realms logo on Duke Nukem 3D, etc.

Fixes Bugzilla #4556.
     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 #if 0
   101 #define FIXME(x) do {} while (0)
   102 #else
   103 #define FIXME(x) \
   104     do { \
   105         static SDL_bool seen = SDL_FALSE; \
   106         if (!seen) { \
   107             fprintf(stderr, "FIXME: %s (%s, %s:%d)\n", x, __FUNCTION__, __FILE__, __LINE__); \
   108             seen = SDL_TRUE; \
   109         } \
   110     } while (0)
   111 #endif
   112 
   113 #define SDL20_SYM(rc,fn,params,args,ret) \
   114     typedef rc (SDLCALL *SDL20_##fn##_t) params; \
   115     static SDL20_##fn##_t SDL20_##fn = NULL;
   116 #include "SDL20_syms.h"
   117 
   118 /* Things that _should_ be binary compatible pass right through... */
   119 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
   120     DECLSPEC rc SDLCALL SDL_##fn params { ret SDL20_##fn args; }
   121 #include "SDL20_syms.h"
   122 
   123 
   124 /* these are macros (etc) in the SDL headers, so make our own. */
   125 #define SDL20_OutOfMemory() SDL20_Error(SDL_ENOMEM)
   126 #define SDL20_Unsupported() SDL20_Error(SDL_UNSUPPORTED)
   127 #define SDL20_InvalidParamError(param) SDL20_SetError("Parameter '%s' is invalid", (param))
   128 #define SDL20_zero(x) SDL20_memset(&(x), 0, sizeof((x)))
   129 #define SDL20_zerop(x) SDL20_memset((x), 0, sizeof(*(x)))
   130 #define SDL_ReportAssertion SDL20_ReportAssertion
   131 
   132 #define SDL12_DEFAULT_REPEAT_DELAY 500
   133 #define SDL12_DEFAULT_REPEAT_INTERVAL 30
   134 
   135 #define SDL12_INIT_TIMER       0x00000001
   136 #define SDL12_INIT_AUDIO       0x00000010
   137 #define SDL12_INIT_VIDEO       0x00000020
   138 #define SDL12_INIT_CDROM       0x00000100
   139 #define SDL12_INIT_JOYSTICK    0x00000200
   140 #define SDL12_INIT_NOPARACHUTE 0x00100000
   141 #define SDL12_INIT_EVENTTHREAD 0x01000000
   142 #define SDL12_INIT_EVERYTHING  0x0000FFFF
   143 
   144 #define SDL12_LOGPAL 1
   145 #define SDL12_PHYSPAL 2
   146 
   147 // this will be in SDL 2.0.10, but here it is in case your headers are missing it.
   148 #ifndef SDL_SIMD_ALIGNED
   149 #define SDL_SIMD_ALIGNED    0x00000008
   150 #endif
   151 
   152 typedef struct SDL12_Rect
   153 {
   154     Sint16 x;
   155     Sint16 y;
   156     Uint16 w;
   157     Uint16 h;
   158 } SDL12_Rect;
   159 
   160 typedef struct SDL12_Palette
   161 {
   162     int       ncolors;
   163     SDL_Color *colors;
   164 } SDL12_Palette;
   165 
   166 typedef struct SDL12_PixelFormat
   167 {
   168     SDL12_Palette *palette;
   169     Uint8 BitsPerPixel;
   170     Uint8 BytesPerPixel;
   171     Uint8 Rloss;
   172     Uint8 Gloss;
   173     Uint8 Bloss;
   174     Uint8 Aloss;
   175     Uint8 Rshift;
   176     Uint8 Gshift;
   177     Uint8 Bshift;
   178     Uint8 Ashift;
   179     Uint32 Rmask;
   180     Uint32 Gmask;
   181     Uint32 Bmask;
   182     Uint32 Amask;
   183     Uint32 colorkey;
   184     Uint8 alpha;
   185 } SDL12_PixelFormat;
   186 
   187 typedef struct SDL12_Surface
   188 {
   189     Uint32 flags;
   190     SDL12_PixelFormat *format;
   191     int w;
   192     int h;
   193     Uint16 pitch;
   194     void *pixels;
   195     int offset;
   196     SDL_Surface *surface20; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here named "hwdata". */
   197     SDL12_Rect clip_rect;
   198     Uint32 unused1;
   199     Uint32 locked;
   200     void *blitmap;
   201     unsigned int format_version;
   202     int refcount;
   203 } SDL12_Surface;
   204 
   205 typedef struct SDL12_Overlay
   206 {
   207     Uint32 format;
   208     int w;
   209     int h;
   210     int planes;
   211     Uint16 *pitches;
   212     Uint8 **pixels;
   213     void *hwfuncs;
   214     void *hwdata;
   215     Uint32 hw_overlay :1;
   216     Uint32 UnusedBits :31;
   217 } SDL12_Overlay;
   218 
   219 typedef struct
   220 {
   221     Uint32 hw_available :1;
   222     Uint32 wm_available :1;
   223     Uint32 UnusedBits1  :6;
   224     Uint32 UnusedBits2  :1;
   225     Uint32 blit_hw      :1;
   226     Uint32 blit_hw_CC   :1;
   227     Uint32 blit_hw_A    :1;
   228     Uint32 blit_sw      :1;
   229     Uint32 blit_sw_CC   :1;
   230     Uint32 blit_sw_A    :1;
   231     Uint32 blit_fill    :1;
   232     Uint32 UnusedBits3  :16;
   233     Uint32 video_mem;
   234     SDL12_PixelFormat *vfmt;
   235     int current_w;
   236     int current_h;
   237 } SDL12_VideoInfo;
   238 
   239 
   240 #define SDL12_HWSURFACE 0x00000001
   241 #define SDL12_ASYNCBLIT 0x00000004
   242 #define SDL12_ANYFORMAT 0x10000000
   243 #define SDL12_HWPALETTE 0x20000000
   244 #define SDL12_DOUBLEBUF 0x40000000
   245 #define SDL12_FULLSCREEN 0x80000000
   246 #define SDL12_OPENGL 0x00000002
   247 #define SDL12_OPENGLBLIT 0x0000000A
   248 #define SDL12_RESIZABLE 0x00000010
   249 #define SDL12_NOFRAME 0x00000020
   250 #define SDL12_HWACCEL 0x00000100
   251 #define SDL12_SRCCOLORKEY 0x00001000
   252 #define SDL12_RLEACCELOK 0x00002000
   253 #define SDL12_RLEACCEL 0x00004000
   254 #define SDL12_SRCALPHA 0x00010000
   255 #define SDL12_PREALLOC 0x01000000
   256 
   257 typedef enum
   258 {
   259     SDLK12_UNKNOWN = 0,
   260     SDLK12_FIRST = 0,
   261     SDLK12_BACKSPACE = 8,
   262     SDLK12_TAB = 9,
   263     SDLK12_CLEAR = 12,
   264     SDLK12_RETURN = 13,
   265     SDLK12_PAUSE = 19,
   266     SDLK12_ESCAPE = 27,
   267     SDLK12_SPACE = 32,
   268     SDLK12_EXCLAIM = 33,
   269     SDLK12_QUOTEDBL = 34,
   270     SDLK12_HASH = 35,
   271     SDLK12_DOLLAR = 36,
   272     SDLK12_AMPERSAND = 38,
   273     SDLK12_QUOTE = 39,
   274     SDLK12_LEFTPAREN = 40,
   275     SDLK12_RIGHTPAREN = 41,
   276     SDLK12_ASTERISK = 42,
   277     SDLK12_PLUS = 43,
   278     SDLK12_COMMA = 44,
   279     SDLK12_MINUS = 45,
   280     SDLK12_PERIOD = 46,
   281     SDLK12_SLASH = 47,
   282     SDLK12_0 = 48,
   283     SDLK12_1 = 49,
   284     SDLK12_2 = 50,
   285     SDLK12_3 = 51,
   286     SDLK12_4 = 52,
   287     SDLK12_5 = 53,
   288     SDLK12_6 = 54,
   289     SDLK12_7 = 55,
   290     SDLK12_8 = 56,
   291     SDLK12_9 = 57,
   292     SDLK12_COLON = 58,
   293     SDLK12_SEMICOLON = 59,
   294     SDLK12_LESS = 60,
   295     SDLK12_EQUALS = 61,
   296     SDLK12_GREATER = 62,
   297     SDLK12_QUESTION = 63,
   298     SDLK12_AT = 64,
   299     SDLK12_LEFTBRACKET = 91,
   300     SDLK12_BACKSLASH = 92,
   301     SDLK12_RIGHTBRACKET = 93,
   302     SDLK12_CARET = 94,
   303     SDLK12_UNDERSCORE = 95,
   304     SDLK12_BACKQUOTE = 96,
   305     SDLK12_a = 97,
   306     SDLK12_b = 98,
   307     SDLK12_c = 99,
   308     SDLK12_d = 100,
   309     SDLK12_e = 101,
   310     SDLK12_f = 102,
   311     SDLK12_g = 103,
   312     SDLK12_h = 104,
   313     SDLK12_i = 105,
   314     SDLK12_j = 106,
   315     SDLK12_k = 107,
   316     SDLK12_l = 108,
   317     SDLK12_m = 109,
   318     SDLK12_n = 110,
   319     SDLK12_o = 111,
   320     SDLK12_p = 112,
   321     SDLK12_q = 113,
   322     SDLK12_r = 114,
   323     SDLK12_s = 115,
   324     SDLK12_t = 116,
   325     SDLK12_u = 117,
   326     SDLK12_v = 118,
   327     SDLK12_w = 119,
   328     SDLK12_x = 120,
   329     SDLK12_y = 121,
   330     SDLK12_z = 122,
   331     SDLK12_DELETE = 127,
   332     SDLK12_WORLD_0 = 160,
   333     SDLK12_WORLD_1 = 161,
   334     SDLK12_WORLD_2 = 162,
   335     SDLK12_WORLD_3 = 163,
   336     SDLK12_WORLD_4 = 164,
   337     SDLK12_WORLD_5 = 165,
   338     SDLK12_WORLD_6 = 166,
   339     SDLK12_WORLD_7 = 167,
   340     SDLK12_WORLD_8 = 168,
   341     SDLK12_WORLD_9 = 169,
   342     SDLK12_WORLD_10 = 170,
   343     SDLK12_WORLD_11 = 171,
   344     SDLK12_WORLD_12 = 172,
   345     SDLK12_WORLD_13 = 173,
   346     SDLK12_WORLD_14 = 174,
   347     SDLK12_WORLD_15 = 175,
   348     SDLK12_WORLD_16 = 176,
   349     SDLK12_WORLD_17 = 177,
   350     SDLK12_WORLD_18 = 178,
   351     SDLK12_WORLD_19 = 179,
   352     SDLK12_WORLD_20 = 180,
   353     SDLK12_WORLD_21 = 181,
   354     SDLK12_WORLD_22 = 182,
   355     SDLK12_WORLD_23 = 183,
   356     SDLK12_WORLD_24 = 184,
   357     SDLK12_WORLD_25 = 185,
   358     SDLK12_WORLD_26 = 186,
   359     SDLK12_WORLD_27 = 187,
   360     SDLK12_WORLD_28 = 188,
   361     SDLK12_WORLD_29 = 189,
   362     SDLK12_WORLD_30 = 190,
   363     SDLK12_WORLD_31 = 191,
   364     SDLK12_WORLD_32 = 192,
   365     SDLK12_WORLD_33 = 193,
   366     SDLK12_WORLD_34 = 194,
   367     SDLK12_WORLD_35 = 195,
   368     SDLK12_WORLD_36 = 196,
   369     SDLK12_WORLD_37 = 197,
   370     SDLK12_WORLD_38 = 198,
   371     SDLK12_WORLD_39 = 199,
   372     SDLK12_WORLD_40 = 200,
   373     SDLK12_WORLD_41 = 201,
   374     SDLK12_WORLD_42 = 202,
   375     SDLK12_WORLD_43 = 203,
   376     SDLK12_WORLD_44 = 204,
   377     SDLK12_WORLD_45 = 205,
   378     SDLK12_WORLD_46 = 206,
   379     SDLK12_WORLD_47 = 207,
   380     SDLK12_WORLD_48 = 208,
   381     SDLK12_WORLD_49 = 209,
   382     SDLK12_WORLD_50 = 210,
   383     SDLK12_WORLD_51 = 211,
   384     SDLK12_WORLD_52 = 212,
   385     SDLK12_WORLD_53 = 213,
   386     SDLK12_WORLD_54 = 214,
   387     SDLK12_WORLD_55 = 215,
   388     SDLK12_WORLD_56 = 216,
   389     SDLK12_WORLD_57 = 217,
   390     SDLK12_WORLD_58 = 218,
   391     SDLK12_WORLD_59 = 219,
   392     SDLK12_WORLD_60 = 220,
   393     SDLK12_WORLD_61 = 221,
   394     SDLK12_WORLD_62 = 222,
   395     SDLK12_WORLD_63 = 223,
   396     SDLK12_WORLD_64 = 224,
   397     SDLK12_WORLD_65 = 225,
   398     SDLK12_WORLD_66 = 226,
   399     SDLK12_WORLD_67 = 227,
   400     SDLK12_WORLD_68 = 228,
   401     SDLK12_WORLD_69 = 229,
   402     SDLK12_WORLD_70 = 230,
   403     SDLK12_WORLD_71 = 231,
   404     SDLK12_WORLD_72 = 232,
   405     SDLK12_WORLD_73 = 233,
   406     SDLK12_WORLD_74 = 234,
   407     SDLK12_WORLD_75 = 235,
   408     SDLK12_WORLD_76 = 236,
   409     SDLK12_WORLD_77 = 237,
   410     SDLK12_WORLD_78 = 238,
   411     SDLK12_WORLD_79 = 239,
   412     SDLK12_WORLD_80 = 240,
   413     SDLK12_WORLD_81 = 241,
   414     SDLK12_WORLD_82 = 242,
   415     SDLK12_WORLD_83 = 243,
   416     SDLK12_WORLD_84 = 244,
   417     SDLK12_WORLD_85 = 245,
   418     SDLK12_WORLD_86 = 246,
   419     SDLK12_WORLD_87 = 247,
   420     SDLK12_WORLD_88 = 248,
   421     SDLK12_WORLD_89 = 249,
   422     SDLK12_WORLD_90 = 250,
   423     SDLK12_WORLD_91 = 251,
   424     SDLK12_WORLD_92 = 252,
   425     SDLK12_WORLD_93 = 253,
   426     SDLK12_WORLD_94 = 254,
   427     SDLK12_WORLD_95 = 255,
   428     SDLK12_KP0 = 256,
   429     SDLK12_KP1 = 257,
   430     SDLK12_KP2 = 258,
   431     SDLK12_KP3 = 259,
   432     SDLK12_KP4 = 260,
   433     SDLK12_KP5 = 261,
   434     SDLK12_KP6 = 262,
   435     SDLK12_KP7 = 263,
   436     SDLK12_KP8 = 264,
   437     SDLK12_KP9 = 265,
   438     SDLK12_KP_PERIOD = 266,
   439     SDLK12_KP_DIVIDE = 267,
   440     SDLK12_KP_MULTIPLY = 268,
   441     SDLK12_KP_MINUS = 269,
   442     SDLK12_KP_PLUS = 270,
   443     SDLK12_KP_ENTER = 271,
   444     SDLK12_KP_EQUALS = 272,
   445     SDLK12_UP = 273,
   446     SDLK12_DOWN = 274,
   447     SDLK12_RIGHT = 275,
   448     SDLK12_LEFT = 276,
   449     SDLK12_INSERT = 277,
   450     SDLK12_HOME = 278,
   451     SDLK12_END = 279,
   452     SDLK12_PAGEUP = 280,
   453     SDLK12_PAGEDOWN = 281,
   454     SDLK12_F1 = 282,
   455     SDLK12_F2 = 283,
   456     SDLK12_F3 = 284,
   457     SDLK12_F4 = 285,
   458     SDLK12_F5 = 286,
   459     SDLK12_F6 = 287,
   460     SDLK12_F7 = 288,
   461     SDLK12_F8 = 289,
   462     SDLK12_F9 = 290,
   463     SDLK12_F10 = 291,
   464     SDLK12_F11 = 292,
   465     SDLK12_F12 = 293,
   466     SDLK12_F13 = 294,
   467     SDLK12_F14 = 295,
   468     SDLK12_F15 = 296,
   469     SDLK12_NUMLOCK = 300,
   470     SDLK12_CAPSLOCK = 301,
   471     SDLK12_SCROLLOCK = 302,
   472     SDLK12_RSHIFT = 303,
   473     SDLK12_LSHIFT = 304,
   474     SDLK12_RCTRL = 305,
   475     SDLK12_LCTRL = 306,
   476     SDLK12_RALT = 307,
   477     SDLK12_LALT = 308,
   478     SDLK12_RMETA = 309,
   479     SDLK12_LMETA = 310,
   480     SDLK12_LSUPER = 311,
   481     SDLK12_RSUPER = 312,
   482     SDLK12_MODE = 313,
   483     SDLK12_COMPOSE = 314,
   484     SDLK12_HELP = 315,
   485     SDLK12_PRINT = 316,
   486     SDLK12_SYSREQ = 317,
   487     SDLK12_BREAK = 318,
   488     SDLK12_MENU = 319,
   489     SDLK12_POWER = 320,
   490     SDLK12_EURO = 321,
   491     SDLK12_UNDO = 322,
   492     SDLK12_LAST
   493 } SDL12Key;
   494 
   495 typedef enum
   496 {
   497     KMOD12_NONE  = 0x0000,
   498     KMOD12_LSHIFT = 0x0001,
   499     KMOD12_RSHIFT = 0x0002,
   500     KMOD12_LCTRL = 0x0040,
   501     KMOD12_RCTRL = 0x0080,
   502     KMOD12_LALT = 0x0100,
   503     KMOD12_RALT = 0x0200,
   504     KMOD12_LMETA = 0x0400,
   505     KMOD12_RMETA = 0x0800,
   506     KMOD12_NUM = 0x1000,
   507     KMOD12_CAPS = 0x2000,
   508     KMOD12_MODE = 0x4000,
   509     KMOD12_RESERVED = 0x8000
   510 } SDL12Mod;
   511 
   512 typedef struct SDL12_keysym
   513 {
   514     Uint8 scancode;
   515     SDL12Key sym;
   516     SDL12Mod mod;
   517     Uint16 unicode;
   518 } SDL12_keysym;
   519 
   520 typedef enum
   521 {
   522     SDL12_NOEVENT = 0,
   523     SDL12_ACTIVEEVENT,
   524     SDL12_KEYDOWN,
   525     SDL12_KEYUP,
   526     SDL12_MOUSEMOTION,
   527     SDL12_MOUSEBUTTONDOWN,
   528     SDL12_MOUSEBUTTONUP,
   529     SDL12_JOYAXISMOTION,
   530     SDL12_JOYBALLMOTION,
   531     SDL12_JOYHATMOTION,
   532     SDL12_JOYBUTTONDOWN,
   533     SDL12_JOYBUTTONUP,
   534     SDL12_QUIT,
   535     SDL12_SYSWMEVENT,
   536     SDL12_EVENT_RESERVEDA,
   537     SDL12_EVENT_RESERVEDB,
   538     SDL12_VIDEORESIZE,
   539     SDL12_VIDEOEXPOSE,
   540     SDL12_USEREVENT = 24,
   541     SDL12_NUMEVENTS = 32
   542 } SDL12_EventType;
   543 
   544 
   545 #define SDL12_APPMOUSEFOCUS (1<<0)
   546 #define SDL12_APPINPUTFOCUS (1<<1)
   547 #define SDL12_APPACTIVE     (1<<2)
   548 
   549 typedef struct
   550 {
   551     Uint8 type;
   552     Uint8 gain;
   553     Uint8 state;
   554 } SDL12_ActiveEvent;
   555 
   556 typedef struct
   557 {
   558     Uint8 type;
   559     Uint8 which;
   560     Uint8 state;
   561     SDL12_keysym keysym;
   562 } SDL12_KeyboardEvent;
   563 
   564 typedef struct
   565 {
   566     Uint8 type;
   567     Uint8 which;
   568     Uint8 state;
   569     Uint16 x, y;
   570     Sint16 xrel;
   571     Sint16 yrel;
   572 } SDL12_MouseMotionEvent;
   573 
   574 typedef struct
   575 {
   576     Uint8 type;
   577     Uint8 which;
   578     Uint8 button;
   579     Uint8 state;
   580     Uint16 x, y;
   581 } SDL12_MouseButtonEvent;
   582 
   583 typedef struct
   584 {
   585     Uint8 type;
   586     Uint8 which;
   587     Uint8 axis;
   588     Sint16 value;
   589 } SDL12_JoyAxisEvent;
   590 
   591 typedef struct
   592 {
   593     Uint8 type;
   594     Uint8 which;
   595     Uint8 ball;
   596     Sint16 xrel;
   597     Sint16 yrel;
   598 } SDL12_JoyBallEvent;
   599 
   600 typedef struct
   601 {
   602     Uint8 type;
   603     Uint8 which;
   604     Uint8 hat;
   605     Uint8 value;
   606 } SDL12_JoyHatEvent;
   607 
   608 typedef struct
   609 {
   610     Uint8 type;
   611     Uint8 which;
   612     Uint8 button;
   613     Uint8 state;
   614 } SDL12_JoyButtonEvent;
   615 
   616 typedef struct
   617 {
   618     Uint8 type;
   619     int w;
   620     int h;
   621 } SDL12_ResizeEvent;
   622 
   623 typedef struct
   624 {
   625     Uint8 type;
   626 } SDL12_ExposeEvent;
   627 
   628 typedef struct
   629 {
   630     Uint8 type;
   631 } SDL12_QuitEvent;
   632 
   633 typedef struct
   634 {
   635     Uint8 type;
   636     int code;
   637     void *data1;
   638     void *data2;
   639 } SDL12_UserEvent;
   640 
   641 typedef struct
   642 {
   643     Uint8 type;
   644     void *msg;
   645 } SDL12_SysWMEvent;
   646 
   647 typedef union
   648 {
   649     Uint8 type;
   650     SDL12_ActiveEvent active;
   651     SDL12_KeyboardEvent key;
   652     SDL12_MouseMotionEvent motion;
   653     SDL12_MouseButtonEvent button;
   654     SDL12_JoyAxisEvent jaxis;
   655     SDL12_JoyBallEvent jball;
   656     SDL12_JoyHatEvent jhat;
   657     SDL12_JoyButtonEvent jbutton;
   658     SDL12_ResizeEvent resize;
   659     SDL12_ExposeEvent expose;
   660     SDL12_QuitEvent quit;
   661     SDL12_UserEvent user;
   662     SDL12_SysWMEvent syswm;
   663 } SDL12_Event;
   664 
   665 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
   666 static int EventFilter20to12(void *data, SDL_Event *event20);
   667 
   668 typedef Uint32 (SDLCALL *SDL12_TimerCallback)(Uint32 interval);
   669 typedef SDL_TimerCallback SDL12_NewTimerCallback;
   670 
   671 typedef struct
   672 {
   673     SDL12_Rect area;
   674     Sint16 hot_x;
   675     Sint16 hot_y;
   676     Uint8 *data;
   677     Uint8 *mask;
   678     Uint8 *save[2];
   679     SDL_Cursor *wm_cursor;  /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
   680 } SDL12_Cursor;
   681 
   682 typedef enum
   683 {
   684     SDL12_GL_RED_SIZE,
   685     SDL12_GL_GREEN_SIZE,
   686     SDL12_GL_BLUE_SIZE,
   687     SDL12_GL_ALPHA_SIZE,
   688     SDL12_GL_BUFFER_SIZE,
   689     SDL12_GL_DOUBLEBUFFER,
   690     SDL12_GL_DEPTH_SIZE,
   691     SDL12_GL_STENCIL_SIZE,
   692     SDL12_GL_ACCUM_RED_SIZE,
   693     SDL12_GL_ACCUM_GREEN_SIZE,
   694     SDL12_GL_ACCUM_BLUE_SIZE,
   695     SDL12_GL_ACCUM_ALPHA_SIZE,
   696     SDL12_GL_STEREO,
   697     SDL12_GL_MULTISAMPLEBUFFERS,
   698     SDL12_GL_MULTISAMPLESAMPLES,
   699     SDL12_GL_ACCELERATED_VISUAL,
   700     SDL12_GL_SWAP_CONTROL,
   701     SDL12_GL_MAX_ATTRIBUTE
   702 } SDL12_GLattr;
   703 
   704 
   705 typedef struct
   706 {
   707     Uint32 format;
   708     int nummodes;
   709     SDL12_Rect *modeslist12;
   710     SDL12_Rect **modes12;  /* ptrs to each item in modeslist, for SDL_ListModes() */
   711 } VideoModeList;
   712 
   713 typedef struct
   714 {
   715     int device_index;
   716     SDL_Joystick *joystick;
   717 } JoystickOpenedItem;
   718 
   719 // !!! FIXME: go through all of these.
   720 static VideoModeList *VideoModes = NULL;
   721 static int VideoModesCount = 0;  // this counts items in VideoModeList, not total video modes.
   722 static SDL12_VideoInfo VideoInfo12;
   723 static SDL12_Palette VideoInfoPalette12;
   724 static SDL12_PixelFormat VideoInfoVfmt12;
   725 static SDL_PixelFormat *VideoInfoVfmt20 = NULL;
   726 static SDL_bool VideoWindowGrabbed = SDL_FALSE;
   727 static SDL_bool VideoCursorHidden = SDL_FALSE;
   728 static SDL_Window *VideoWindow20 = NULL;
   729 static SDL_Renderer *VideoRenderer20 = NULL;
   730 static SDL_Texture *VideoTexture20 = NULL;
   731 static SDL12_Surface *VideoSurface12 = NULL;
   732 static Uint32 VideoSurfacePresentTicks = 0;
   733 static Uint32 VideoSurfaceLastPresentTicks = 0;
   734 static SDL_Surface *VideoConvertSurface20 = NULL;
   735 static SDL_GLContext *VideoGLContext20 = NULL;
   736 static char *WindowTitle = NULL;
   737 static char *WindowIconTitle = NULL;
   738 static SDL_Surface *VideoIcon20 = NULL;
   739 static int EnabledUnicode = 0;
   740 static int VideoDisplayIndex = 0;
   741 static int CDRomInit = 0;
   742 static SDL12_EventFilter EventFilter12 = NULL;
   743 static SDL12_Cursor *CurrentCursor12 = NULL;
   744 static Uint8 EventStates[SDL12_NUMEVENTS];
   745 static int SwapInterval = 0;
   746 static JoystickOpenedItem JoystickOpenList[16];
   747 static Uint8 KeyState[SDLK12_LAST];
   748 
   749 // !!! FIXME: need a mutex for the event queue.
   750 #define SDL12_MAXEVENTS 128
   751 typedef struct EventQueueType
   752 {
   753     SDL12_Event event12;
   754     struct EventQueueType *next;
   755 } EventQueueType;
   756 
   757 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
   758 static EventQueueType *EventQueueHead = NULL;
   759 static EventQueueType *EventQueueTail = NULL;
   760 static EventQueueType *EventQueueAvailable = NULL;
   761 
   762 
   763 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   764 #if defined(_WINDOWS)
   765     #define WIN32_LEAN_AND_MEAN 1
   766     #include <windows.h>
   767     #define SDL20_LIBNAME "SDL2.dll"
   768     static HANDLE Loaded_SDL20 = NULL;
   769     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   770     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   771     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   772 #elif defined(unix) || defined(__APPLE__)
   773     #include <dlfcn.h>
   774     #ifdef __APPLE__
   775     #define SDL20_LIBNAME "libSDL2-2.0.0.dylib"
   776     #else
   777     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   778     #endif
   779     static void *Loaded_SDL20 = NULL;
   780     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL|RTLD_NOW)) != NULL)
   781     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   782     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   783 #else
   784     #error Please define your platform.
   785 #endif
   786 
   787 static void *
   788 LoadSDL20Symbol(const char *fn, int *okay)
   789 {
   790     void *retval = NULL;
   791     if (*okay) { /* only bother trying if we haven't previously failed. */
   792         retval = LookupSDL20Sym(fn);
   793         if (retval == NULL) {
   794             /* Flip to 1 to warn but maybe work if nothing calls that function, flip to zero to fail out. */
   795             #if 0
   796             fprintf(stderr, "WARNING: LOAD FAILED: %s\n", fn);
   797             #else
   798             *okay = 0;
   799             #endif
   800         }
   801     }
   802     return retval;
   803 }
   804 
   805 static void
   806 UnloadSDL20(void)
   807 {
   808     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   809     #include "SDL20_syms.h"
   810     CloseSDL20Library();
   811 }
   812 
   813 static int
   814 LoadSDL20(void)
   815 {
   816     int okay = 1;
   817     if (!Loaded_SDL20)
   818     {
   819         okay = LoadSDL20Library();
   820         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   821         #include "SDL20_syms.h"
   822         if (!okay)
   823             UnloadSDL20();
   824     }
   825     return okay;
   826 }
   827 
   828 static void dllinit(void) __attribute__((constructor));
   829 static void dllinit(void)
   830 {
   831     if (!LoadSDL20()) {
   832         fprintf(stderr, "ERROR: sdl12-compat failed to load SDL 2.0! Aborting!\n");
   833         fflush(stderr);
   834         abort();
   835     }
   836 }
   837 
   838 static void dllquit(void) __attribute__((destructor));
   839 static void dllquit(void)
   840 {
   841     UnloadSDL20();
   842 }
   843 
   844 DECLSPEC const SDL_version * SDLCALL
   845 SDL_Linked_Version(void)
   846 {
   847     static const SDL_version version = { 1, 2, SDL12_COMPAT_VERSION };
   848     return &version;
   849 }
   850 
   851 DECLSPEC int SDLCALL
   852 SDL_sscanf(const char *text, const char *fmt, ...)
   853 {
   854     int retval;
   855     va_list ap;
   856     va_start(ap, fmt);
   857     retval = (int) SDL20_sscanf(text, fmt, ap);
   858     va_end(ap);
   859     return retval;
   860 }
   861 
   862 DECLSPEC int SDLCALL
   863 SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
   864 {
   865     int retval;
   866     va_list ap;
   867     va_start(ap, fmt);
   868     retval = (int) SDL20_vsnprintf(text, maxlen, fmt, ap);
   869     va_end(ap);
   870     return retval;
   871 }
   872 
   873 DECLSPEC void * SDLCALL
   874 SDL_revcpy(void *dst, const void *src, size_t len)
   875 {
   876     /* this doesn't reverse the data...I think this was just a memcpy that
   877        was meant to be CPU-cache friendly if you knew you were working with
   878        data going backwards in memory, instead of jumping over pages to copy
   879        from the start...? Whatever, just do a memcpy here. */
   880     return SDL_memcpy(dst, src, len);
   881 }
   882 
   883 
   884 DECLSPEC SDL_bool SDLCALL
   885 SDL_HasMMXExt(void)
   886 {
   887     /* this isn't accurate, but SDL2 doesn't have this for some reason.
   888         MMXExt is available in all SSE1 machines, except early Athlon chips,
   889         so we'll just say it's available if they have SSE1. Oh well. */
   890     return SDL20_HasSSE();
   891 }
   892 
   893 DECLSPEC SDL_bool SDLCALL
   894 SDL_Has3DNowExt(void)
   895 {
   896     FIXME("check this");
   897     return SDL20_HasSSE();
   898 }
   899 
   900 DECLSPEC SDL_Joystick * SDLCALL
   901 SDL_JoystickOpen(int device_index)
   902 {
   903     int i;
   904     SDL20_LockJoysticks();
   905     for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
   906         if (JoystickOpenList[i].joystick == NULL) {
   907             break;
   908         }
   909     }
   910 
   911     if (i == SDL_arraysize(JoystickOpenList)) {
   912         SDL20_UnlockJoysticks();
   913         SDL20_SetError("Too many open joysticks");
   914         return NULL;
   915     }
   916 
   917     JoystickOpenList[i].joystick = SDL20_JoystickOpen(device_index);
   918     if (JoystickOpenList[i].joystick) {
   919         JoystickOpenList[i].device_index = device_index;
   920     }
   921 
   922     SDL20_UnlockJoysticks();
   923     return JoystickOpenList[i].joystick;
   924 }
   925 
   926 DECLSPEC void SDLCALL
   927 SDL_JoystickClose(SDL_Joystick *joystick)
   928 {
   929     int i;
   930     SDL20_LockJoysticks();
   931     for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
   932         if (JoystickOpenList[i].joystick == joystick) {
   933             break;
   934         }
   935     }
   936 
   937     if (i < SDL_arraysize(JoystickOpenList)) {
   938         JoystickOpenList[i].joystick = NULL;
   939     }
   940 
   941     SDL20_UnlockJoysticks();
   942 
   943     SDL20_JoystickClose(joystick);
   944 }
   945 
   946 DECLSPEC const char * SDLCALL
   947 SDL_JoystickName(int device_index)
   948 {
   949     return SDL20_JoystickNameForIndex(device_index);
   950 }
   951 
   952 DECLSPEC int SDLCALL
   953 SDL_JoystickIndex(SDL_Joystick *joystick)
   954 {
   955     int i;
   956 
   957     SDL20_LockJoysticks(); {
   958         for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
   959             if (JoystickOpenList[i].joystick == joystick) {
   960                 break;
   961             }
   962         }
   963 
   964         if (i < SDL_arraysize(JoystickOpenList)) {
   965             SDL20_UnlockJoysticks();
   966             return JoystickOpenList[i].device_index;
   967         }
   968 
   969     }
   970     SDL20_UnlockJoysticks();
   971     return SDL20_SetError("Can't find joystick");
   972 }
   973 
   974 DECLSPEC int SDLCALL
   975 SDL_JoystickOpened(int device_index)
   976 {
   977     int retval = 0;
   978     int i;
   979     SDL20_LockJoysticks();
   980     for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
   981         if ((JoystickOpenList[i].joystick) && (JoystickOpenList[i].device_index == device_index)) {
   982             retval = 1;
   983             break;
   984         }
   985     }
   986     SDL20_UnlockJoysticks();
   987     return retval;
   988 }
   989 
   990 static SDL_PixelFormat *
   991 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
   992 {
   993     if (format12->palette) {
   994         palette20->ncolors = format12->palette->ncolors;
   995         palette20->colors = format12->palette->colors;
   996         palette20->version = 1;
   997         palette20->refcount = 1;
   998         format20->palette = palette20;
   999     } else {
  1000         format20->palette = NULL;
  1001     }
  1002 
  1003     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1004     format20->BitsPerPixel = format12->BitsPerPixel;
  1005     format20->BytesPerPixel = format12->BytesPerPixel;
  1006     format20->Rmask = format12->Rmask;
  1007     format20->Gmask = format12->Gmask;
  1008     format20->Bmask = format12->Bmask;
  1009     format20->Amask = format12->Amask;
  1010     format20->Rloss = format12->Rloss;
  1011     format20->Gloss = format12->Gloss;
  1012     format20->Bloss = format12->Bloss;
  1013     format20->Aloss = format12->Aloss;
  1014     format20->Rshift = format12->Rshift;
  1015     format20->Gshift = format12->Gshift;
  1016     format20->Bshift = format12->Bshift;
  1017     format20->Ashift = format12->Ashift;
  1018     format20->refcount = 1;
  1019     format20->next = NULL;
  1020     return format20;
  1021 }
  1022 
  1023 static SDL12_PixelFormat *
  1024 PixelFormat20to12(SDL12_PixelFormat *format12, SDL12_Palette *palette12, const SDL_PixelFormat *format20)
  1025 {
  1026     if (format20->palette) {
  1027         palette12->ncolors = format20->palette->ncolors;
  1028         palette12->colors = format20->palette->colors;
  1029         format12->palette = palette12;
  1030     } else {
  1031         format12->palette = NULL;
  1032     }
  1033 
  1034     format12->BitsPerPixel = format20->BitsPerPixel;
  1035     format12->BytesPerPixel = format20->BytesPerPixel;
  1036     format12->Rloss = format20->Rloss;
  1037     format12->Gloss = format20->Gloss;
  1038     format12->Bloss = format20->Bloss;
  1039     format12->Aloss = format20->Aloss;
  1040     format12->Rshift = format20->Rshift;
  1041     format12->Gshift = format20->Gshift;
  1042     format12->Bshift = format20->Bshift;
  1043     format12->Ashift = format20->Ashift;
  1044     format12->Rmask = format20->Rmask;
  1045     format12->Gmask = format20->Gmask;
  1046     format12->Bmask = format20->Bmask;
  1047     format12->Amask = format20->Amask;
  1048     format12->colorkey = 0;  // this is a surface, not pixelformat, properties in SDL2.
  1049     format12->alpha = 255;  // this is a surface, not pixelformat, properties in SDL2.
  1050     return format12;
  1051 }
  1052 
  1053 static int
  1054 GetVideoDisplay()
  1055 {
  1056     FIXME("cache this value during SDL_Init() so it doesn't change.");
  1057     const char *variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
  1058     if ( !variable ) {
  1059         variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
  1060     }
  1061     if ( variable ) {
  1062         return SDL20_atoi(variable);
  1063     } else {
  1064         return 0;
  1065     }
  1066 }
  1067 
  1068 /* This sets up VideoModes and VideoModesCount. You end up with arrays by pixel
  1069     format, each with a value that 1.2's SDL_ListModes() can return. */
  1070 static int
  1071 Init12VidModes(void)
  1072 {
  1073     const int total = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1074     VideoModeList *vmode = NULL;
  1075     void *ptr = NULL;
  1076     int i, j;
  1077 
  1078     if (VideoModesCount > 0) {
  1079         return 0;  // already did this.
  1080     }
  1081 
  1082     SDL_assert(VideoModes == NULL);
  1083 
  1084     for (i = 0; i < total; ++i) {
  1085         SDL_DisplayMode mode;
  1086 
  1087         if (SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode) == -1) {
  1088             continue;
  1089         } else if (!mode.w || !mode.h) {
  1090             SDL_assert(0 && "Can this actually happen?");
  1091             continue;
  1092         }
  1093 
  1094         if (!vmode || (mode.format != vmode->format)) {  // SDL20_GetDisplayMode() sorts on bpp first. We know when to change arrays.
  1095             ptr = (VideoModeList *) SDL20_realloc(VideoModes, sizeof (VideoModeList) * (VideoModesCount+1));
  1096             if (!ptr) {
  1097                 return SDL20_OutOfMemory();
  1098             }
  1099             VideoModes = (VideoModeList *) ptr;
  1100             vmode = &VideoModes[VideoModesCount];
  1101             vmode->format = mode.format;
  1102             vmode->nummodes = 0;
  1103             vmode->modeslist12 = NULL;
  1104             vmode->modes12 = NULL;
  1105             VideoModesCount++;
  1106         }
  1107 
  1108         /* make sure we don't have this one already (with a different refresh rate, etc). */
  1109         for (j = 0; j < vmode->nummodes; j++) {
  1110             if ((vmode->modeslist12[j].w == mode.w) && (vmode->modeslist12[j].h == mode.h)) {
  1111                 break;
  1112             }
  1113         }
  1114 
  1115         if (j < vmode->nummodes) {
  1116             continue;  /* already have this one. */
  1117         }
  1118 
  1119         FIXME("Make sure mode dimensions fit in 16-bits for SDL12_Rect");
  1120 
  1121         ptr = SDL20_realloc(vmode->modeslist12, sizeof (SDL12_Rect) * (vmode->nummodes + 1));
  1122         if (ptr == NULL) {
  1123             return SDL20_OutOfMemory();
  1124         }
  1125         vmode->modeslist12 = (SDL12_Rect *) ptr;
  1126 
  1127         vmode->modeslist12[vmode->nummodes].x = 0;
  1128         vmode->modeslist12[vmode->nummodes].y = 0;
  1129         vmode->modeslist12[vmode->nummodes].w = mode.w;
  1130         vmode->modeslist12[vmode->nummodes].h = mode.h;
  1131 
  1132         vmode->nummodes++;
  1133     }
  1134 
  1135     // link up modes12 for SDL_ListModes()'s use...
  1136     for (i = 0, vmode = VideoModes; i < VideoModesCount; i++, vmode++) {
  1137         const int nummodes = vmode->nummodes;
  1138         vmode->modes12 = (SDL12_Rect **) SDL20_calloc(sizeof (SDL12_Rect *), nummodes + 1);
  1139         if (vmode->modes12 == NULL) {
  1140             return SDL20_OutOfMemory();
  1141         }
  1142         for (j = 0; j < nummodes; j++) {
  1143             vmode->modes12[j] = &vmode->modeslist12[j];
  1144         }
  1145     }
  1146 
  1147     return 0;
  1148 }
  1149 
  1150 static int
  1151 Init12Video(void)
  1152 {
  1153     int i;
  1154 
  1155     for (i = 0; i < SDL12_MAXEVENTS-1; i++)
  1156         EventQueuePool[i].next = &EventQueuePool[i+1];
  1157     EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
  1158 
  1159     EventQueueHead = EventQueueTail = NULL;
  1160     EventQueueAvailable = EventQueuePool;
  1161 
  1162     SDL_memset(EventStates, SDL_ENABLE, sizeof (EventStates)); /* on by default */
  1163     EventStates[SDL12_SYSWMEVENT] = SDL_IGNORE;  /* off by default. */
  1164 
  1165     SDL20_SetEventFilter(EventFilter20to12, NULL);
  1166 
  1167     VideoDisplayIndex = GetVideoDisplay();
  1168     SwapInterval = 0;
  1169 
  1170     VideoWindowGrabbed = SDL_FALSE;
  1171     VideoCursorHidden = SDL_FALSE;
  1172     SDL20_ShowCursor(1);
  1173 
  1174     if (Init12VidModes() == -1) {
  1175         return -1;
  1176     }
  1177 
  1178     SDL20_StopTextInput();
  1179 
  1180     SDL_DisplayMode mode;
  1181     if (SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1182         VideoInfoVfmt20 = SDL20_AllocFormat(mode.format);
  1183         VideoInfo12.vfmt = PixelFormat20to12(&VideoInfoVfmt12, &VideoInfoPalette12, VideoInfoVfmt20);
  1184         VideoInfo12.current_w = mode.w;
  1185         VideoInfo12.current_h = mode.h;
  1186         VideoInfo12.wm_available = 1;  FIXME("not sure if we can determine this in SDL2...?");
  1187         VideoInfo12.video_mem = 1024 * 256;  /* good enough. */
  1188     }
  1189 
  1190     return 0;
  1191 }
  1192 
  1193 DECLSPEC int SDLCALL
  1194 SDL_InitSubSystem(Uint32 sdl12flags)
  1195 {
  1196     FIXME("there is never a parachute in SDL2, should we catch segfaults ourselves?");
  1197 
  1198     FIXME("support event thread where it makes sense to do so?");
  1199 
  1200     if ( (sdl12flags & SDL12_INIT_EVENTTHREAD) == SDL12_INIT_EVENTTHREAD ) {
  1201         return SDL20_SetError("OS doesn't support threaded events");
  1202     }
  1203 
  1204     Uint32 sdl20flags = 0;
  1205     int rc;
  1206 
  1207 #ifdef __MACOSX__
  1208     extern void sdl12_compat_macos_init(void);
  1209     sdl12_compat_macos_init();
  1210 #endif
  1211 
  1212     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
  1213     SETFLAG(TIMER);
  1214     SETFLAG(AUDIO);
  1215     SETFLAG(VIDEO);
  1216     SETFLAG(JOYSTICK);
  1217     SETFLAG(NOPARACHUTE);
  1218     #undef SETFLAG
  1219 
  1220     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
  1221     if (sdl12flags & SDL12_INIT_CDROM)
  1222         CDRomInit = 1;
  1223 
  1224     FIXME("do something about SDL12_INIT_EVENTTHREAD");
  1225 
  1226     rc = SDL20_Init(sdl20flags);
  1227     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO)) {
  1228         if (Init12Video() == -1) {
  1229             FIXME("should we deinit other subsystems?");
  1230             return -1;
  1231         }
  1232     }
  1233 
  1234     return rc;
  1235 }
  1236 
  1237 DECLSPEC int SDLCALL
  1238 SDL_Init(Uint32 sdl12flags)
  1239 {
  1240     FIXME("what was different in 1.2?");
  1241     return SDL_InitSubSystem(sdl12flags);   /* there's no difference betwee Init and InitSubSystem in SDL2. */
  1242 }
  1243 
  1244 
  1245 static void
  1246 InitFlags12To20(const Uint32 flags12, Uint32 *_flags20, Uint32 *_extraflags)
  1247 {
  1248     Uint32 flags20 = 0;
  1249     Uint32 extraflags = 0;
  1250 
  1251     #define SETFLAG(flag) if (flags12 & SDL12_INIT_##flag) flags20 |= SDL_INIT_##flag
  1252     SETFLAG(TIMER);
  1253     SETFLAG(AUDIO);
  1254     SETFLAG(VIDEO);
  1255     SETFLAG(JOYSTICK);
  1256     SETFLAG(NOPARACHUTE);
  1257     #undef SETFLAG
  1258 
  1259     if ((flags12 & SDL12_INIT_CDROM) && (CDRomInit)) {
  1260         extraflags |= SDL12_INIT_CDROM;
  1261     }
  1262 
  1263     FIXME("do something about SDL12_INIT_EVENTTHREAD");
  1264 
  1265     *_flags20 = flags20;
  1266     *_extraflags = extraflags;
  1267 }
  1268 
  1269 static Uint32
  1270 InitFlags20to12(const Uint32 flags20)
  1271 {
  1272     Uint32 flags12 = 0;
  1273 
  1274     #define SETFLAG(flag) if (flags20 & SDL_INIT_##flag) flags12 |= SDL12_INIT_##flag
  1275     SETFLAG(TIMER);
  1276     SETFLAG(AUDIO);
  1277     SETFLAG(VIDEO);
  1278     SETFLAG(JOYSTICK);
  1279     SETFLAG(NOPARACHUTE);
  1280     #undef SETFLAG
  1281 
  1282     return flags12;
  1283 }
  1284 
  1285 
  1286 DECLSPEC Uint32 SDLCALL
  1287 SDL_WasInit(Uint32 sdl12flags)
  1288 {
  1289     Uint32 sdl20flags, extraflags;
  1290     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
  1291 
  1292     return InitFlags20to12(SDL20_WasInit(sdl20flags)) | extraflags;
  1293 }
  1294 
  1295 static void
  1296 Quit12Video(void)
  1297 {
  1298     int i;
  1299 
  1300     SDL20_FreeSurface(VideoIcon20);
  1301     VideoIcon20 = NULL;
  1302 
  1303     for (i = 0; i < VideoModesCount; i++) {
  1304         SDL20_free(VideoModes[i].modeslist12);
  1305         SDL20_free(VideoModes[i].modes12);
  1306     }
  1307     SDL20_free(VideoModes);
  1308 
  1309     SDL20_FreeFormat(VideoInfoVfmt20);
  1310     SDL20_zero(VideoInfo12);
  1311 
  1312     VideoInfoVfmt20 = NULL;
  1313     EventFilter12 = NULL;
  1314     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
  1315     CurrentCursor12 = NULL;
  1316     VideoModes = NULL;
  1317     VideoModesCount = 0;
  1318 }
  1319 
  1320 DECLSPEC void SDLCALL
  1321 SDL_QuitSubSystem(Uint32 sdl12flags)
  1322 {
  1323     Uint32 sdl20flags, extraflags;
  1324     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
  1325 
  1326     if (extraflags & SDL12_INIT_CDROM) {
  1327         CDRomInit = 0;
  1328     }
  1329 
  1330     FIXME("reset a bunch of other global variables too.");
  1331     if (sdl12flags & SDL12_INIT_VIDEO) {
  1332         Quit12Video();
  1333     }
  1334 
  1335     FIXME("do something about SDL12_INIT_EVENTTHREAD");
  1336     SDL20_QuitSubSystem(sdl20flags);
  1337 
  1338     if ((SDL20_WasInit(0) == 0) && (!CDRomInit)) {
  1339         SDL20_Quit();
  1340     }
  1341 }
  1342 
  1343 DECLSPEC void SDLCALL
  1344 SDL_Quit(void)
  1345 {
  1346     SDL_QuitSubSystem(SDL_WasInit(0) | SDL12_INIT_CDROM);
  1347 }
  1348 
  1349 DECLSPEC void SDLCALL
  1350 SDL_SetError(const char *fmt, ...)
  1351 {
  1352     char ch;
  1353     char *str = NULL;
  1354     size_t len = 0;
  1355     va_list ap;
  1356 
  1357     va_start(ap, fmt);
  1358     len = SDL20_vsnprintf(&ch, 1, fmt, ap);
  1359     va_end(ap);
  1360 
  1361     str = (char *) SDL20_malloc(len + 1);
  1362     if (!str)
  1363         SDL20_OutOfMemory();
  1364     else
  1365     {
  1366         va_start(ap, fmt);
  1367         SDL20_vsnprintf(str, len + 1, fmt, ap);
  1368         va_end(ap);
  1369         SDL20_SetError("%s", str);
  1370         SDL20_free(str);
  1371     }
  1372 }
  1373 
  1374 DECLSPEC const char * SDLCALL
  1375 SDL_GetError(void)
  1376 {
  1377     if (SDL20_GetError == NULL)
  1378     {
  1379         static const char noload_errstr[] = "The SDL 2.0 library that the 1.2 compatibility layer needs isn't loaded";
  1380         return noload_errstr;
  1381     }
  1382     return SDL20_GetError();
  1383 }
  1384 
  1385 
  1386 static const char *
  1387 GetDriverName(const char *name, char *namebuf, int maxlen)
  1388 {
  1389     if (name) {
  1390         if (namebuf) {
  1391             SDL20_strlcpy(namebuf, name, maxlen);
  1392             return namebuf;
  1393         } else {
  1394             return name;
  1395         }
  1396     }
  1397     return NULL;
  1398 }
  1399 
  1400 DECLSPEC const char * SDLCALL
  1401 SDL_AudioDriverName(char *namebuf, int maxlen)
  1402 {
  1403     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
  1404 }
  1405 
  1406 DECLSPEC const char * SDLCALL
  1407 SDL_VideoDriverName(char *namebuf, int maxlen)
  1408 {
  1409     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
  1410 }
  1411 
  1412 
  1413 DECLSPEC int SDLCALL
  1414 SDL_PollEvent(SDL12_Event *event12)
  1415 {
  1416     EventQueueType *next;
  1417 
  1418     SDL_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
  1419 
  1420     if (EventQueueHead == NULL) {
  1421         return 0;  /* no events at the moment. */
  1422     }
  1423 
  1424     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
  1425     next = EventQueueHead->next;
  1426     EventQueueHead->next = EventQueueAvailable;
  1427     EventQueueAvailable = EventQueueHead;
  1428     EventQueueHead = next;
  1429     if (!next) {
  1430         EventQueueTail = NULL;
  1431     }
  1432 
  1433     return 1;
  1434 }
  1435 
  1436 DECLSPEC int SDLCALL
  1437 SDL_PushEvent(SDL12_Event *event12)
  1438 {
  1439     EventQueueType *item = EventQueueAvailable;
  1440     if (item == NULL) {
  1441         return -1;  /* no space available at the moment. */
  1442     }
  1443 
  1444     EventQueueAvailable = item->next;
  1445     if (EventQueueTail) {
  1446         EventQueueTail->next = item;
  1447         EventQueueTail = item;
  1448     } else {
  1449         EventQueueHead = EventQueueTail = item;
  1450     }
  1451     item->next = NULL;
  1452 
  1453     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
  1454 
  1455     return 0;
  1456 }
  1457 
  1458 DECLSPEC int SDLCALL
  1459 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
  1460 {
  1461     if (action == SDL_ADDEVENT)
  1462     {
  1463         int i;
  1464         for (i = 0; i < numevents; i++)
  1465         {
  1466             if (SDL_PushEvent(&events12[i]) == -1)
  1467                 break;  /* out of space for more events. */
  1468         }
  1469         return i;
  1470     }
  1471     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
  1472     {
  1473         const SDL_bool isGet = (action == SDL_GETEVENT);
  1474         EventQueueType *prev = NULL;
  1475         EventQueueType *item = EventQueueHead;
  1476         EventQueueType *next = NULL;
  1477         int chosen = 0;
  1478         while (chosen < numevents)
  1479         {
  1480             EventQueueType *nextPrev = item;
  1481             if (!item)
  1482                 break;  /* no more events at the moment. */
  1483 
  1484             next = item->next;  /* copy, since we might overwrite item->next */
  1485 
  1486             if (mask & (1<<item->event12.type))
  1487             {
  1488                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
  1489                 if (isGet)  /* remove from list? */
  1490                 {
  1491                     if (prev != NULL)
  1492                         prev->next = next;
  1493                     if (item == EventQueueHead)
  1494                         EventQueueHead = next;
  1495                     if (item == EventQueueTail)
  1496                         EventQueueTail = prev;
  1497 
  1498                     /* put it back in the free pool. */
  1499                     item->next = EventQueueAvailable;
  1500                     EventQueueAvailable = item;
  1501                     nextPrev = prev;  /* previous item doesn't change. */
  1502                 }
  1503             }
  1504 
  1505             item = next;
  1506             prev = nextPrev;
  1507         }
  1508         return chosen;
  1509     }
  1510 
  1511     return 0;
  1512 }
  1513 
  1514 DECLSPEC int SDLCALL
  1515 SDL_WaitEvent(SDL12_Event *event12)
  1516 {
  1517     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1518     while (!SDL_PollEvent(event12))
  1519         SDL20_Delay(10);
  1520     return 1;
  1521 }
  1522 
  1523 static SDL_bool
  1524 PushEventIfNotFiltered(SDL12_Event *event12)
  1525 {
  1526     if (event12->type != SDL12_NOEVENT)
  1527     {
  1528         if (EventStates[event12->type] != SDL_IGNORE)
  1529         {
  1530             if ((!EventFilter12) || (EventFilter12(event12)))
  1531                 return (SDL_PushEvent(event12) == 0);
  1532         }
  1533     }
  1534     return SDL_FALSE;
  1535 }
  1536 
  1537 DECLSPEC Uint8 SDLCALL
  1538 SDL_EventState(Uint8 type, int state)
  1539 {
  1540     /* the values of "state" match between 1.2 and 2.0 */
  1541     const Uint8 retval = EventStates[type];
  1542     SDL12_Event e;
  1543 
  1544     if (state != SDL_QUERY)
  1545         EventStates[type] = state;
  1546     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1547         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1548 
  1549     return retval;
  1550 }
  1551 
  1552 static Uint8 MouseButtonState20to12(const Uint32 state20)
  1553 {
  1554     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1555 
  1556     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1557     if (state20 & SDL_BUTTON(SDL_BUTTON_X1)) {
  1558         retval |= (1<<5);
  1559     }
  1560     if (state20 & SDL_BUTTON(SDL_BUTTON_X2)) {
  1561         retval |= (1<<6);
  1562     }
  1563 
  1564     return retval;
  1565 }
  1566 
  1567 DECLSPEC Uint8 SDLCALL
  1568 SDL_GetMouseState(int *x, int *y)
  1569 {
  1570     return MouseButtonState20to12(SDL20_GetMouseState(x, y));
  1571 }
  1572 
  1573 DECLSPEC Uint8 SDLCALL
  1574 SDL_GetRelativeMouseState(int *x, int *y)
  1575 {
  1576     return MouseButtonState20to12(SDL20_GetRelativeMouseState(x, y));
  1577 }
  1578 
  1579 DECLSPEC char * SDLCALL
  1580 SDL_GetKeyName(SDL12Key key)
  1581 {
  1582     switch (key) {
  1583         #define CASESDLK12TONAME(k, n) case k: return (char *) n
  1584 	    CASESDLK12TONAME(SDLK12_BACKSPACE, "backspace");
  1585 	    CASESDLK12TONAME(SDLK12_TAB, "tab");
  1586 	    CASESDLK12TONAME(SDLK12_CLEAR, "clear");
  1587 	    CASESDLK12TONAME(SDLK12_RETURN, "return");
  1588 	    CASESDLK12TONAME(SDLK12_PAUSE, "pause");
  1589 	    CASESDLK12TONAME(SDLK12_ESCAPE, "escape");
  1590 	    CASESDLK12TONAME(SDLK12_SPACE, "space");
  1591 	    CASESDLK12TONAME(SDLK12_EXCLAIM, "!");
  1592 	    CASESDLK12TONAME(SDLK12_QUOTEDBL, "\"");
  1593 	    CASESDLK12TONAME(SDLK12_HASH, "#");
  1594 	    CASESDLK12TONAME(SDLK12_DOLLAR, "$");
  1595 	    CASESDLK12TONAME(SDLK12_AMPERSAND, "&");
  1596 	    CASESDLK12TONAME(SDLK12_QUOTE, "'");
  1597 	    CASESDLK12TONAME(SDLK12_LEFTPAREN, "(");
  1598 	    CASESDLK12TONAME(SDLK12_RIGHTPAREN, ")");
  1599 	    CASESDLK12TONAME(SDLK12_ASTERISK, "*");
  1600 	    CASESDLK12TONAME(SDLK12_PLUS, "+");
  1601 	    CASESDLK12TONAME(SDLK12_COMMA, ",");
  1602 	    CASESDLK12TONAME(SDLK12_MINUS, "-");
  1603 	    CASESDLK12TONAME(SDLK12_PERIOD, ".");
  1604 	    CASESDLK12TONAME(SDLK12_SLASH, "/");
  1605 	    CASESDLK12TONAME(SDLK12_0, "0");
  1606 	    CASESDLK12TONAME(SDLK12_1, "1");
  1607 	    CASESDLK12TONAME(SDLK12_2, "2");
  1608 	    CASESDLK12TONAME(SDLK12_3, "3");
  1609 	    CASESDLK12TONAME(SDLK12_4, "4");
  1610 	    CASESDLK12TONAME(SDLK12_5, "5");
  1611 	    CASESDLK12TONAME(SDLK12_6, "6");
  1612 	    CASESDLK12TONAME(SDLK12_7, "7");
  1613 	    CASESDLK12TONAME(SDLK12_8, "8");
  1614 	    CASESDLK12TONAME(SDLK12_9, "9");
  1615 	    CASESDLK12TONAME(SDLK12_COLON, ":");
  1616 	    CASESDLK12TONAME(SDLK12_SEMICOLON, ");");
  1617 	    CASESDLK12TONAME(SDLK12_LESS, "<");
  1618 	    CASESDLK12TONAME(SDLK12_EQUALS, "=");
  1619 	    CASESDLK12TONAME(SDLK12_GREATER, ">");
  1620 	    CASESDLK12TONAME(SDLK12_QUESTION, "?");
  1621 	    CASESDLK12TONAME(SDLK12_AT, "@");
  1622 	    CASESDLK12TONAME(SDLK12_LEFTBRACKET, "[");
  1623 	    CASESDLK12TONAME(SDLK12_BACKSLASH, "\\");
  1624 	    CASESDLK12TONAME(SDLK12_RIGHTBRACKET, "]");
  1625 	    CASESDLK12TONAME(SDLK12_CARET, "^");
  1626 	    CASESDLK12TONAME(SDLK12_UNDERSCORE, "_");
  1627 	    CASESDLK12TONAME(SDLK12_BACKQUOTE, "`");
  1628 	    CASESDLK12TONAME(SDLK12_a, "a");
  1629 	    CASESDLK12TONAME(SDLK12_b, "b");
  1630 	    CASESDLK12TONAME(SDLK12_c, "c");
  1631 	    CASESDLK12TONAME(SDLK12_d, "d");
  1632 	    CASESDLK12TONAME(SDLK12_e, "e");
  1633 	    CASESDLK12TONAME(SDLK12_f, "f");
  1634 	    CASESDLK12TONAME(SDLK12_g, "g");
  1635 	    CASESDLK12TONAME(SDLK12_h, "h");
  1636 	    CASESDLK12TONAME(SDLK12_i, "i");
  1637 	    CASESDLK12TONAME(SDLK12_j, "j");
  1638 	    CASESDLK12TONAME(SDLK12_k, "k");
  1639 	    CASESDLK12TONAME(SDLK12_l, "l");
  1640 	    CASESDLK12TONAME(SDLK12_m, "m");
  1641 	    CASESDLK12TONAME(SDLK12_n, "n");
  1642 	    CASESDLK12TONAME(SDLK12_o, "o");
  1643 	    CASESDLK12TONAME(SDLK12_p, "p");
  1644 	    CASESDLK12TONAME(SDLK12_q, "q");
  1645 	    CASESDLK12TONAME(SDLK12_r, "r");
  1646 	    CASESDLK12TONAME(SDLK12_s, "s");
  1647 	    CASESDLK12TONAME(SDLK12_t, "t");
  1648 	    CASESDLK12TONAME(SDLK12_u, "u");
  1649 	    CASESDLK12TONAME(SDLK12_v, "v");
  1650 	    CASESDLK12TONAME(SDLK12_w, "w");
  1651 	    CASESDLK12TONAME(SDLK12_x, "x");
  1652 	    CASESDLK12TONAME(SDLK12_y, "y");
  1653 	    CASESDLK12TONAME(SDLK12_z, "z");
  1654 	    CASESDLK12TONAME(SDLK12_DELETE, "delete");
  1655 
  1656 	    CASESDLK12TONAME(SDLK12_WORLD_0, "world 0");
  1657 	    CASESDLK12TONAME(SDLK12_WORLD_1, "world 1");
  1658 	    CASESDLK12TONAME(SDLK12_WORLD_2, "world 2");
  1659 	    CASESDLK12TONAME(SDLK12_WORLD_3, "world 3");
  1660 	    CASESDLK12TONAME(SDLK12_WORLD_4, "world 4");
  1661 	    CASESDLK12TONAME(SDLK12_WORLD_5, "world 5");
  1662 	    CASESDLK12TONAME(SDLK12_WORLD_6, "world 6");
  1663 	    CASESDLK12TONAME(SDLK12_WORLD_7, "world 7");
  1664 	    CASESDLK12TONAME(SDLK12_WORLD_8, "world 8");
  1665 	    CASESDLK12TONAME(SDLK12_WORLD_9, "world 9");
  1666 	    CASESDLK12TONAME(SDLK12_WORLD_10, "world 10");
  1667 	    CASESDLK12TONAME(SDLK12_WORLD_11, "world 11");
  1668 	    CASESDLK12TONAME(SDLK12_WORLD_12, "world 12");
  1669 	    CASESDLK12TONAME(SDLK12_WORLD_13, "world 13");
  1670 	    CASESDLK12TONAME(SDLK12_WORLD_14, "world 14");
  1671 	    CASESDLK12TONAME(SDLK12_WORLD_15, "world 15");
  1672 	    CASESDLK12TONAME(SDLK12_WORLD_16, "world 16");
  1673 	    CASESDLK12TONAME(SDLK12_WORLD_17, "world 17");
  1674 	    CASESDLK12TONAME(SDLK12_WORLD_18, "world 18");
  1675 	    CASESDLK12TONAME(SDLK12_WORLD_19, "world 19");
  1676 	    CASESDLK12TONAME(SDLK12_WORLD_20, "world 20");
  1677 	    CASESDLK12TONAME(SDLK12_WORLD_21, "world 21");
  1678 	    CASESDLK12TONAME(SDLK12_WORLD_22, "world 22");
  1679 	    CASESDLK12TONAME(SDLK12_WORLD_23, "world 23");
  1680 	    CASESDLK12TONAME(SDLK12_WORLD_24, "world 24");
  1681 	    CASESDLK12TONAME(SDLK12_WORLD_25, "world 25");
  1682 	    CASESDLK12TONAME(SDLK12_WORLD_26, "world 26");
  1683 	    CASESDLK12TONAME(SDLK12_WORLD_27, "world 27");
  1684 	    CASESDLK12TONAME(SDLK12_WORLD_28, "world 28");
  1685 	    CASESDLK12TONAME(SDLK12_WORLD_29, "world 29");
  1686 	    CASESDLK12TONAME(SDLK12_WORLD_30, "world 30");
  1687 	    CASESDLK12TONAME(SDLK12_WORLD_31, "world 31");
  1688 	    CASESDLK12TONAME(SDLK12_WORLD_32, "world 32");
  1689 	    CASESDLK12TONAME(SDLK12_WORLD_33, "world 33");
  1690 	    CASESDLK12TONAME(SDLK12_WORLD_34, "world 34");
  1691 	    CASESDLK12TONAME(SDLK12_WORLD_35, "world 35");
  1692 	    CASESDLK12TONAME(SDLK12_WORLD_36, "world 36");
  1693 	    CASESDLK12TONAME(SDLK12_WORLD_37, "world 37");
  1694 	    CASESDLK12TONAME(SDLK12_WORLD_38, "world 38");
  1695 	    CASESDLK12TONAME(SDLK12_WORLD_39, "world 39");
  1696 	    CASESDLK12TONAME(SDLK12_WORLD_40, "world 40");
  1697 	    CASESDLK12TONAME(SDLK12_WORLD_41, "world 41");
  1698 	    CASESDLK12TONAME(SDLK12_WORLD_42, "world 42");
  1699 	    CASESDLK12TONAME(SDLK12_WORLD_43, "world 43");
  1700 	    CASESDLK12TONAME(SDLK12_WORLD_44, "world 44");
  1701 	    CASESDLK12TONAME(SDLK12_WORLD_45, "world 45");
  1702 	    CASESDLK12TONAME(SDLK12_WORLD_46, "world 46");
  1703 	    CASESDLK12TONAME(SDLK12_WORLD_47, "world 47");
  1704 	    CASESDLK12TONAME(SDLK12_WORLD_48, "world 48");
  1705 	    CASESDLK12TONAME(SDLK12_WORLD_49, "world 49");
  1706 	    CASESDLK12TONAME(SDLK12_WORLD_50, "world 50");
  1707 	    CASESDLK12TONAME(SDLK12_WORLD_51, "world 51");
  1708 	    CASESDLK12TONAME(SDLK12_WORLD_52, "world 52");
  1709 	    CASESDLK12TONAME(SDLK12_WORLD_53, "world 53");
  1710 	    CASESDLK12TONAME(SDLK12_WORLD_54, "world 54");
  1711 	    CASESDLK12TONAME(SDLK12_WORLD_55, "world 55");
  1712 	    CASESDLK12TONAME(SDLK12_WORLD_56, "world 56");
  1713 	    CASESDLK12TONAME(SDLK12_WORLD_57, "world 57");
  1714 	    CASESDLK12TONAME(SDLK12_WORLD_58, "world 58");
  1715 	    CASESDLK12TONAME(SDLK12_WORLD_59, "world 59");
  1716 	    CASESDLK12TONAME(SDLK12_WORLD_60, "world 60");
  1717 	    CASESDLK12TONAME(SDLK12_WORLD_61, "world 61");
  1718 	    CASESDLK12TONAME(SDLK12_WORLD_62, "world 62");
  1719 	    CASESDLK12TONAME(SDLK12_WORLD_63, "world 63");
  1720 	    CASESDLK12TONAME(SDLK12_WORLD_64, "world 64");
  1721 	    CASESDLK12TONAME(SDLK12_WORLD_65, "world 65");
  1722 	    CASESDLK12TONAME(SDLK12_WORLD_66, "world 66");
  1723 	    CASESDLK12TONAME(SDLK12_WORLD_67, "world 67");
  1724 	    CASESDLK12TONAME(SDLK12_WORLD_68, "world 68");
  1725 	    CASESDLK12TONAME(SDLK12_WORLD_69, "world 69");
  1726 	    CASESDLK12TONAME(SDLK12_WORLD_70, "world 70");
  1727 	    CASESDLK12TONAME(SDLK12_WORLD_71, "world 71");
  1728 	    CASESDLK12TONAME(SDLK12_WORLD_72, "world 72");
  1729 	    CASESDLK12TONAME(SDLK12_WORLD_73, "world 73");
  1730 	    CASESDLK12TONAME(SDLK12_WORLD_74, "world 74");
  1731 	    CASESDLK12TONAME(SDLK12_WORLD_75, "world 75");
  1732 	    CASESDLK12TONAME(SDLK12_WORLD_76, "world 76");
  1733 	    CASESDLK12TONAME(SDLK12_WORLD_77, "world 77");
  1734 	    CASESDLK12TONAME(SDLK12_WORLD_78, "world 78");
  1735 	    CASESDLK12TONAME(SDLK12_WORLD_79, "world 79");
  1736 	    CASESDLK12TONAME(SDLK12_WORLD_80, "world 80");
  1737 	    CASESDLK12TONAME(SDLK12_WORLD_81, "world 81");
  1738 	    CASESDLK12TONAME(SDLK12_WORLD_82, "world 82");
  1739 	    CASESDLK12TONAME(SDLK12_WORLD_83, "world 83");
  1740 	    CASESDLK12TONAME(SDLK12_WORLD_84, "world 84");
  1741 	    CASESDLK12TONAME(SDLK12_WORLD_85, "world 85");
  1742 	    CASESDLK12TONAME(SDLK12_WORLD_86, "world 86");
  1743 	    CASESDLK12TONAME(SDLK12_WORLD_87, "world 87");
  1744 	    CASESDLK12TONAME(SDLK12_WORLD_88, "world 88");
  1745 	    CASESDLK12TONAME(SDLK12_WORLD_89, "world 89");
  1746 	    CASESDLK12TONAME(SDLK12_WORLD_90, "world 90");
  1747 	    CASESDLK12TONAME(SDLK12_WORLD_91, "world 91");
  1748 	    CASESDLK12TONAME(SDLK12_WORLD_92, "world 92");
  1749 	    CASESDLK12TONAME(SDLK12_WORLD_93, "world 93");
  1750 	    CASESDLK12TONAME(SDLK12_WORLD_94, "world 94");
  1751 	    CASESDLK12TONAME(SDLK12_WORLD_95, "world 95");
  1752 
  1753 	    CASESDLK12TONAME(SDLK12_KP0, "[0]");
  1754 	    CASESDLK12TONAME(SDLK12_KP1, "[1]");
  1755 	    CASESDLK12TONAME(SDLK12_KP2, "[2]");
  1756 	    CASESDLK12TONAME(SDLK12_KP3, "[3]");
  1757 	    CASESDLK12TONAME(SDLK12_KP4, "[4]");
  1758 	    CASESDLK12TONAME(SDLK12_KP5, "[5]");
  1759 	    CASESDLK12TONAME(SDLK12_KP6, "[6]");
  1760 	    CASESDLK12TONAME(SDLK12_KP7, "[7]");
  1761 	    CASESDLK12TONAME(SDLK12_KP8, "[8]");
  1762 	    CASESDLK12TONAME(SDLK12_KP9, "[9]");
  1763 	    CASESDLK12TONAME(SDLK12_KP_PERIOD, "[.]");
  1764 	    CASESDLK12TONAME(SDLK12_KP_DIVIDE, "[/]");
  1765 	    CASESDLK12TONAME(SDLK12_KP_MULTIPLY, "[*]");
  1766 	    CASESDLK12TONAME(SDLK12_KP_MINUS, "[-]");
  1767 	    CASESDLK12TONAME(SDLK12_KP_PLUS, "[+]");
  1768 	    CASESDLK12TONAME(SDLK12_KP_ENTER, "enter");
  1769 	    CASESDLK12TONAME(SDLK12_KP_EQUALS, "equals");
  1770 
  1771 	    CASESDLK12TONAME(SDLK12_UP, "up");
  1772 	    CASESDLK12TONAME(SDLK12_DOWN, "down");
  1773 	    CASESDLK12TONAME(SDLK12_RIGHT, "right");
  1774 	    CASESDLK12TONAME(SDLK12_LEFT, "left");
  1775 	    CASESDLK12TONAME(SDLK12_INSERT, "insert");
  1776 	    CASESDLK12TONAME(SDLK12_HOME, "home");
  1777 	    CASESDLK12TONAME(SDLK12_END, "end");
  1778 	    CASESDLK12TONAME(SDLK12_PAGEUP, "page up");
  1779 	    CASESDLK12TONAME(SDLK12_PAGEDOWN, "page down");
  1780 
  1781 	    CASESDLK12TONAME(SDLK12_F1, "f1");
  1782 	    CASESDLK12TONAME(SDLK12_F2, "f2");
  1783 	    CASESDLK12TONAME(SDLK12_F3, "f3");
  1784 	    CASESDLK12TONAME(SDLK12_F4, "f4");
  1785 	    CASESDLK12TONAME(SDLK12_F5, "f5");
  1786 	    CASESDLK12TONAME(SDLK12_F6, "f6");
  1787 	    CASESDLK12TONAME(SDLK12_F7, "f7");
  1788 	    CASESDLK12TONAME(SDLK12_F8, "f8");
  1789 	    CASESDLK12TONAME(SDLK12_F9, "f9");
  1790 	    CASESDLK12TONAME(SDLK12_F10, "f10");
  1791 	    CASESDLK12TONAME(SDLK12_F11, "f11");
  1792 	    CASESDLK12TONAME(SDLK12_F12, "f12");
  1793 	    CASESDLK12TONAME(SDLK12_F13, "f13");
  1794 	    CASESDLK12TONAME(SDLK12_F14, "f14");
  1795 	    CASESDLK12TONAME(SDLK12_F15, "f15");
  1796 
  1797 	    CASESDLK12TONAME(SDLK12_NUMLOCK, "numlock");
  1798 	    CASESDLK12TONAME(SDLK12_CAPSLOCK, "caps lock");
  1799 	    CASESDLK12TONAME(SDLK12_SCROLLOCK, "scroll lock");
  1800 	    CASESDLK12TONAME(SDLK12_RSHIFT, "right shift");
  1801 	    CASESDLK12TONAME(SDLK12_LSHIFT, "left shift");
  1802 	    CASESDLK12TONAME(SDLK12_RCTRL, "right ctrl");
  1803 	    CASESDLK12TONAME(SDLK12_LCTRL, "left ctrl");
  1804 	    CASESDLK12TONAME(SDLK12_RALT, "right alt");
  1805 	    CASESDLK12TONAME(SDLK12_LALT, "left alt");
  1806 	    CASESDLK12TONAME(SDLK12_RMETA, "right meta");
  1807 	    CASESDLK12TONAME(SDLK12_LMETA, "left meta");
  1808 	    CASESDLK12TONAME(SDLK12_LSUPER, "left super");	/* "Windows" keys */
  1809 	    CASESDLK12TONAME(SDLK12_RSUPER, "right super");	
  1810 	    CASESDLK12TONAME(SDLK12_MODE, "alt gr");
  1811 	    CASESDLK12TONAME(SDLK12_COMPOSE, "compose");
  1812 
  1813 	    CASESDLK12TONAME(SDLK12_HELP, "help");
  1814 	    CASESDLK12TONAME(SDLK12_PRINT, "print screen");
  1815 	    CASESDLK12TONAME(SDLK12_SYSREQ, "sys req");
  1816 	    CASESDLK12TONAME(SDLK12_BREAK, "break");
  1817 	    CASESDLK12TONAME(SDLK12_MENU, "menu");
  1818 	    CASESDLK12TONAME(SDLK12_POWER, "power");
  1819 	    CASESDLK12TONAME(SDLK12_EURO, "euro");
  1820 	    CASESDLK12TONAME(SDLK12_UNDO, "undo");
  1821         #undef CASESDLK12TONAME
  1822         default: break;
  1823     }
  1824 
  1825     return (char *) "unknown key";
  1826 }
  1827 
  1828 static SDL12Key
  1829 Keysym20to12(const SDL_Keycode keysym20)
  1830 {
  1831     if ( ((int) keysym20) < 127 ) {  /* (most of) low-ASCII maps directly */
  1832         if (keysym20 == SDLK_PAUSE) {
  1833             return SDLK12_PAUSE;
  1834         } else if (keysym20 == SDLK_CLEAR) {
  1835             return SDLK12_CLEAR;
  1836         }
  1837         return (SDL12Key) keysym20;
  1838     }
  1839 
  1840     switch (keysym20) {
  1841         #define CASEKEYSYM20TO12(k20, k12) case SDLK_##k20: return SDLK12_##k12
  1842         CASEKEYSYM20TO12(KP_0, KP0);
  1843         CASEKEYSYM20TO12(KP_1, KP1);
  1844         CASEKEYSYM20TO12(KP_2, KP2);
  1845         CASEKEYSYM20TO12(KP_3, KP3);
  1846         CASEKEYSYM20TO12(KP_4, KP4);
  1847         CASEKEYSYM20TO12(KP_5, KP5);
  1848         CASEKEYSYM20TO12(KP_6, KP6);
  1849         CASEKEYSYM20TO12(KP_7, KP7);
  1850         CASEKEYSYM20TO12(KP_8, KP8);
  1851         CASEKEYSYM20TO12(KP_9, KP9);
  1852         CASEKEYSYM20TO12(NUMLOCKCLEAR, NUMLOCK);
  1853         CASEKEYSYM20TO12(SCROLLLOCK, SCROLLOCK);
  1854         CASEKEYSYM20TO12(RGUI, RMETA);
  1855         CASEKEYSYM20TO12(LGUI, LMETA);
  1856         CASEKEYSYM20TO12(PRINTSCREEN, PRINT);
  1857         #undef CASEKEYSYM20TO12
  1858 
  1859         #define CASEKEYSYM20TO12(k) case SDLK_##k: return SDLK12_##k
  1860         CASEKEYSYM20TO12(CLEAR);
  1861         CASEKEYSYM20TO12(PAUSE);
  1862         CASEKEYSYM20TO12(KP_PERIOD);
  1863         CASEKEYSYM20TO12(KP_DIVIDE);
  1864         CASEKEYSYM20TO12(KP_MULTIPLY);
  1865         CASEKEYSYM20TO12(KP_MINUS);
  1866         CASEKEYSYM20TO12(KP_PLUS);
  1867         CASEKEYSYM20TO12(KP_ENTER);
  1868         CASEKEYSYM20TO12(KP_EQUALS);
  1869         CASEKEYSYM20TO12(UP);
  1870         CASEKEYSYM20TO12(DOWN);
  1871         CASEKEYSYM20TO12(RIGHT);
  1872         CASEKEYSYM20TO12(LEFT);
  1873         CASEKEYSYM20TO12(INSERT);
  1874         CASEKEYSYM20TO12(HOME);
  1875         CASEKEYSYM20TO12(END);
  1876         CASEKEYSYM20TO12(PAGEUP);
  1877         CASEKEYSYM20TO12(PAGEDOWN);
  1878         CASEKEYSYM20TO12(F1);
  1879         CASEKEYSYM20TO12(F2);
  1880         CASEKEYSYM20TO12(F3);
  1881         CASEKEYSYM20TO12(F4);
  1882         CASEKEYSYM20TO12(F5);
  1883         CASEKEYSYM20TO12(F6);
  1884         CASEKEYSYM20TO12(F7);
  1885         CASEKEYSYM20TO12(F8);
  1886         CASEKEYSYM20TO12(F9);
  1887         CASEKEYSYM20TO12(F10);
  1888         CASEKEYSYM20TO12(F11);
  1889         CASEKEYSYM20TO12(F12);
  1890         CASEKEYSYM20TO12(F13);
  1891         CASEKEYSYM20TO12(F14);
  1892         CASEKEYSYM20TO12(F15);
  1893         CASEKEYSYM20TO12(CAPSLOCK);
  1894         CASEKEYSYM20TO12(RSHIFT);
  1895         CASEKEYSYM20TO12(LSHIFT);
  1896         CASEKEYSYM20TO12(RCTRL);
  1897         CASEKEYSYM20TO12(LCTRL);
  1898         CASEKEYSYM20TO12(RALT);
  1899         CASEKEYSYM20TO12(LALT);
  1900         CASEKEYSYM20TO12(MODE);
  1901         CASEKEYSYM20TO12(HELP);
  1902         CASEKEYSYM20TO12(SYSREQ);;
  1903         CASEKEYSYM20TO12(MENU);
  1904         CASEKEYSYM20TO12(POWER);
  1905         CASEKEYSYM20TO12(UNDO);
  1906         #undef CASEKEYSYM20TO12
  1907         default: break;
  1908     }
  1909 
  1910     FIXME("nothing maps to SDLK12_COMPOSE, SDLK12_BREAK, or SDLK12_EURO ...?");
  1911     FIXME("map some of the SDLK12_WORLD keys");
  1912     return SDLK12_UNKNOWN;
  1913 }
  1914 
  1915 DECLSPEC Uint8 * SDLCALL
  1916 SDL_GetKeyState(int *numkeys)
  1917 {
  1918     if (numkeys) {
  1919         *numkeys = (int) SDL_arraysize(KeyState);
  1920     }
  1921     return KeyState;
  1922 }
  1923 
  1924 
  1925 static int
  1926 EventFilter20to12(void *data, SDL_Event *event20)
  1927 {
  1928     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1929     SDL12_Event event12;
  1930     int x, y;
  1931 
  1932     SDL_assert(data == NULL);  /* currently unused. */
  1933 
  1934     SDL20_zero(event12);
  1935 
  1936     switch (event20->type)
  1937     {
  1938         case SDL_QUIT:
  1939             event12.type = SDL12_QUIT;
  1940             break;
  1941 
  1942         case SDL_WINDOWEVENT:
  1943             switch (event20->window.event)
  1944             {
  1945                 case SDL_WINDOWEVENT_CLOSE:
  1946                     event12.type = SDL12_QUIT;
  1947                     break;
  1948 
  1949                 case SDL_WINDOWEVENT_SHOWN:
  1950                 case SDL_WINDOWEVENT_EXPOSED:
  1951                     event12.type = SDL12_VIDEOEXPOSE;
  1952                     break;
  1953 
  1954                 case SDL_WINDOWEVENT_RESIZED:
  1955                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1956                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1957                     event12.type = SDL12_VIDEORESIZE;
  1958                     event12.resize.w = event20->window.data1;
  1959                     event12.resize.h = event20->window.data2;
  1960                     break;
  1961 
  1962                 case SDL_WINDOWEVENT_MINIMIZED:
  1963                     event12.type = SDL12_ACTIVEEVENT;
  1964                     event12.active.gain = 0;
  1965                     event12.active.state = SDL12_APPACTIVE;
  1966                     break;
  1967 
  1968                 case SDL_WINDOWEVENT_RESTORED:
  1969                     event12.type = SDL12_ACTIVEEVENT;
  1970                     event12.active.gain = 1;
  1971                     event12.active.state = SDL12_APPACTIVE;
  1972                     break;
  1973 
  1974                 case SDL_WINDOWEVENT_ENTER:
  1975                     event12.type = SDL12_ACTIVEEVENT;
  1976                     event12.active.gain = 1;
  1977                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1978                     break;
  1979 
  1980                 case SDL_WINDOWEVENT_LEAVE:
  1981                     event12.type = SDL12_ACTIVEEVENT;
  1982                     event12.active.gain = 0;
  1983                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1984                     break;
  1985 
  1986                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1987                     event12.type = SDL12_ACTIVEEVENT;
  1988                     event12.active.gain = 1;
  1989                     event12.active.state = SDL12_APPINPUTFOCUS;
  1990                     break;
  1991 
  1992                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1993                     event12.type = SDL12_ACTIVEEVENT;
  1994                     event12.active.gain = 0;
  1995                     event12.active.state = SDL12_APPINPUTFOCUS;
  1996                     break;
  1997             }
  1998             break;
  1999 
  2000         // !!! FIXME: this is sort of a mess to convert.
  2001         case SDL_SYSWMEVENT: FIXME("write me"); return 0;
  2002 
  2003         case SDL_KEYUP:
  2004         case SDL_KEYDOWN:
  2005             if (event20->key.repeat) {
  2006                 return 0;  /* ignore 2.0-style key repeat events */
  2007             }
  2008             event12.key.keysym.sym = Keysym20to12(event20->key.keysym.sym);
  2009             if (event12.key.keysym.sym == SDLK12_UNKNOWN) {
  2010                 return 0;  /* drop it if we can't map it */
  2011             }
  2012 
  2013             KeyState[event12.key.keysym.sym] = event20->key.state;
  2014 
  2015             event12.type = (event20->type == SDL_KEYDOWN) ? SDL12_KEYDOWN : SDL12_KEYUP;
  2016             event12.key.which = 0;
  2017             event12.key.state = event20->key.state;
  2018             event12.key.keysym.scancode = (event20->key.keysym.scancode < 256) ? (Uint8) event20->key.keysym.scancode : 0;
  2019             event12.key.keysym.mod = event20->key.keysym.mod;  /* these match up between 1.2 and 2.0! */
  2020             event12.key.keysym.unicode = 0;  FIXME("unicode");
  2021             break;
  2022 
  2023         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  2024         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  2025 
  2026         case SDL_MOUSEMOTION:
  2027         	event12.type = SDL12_MOUSEMOTION;
  2028             event12.motion.which = (Uint8) event20->motion.which;
  2029             event12.motion.state = event20->motion.state;
  2030             event12.motion.x = (Uint16) event20->motion.x;
  2031             event12.motion.y = (Uint16) event20->motion.y;
  2032             event12.motion.xrel = (Sint16) event20->motion.xrel;
  2033             event12.motion.yrel = (Sint16) event20->motion.yrel;
  2034             break;
  2035 
  2036         case SDL_MOUSEBUTTONDOWN:
  2037         	event12.type = SDL12_MOUSEBUTTONDOWN;
  2038             event12.button.which = (Uint8) event20->button.which;
  2039             event12.button.button = event20->button.button;
  2040             event12.button.state = event20->button.state;
  2041             event12.button.x = (Uint16) event20->button.x;
  2042             event12.button.y = (Uint16) event20->button.y;
  2043             break;
  2044 
  2045         case SDL_MOUSEBUTTONUP:
  2046         	event12.type = SDL12_MOUSEBUTTONUP;
  2047             event12.button.which = (Uint8) event20->button.which;
  2048             event12.button.button = event20->button.button;
  2049             event12.button.state = event20->button.state;
  2050             event12.button.x = (Uint16) event20->button.x;
  2051             event12.button.y = (Uint16) event20->button.y;
  2052             break;
  2053 
  2054         case SDL_MOUSEWHEEL:
  2055             if (event20->wheel.y == 0)
  2056                 break;  /* don't support horizontal wheels in 1.2. */
  2057 
  2058             event12.type = SDL12_MOUSEBUTTONDOWN;
  2059             event12.button.which = (Uint8) event20->wheel.which;
  2060             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  2061             event12.button.state = SDL_GetMouseState(&x, &y);
  2062             event12.button.x = (Uint16) x;
  2063             event12.button.y = (Uint16) y;
  2064             PushEventIfNotFiltered(&event12);
  2065 
  2066             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  2067             break;
  2068 
  2069         case SDL_JOYAXISMOTION:
  2070             event12.type = SDL12_JOYAXISMOTION;
  2071             event12.jaxis.which = (Uint8) event20->jaxis.which;
  2072             event12.jaxis.axis = event20->jaxis.axis;
  2073             event12.jaxis.value = event20->jaxis.value;
  2074             break;
  2075 
  2076         case SDL_JOYBALLMOTION:
  2077             event12.type = SDL12_JOYBALLMOTION;
  2078             event12.jball.which = (Uint8) event20->jball.which;
  2079             event12.jball.ball = event20->jball.ball;
  2080             event12.jball.xrel = event20->jball.xrel;
  2081             event12.jball.yrel = event20->jball.yrel;
  2082             break;
  2083 
  2084         case SDL_JOYHATMOTION:
  2085             event12.type = SDL12_JOYHATMOTION;
  2086             event12.jhat.which = (Uint8) event20->jhat.which;
  2087             event12.jhat.hat = event20->jhat.hat;
  2088             event12.jhat.value = event20->jhat.value;
  2089             break;
  2090 
  2091         case SDL_JOYBUTTONDOWN:
  2092             event12.type = SDL12_JOYBUTTONDOWN;
  2093             event12.jbutton.which = (Uint8) event20->jbutton.which;
  2094             event12.jbutton.button = event20->jbutton.button;
  2095             event12.jbutton.state = event20->jbutton.state;
  2096             break;
  2097 
  2098         case SDL_JOYBUTTONUP:
  2099             event12.type = SDL12_JOYBUTTONUP;
  2100             event12.jbutton.which = (Uint8) event20->jbutton.which;
  2101             event12.jbutton.button = event20->jbutton.button;
  2102             event12.jbutton.state = event20->jbutton.state;
  2103             break;
  2104 
  2105         //case SDL_JOYDEVICEADDED:
  2106         //case SDL_JOYDEVICEREMOVED:
  2107 	    //case SDL_CONTROLLERAXISMOTION:
  2108 	    //case SDL_CONTROLLERBUTTONDOWN:
  2109 	    //case SDL_CONTROLLERBUTTONUP:
  2110 	    //case SDL_CONTROLLERDEVICEADDED:
  2111 	    //case SDL_CONTROLLERDEVICEREMOVED:
  2112 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  2113         //case SDL_FINGERDOWN:
  2114         //case SDL_FINGERUP:
  2115         //case SDL_FINGERMOTION:
  2116         //case SDL_DOLLARGESTURE:
  2117         //case SDL_DOLLARRECORD:
  2118         //case SDL_MULTIGESTURE:
  2119         //case SDL_CLIPBOARDUPDATE:
  2120         //case SDL_DROPFILE:
  2121 
  2122         default:
  2123             return 0;  /* drop everything else. */
  2124     }
  2125 
  2126     PushEventIfNotFiltered(&event12);
  2127 
  2128     return 0;  /* always drop it from the 2.0 event queue. */
  2129 }
  2130 
  2131 DECLSPEC void SDLCALL
  2132 SDL_SetEventFilter(SDL12_EventFilter filter12)
  2133 {
  2134     /* We always have a filter installed, but will call the app's too. */
  2135     EventFilter12 = filter12;
  2136 }
  2137 
  2138 DECLSPEC SDL12_EventFilter SDLCALL
  2139 SDL_GetEventFilter(void)
  2140 {
  2141     return EventFilter12;
  2142 }
  2143 
  2144 
  2145 static SDL12_Rect *
  2146 Rect20to12(const SDL_Rect *rect20, SDL12_Rect *rect12)
  2147 {
  2148     rect12->x = (Sint16) rect20->x;
  2149     rect12->y = (Sint16) rect20->y;
  2150     rect12->w = (Uint16) rect20->w;
  2151     rect12->h = (Uint16) rect20->h;
  2152     return rect12;
  2153 }
  2154 
  2155 static SDL_Rect *
  2156 Rect12to20(const SDL12_Rect *rect12, SDL_Rect *rect20)
  2157 {
  2158     rect20->x = (int) rect12->x;
  2159     rect20->y = (int) rect12->y;
  2160     rect20->w = (int) rect12->w;
  2161     rect20->h = (int) rect12->h;
  2162     return rect20;
  2163 }
  2164 
  2165 static SDL12_Surface *
  2166 Surface20to12(SDL_Surface *surface20)
  2167 {
  2168     SDL12_Surface *surface12 = NULL;
  2169     SDL12_Palette *palette12 = NULL;
  2170     SDL12_PixelFormat *format12 = NULL;
  2171     Uint32 flags = 0;
  2172 
  2173     if (!surface20)
  2174         return NULL;
  2175 
  2176     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  2177     if (!surface12)
  2178         goto failed;
  2179 
  2180     if (surface20->format->palette) {
  2181         palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  2182         if (!palette12)
  2183             goto failed;
  2184     }
  2185 
  2186     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  2187     if (!format12)
  2188         goto failed;
  2189 
  2190     if (palette12) {
  2191         SDL20_zerop(palette12);
  2192         SDL_assert(surface20->format->palette);
  2193         palette12->ncolors = surface20->format->palette->ncolors;
  2194         palette12->colors = surface20->format->palette->colors;
  2195     }
  2196 
  2197     SDL20_zerop(format12);
  2198     format12->palette = palette12;
  2199     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  2200     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  2201     format12->Rloss = surface20->format->Rloss;
  2202     format12->Gloss = surface20->format->Gloss;
  2203     format12->Bloss = surface20->format->Bloss;
  2204     format12->Aloss = surface20->format->Aloss;
  2205     format12->Rshift = surface20->format->Rshift;
  2206     format12->Gshift = surface20->format->Gshift;
  2207     format12->Bshift = surface20->format->Bshift;
  2208     format12->Ashift = surface20->format->Ashift;
  2209     format12->Rmask = surface20->format->Rmask;
  2210     format12->Gmask = surface20->format->Gmask;
  2211     format12->Bmask = surface20->format->Bmask;
  2212     format12->Amask = surface20->format->Amask;
  2213 
  2214     if (SDL20_HasColorKey(surface20)) {
  2215         if (SDL20_GetColorKey(surface20, &format12->colorkey) == -1) {
  2216             format12->colorkey = 0;
  2217         } else {
  2218             surface12->flags |= SDL12_SRCCOLORKEY;
  2219         }
  2220     }
  2221 
  2222     if (SDL20_GetSurfaceAlphaMod(surface20, &format12->alpha) == -1) {
  2223         format12->alpha = 255;
  2224     }
  2225 
  2226     SDL_BlendMode blendmode = SDL_BLENDMODE_NONE;
  2227     if ((SDL20_GetSurfaceBlendMode(surface20, &blendmode) == 0) && (blendmode == SDL_BLENDMODE_BLEND)) {
  2228         surface12->flags |= SDL12_SRCALPHA;
  2229     }
  2230 
  2231     SDL20_zerop(surface12);
  2232     flags = surface20->flags;
  2233     flags &= ~SDL_SIMD_ALIGNED;  /* we don't need to map this to 1.2 */
  2234     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  2235     MAPSURFACEFLAGS(PREALLOC);
  2236     MAPSURFACEFLAGS(RLEACCEL);
  2237     /*MAPSURFACEFLAGS(DONTFREE);*/
  2238     #undef MAPSURFACEFLAGS
  2239     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  2240 
  2241     surface12->format = format12;
  2242     surface12->w = surface20->w;
  2243     surface12->h = surface20->h;
  2244     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  2245     surface12->pixels = surface20->pixels;
  2246     surface12->offset = 0;
  2247     surface12->surface20 = surface20;
  2248     Rect20to12(&surface20->clip_rect, &surface12->clip_rect);
  2249     surface12->refcount = surface20->refcount;
  2250 
  2251     return surface12;
  2252 
  2253 failed:
  2254     SDL20_free(surface12);
  2255     SDL20_free(palette12);
  2256     SDL20_free(format12);
  2257     return NULL;
  2258 }
  2259 
  2260 static void
  2261 SetPalette12ForMasks(SDL12_Surface *surface12, const Uint32 Rmask, const Uint32 Gmask, const Uint32 Bmask)
  2262 {
  2263     SDL12_PixelFormat *format12 = surface12->format;
  2264     if (format12->palette && (Rmask || Bmask || Gmask)) {
  2265         #define LOSSMASKSHIFTSETUP(t) { \
  2266             format12->t##shift = 0; \
  2267             format12->t##loss = 8; \
  2268             if (t##mask) { \
  2269                 Uint32 mask; \
  2270                 for (mask = t##mask; !(mask & 1); mask >>= 1) { \
  2271                     format12->t##shift++; \
  2272                 } \
  2273                 while (mask & 1) { \
  2274                     format12->t##loss--; \
  2275                     mask >>= 1; \
  2276                 } \
  2277             } \
  2278             format12->t##mask = t##mask; \
  2279         }
  2280         LOSSMASKSHIFTSETUP(R);
  2281         LOSSMASKSHIFTSETUP(G);
  2282         LOSSMASKSHIFTSETUP(B);
  2283         #undef LOSSMASSSHIFTSETUP
  2284         format12->Amask = 0;
  2285         format12->Ashift = 0;
  2286         format12->Aloss = 8;
  2287 
  2288         #define MASKSETUP(t) \
  2289             int t##w = 0, t##m = 0; \
  2290             if (t##mask) { \
  2291             t##w = 8 - format12->t##loss; \
  2292             for (int i = format12->t##loss; i > 0; i -= t##w) { \
  2293                 t##m |= 1 << i; \
  2294             } \
  2295         }
  2296         MASKSETUP(R);
  2297         MASKSETUP(G);
  2298         MASKSETUP(B);
  2299         #undef MASKSETUP
  2300 
  2301         const int ncolors = format12->palette->ncolors;
  2302         SDL_Color *color = format12->palette->colors;
  2303         for (int i = 0; i < ncolors; i++, color++) {
  2304             #define SETCOLOR(T, t) { \
  2305                 const int x = (i & T##mask) >> format12->T##shift; \
  2306                 color->t = (x << format12->T##loss) | ((x * T##m) >> T##w); \
  2307             }
  2308             SETCOLOR(R, r);
  2309             SETCOLOR(G, g);
  2310             SETCOLOR(B, b);
  2311             #undef SETCOLOR
  2312             color->a = 255;
  2313         }
  2314 
  2315         SDL_PixelFormat *format20 = surface12->surface20->format;
  2316         #define UPDATEFMT20(t) \
  2317             format20->t##mask = format12->t##mask; \
  2318             format20->t##loss = format12->t##loss; \
  2319             format20->t##shift = format12->t##shift;
  2320         UPDATEFMT20(R);
  2321         UPDATEFMT20(G);
  2322         UPDATEFMT20(B);
  2323         UPDATEFMT20(A);
  2324         #undef UPDATEFMT20
  2325     }
  2326 }
  2327 
  2328 DECLSPEC SDL12_Surface * SDLCALL
  2329 SDL_CreateRGBSurface(Uint32 flags12, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  2330 {
  2331     // SDL 1.2 checks this.
  2332     if ((width >= 16384) || (height >= 65536)) {
  2333         SDL20_SetError("Width or height is too large");
  2334         return NULL;
  2335     }
  2336 
  2337     SDL_Surface *surface20;
  2338     if (depth == 8) {  // don't pass masks to SDL2 for 8-bit surfaces, it'll cause problems.
  2339         surface20 = SDL20_CreateRGBSurface(0, width, height, depth, 0, 0, 0, 0);
  2340     } else {
  2341         surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  2342     }
  2343 
  2344     SDL12_Surface *surface12 = Surface20to12(surface20);
  2345     if (!surface12) {
  2346         SDL20_FreeSurface(surface20);
  2347         return NULL;
  2348     }
  2349 
  2350     SDL_assert((surface12->flags & ~(SDL12_SRCCOLORKEY|SDL12_SRCALPHA)) == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  2351 
  2352     SetPalette12ForMasks(surface12, Rmask, Gmask, Bmask);
  2353 
  2354     if (flags12 & SDL12_SRCALPHA) {
  2355         surface12->flags |= SDL12_SRCALPHA;
  2356         SDL20_SetSurfaceBlendMode(surface20, SDL_BLENDMODE_BLEND);
  2357     }
  2358 
  2359     return surface12;
  2360 }
  2361 
  2362 DECLSPEC SDL12_Surface * SDLCALL
  2363 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  2364 {
  2365     if ((width >= 16384) || (height >= 65536)) {
  2366         SDL20_SetError("Width or height is too large");
  2367         return NULL;
  2368     }
  2369 
  2370     SDL_Surface *surface20;
  2371     if (depth == 8) {  // don't pass masks to SDL2 for 8-bit surfaces, it'll cause problems.
  2372         surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, 0, 0, 0, 0);
  2373     } else {
  2374         surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  2375     }
  2376 
  2377     SDL12_Surface *surface12 = Surface20to12(surface20);
  2378     if (!surface12) {
  2379         SDL20_FreeSurface(surface20);
  2380         return NULL;
  2381     }
  2382 
  2383     SDL_assert((surface12->flags & ~(SDL12_SRCCOLORKEY|SDL12_SRCALPHA)) == SDL12_PREALLOC);  // should _only_ have prealloc.
  2384 
  2385     SetPalette12ForMasks(surface12, Rmask, Gmask, Bmask);
  2386 
  2387     return surface12;
  2388 }
  2389 
  2390 DECLSPEC void SDLCALL
  2391 SDL_FreeSurface(SDL12_Surface *surface12)
  2392 {
  2393     if (surface12 && (surface12 != VideoSurface12)) {
  2394         SDL20_FreeSurface(surface12->surface20);
  2395         if (surface12->format) {
  2396             SDL20_free(surface12->format->palette);
  2397             SDL20_free(surface12->format);
  2398         }
  2399         SDL20_free(surface12);
  2400     }
  2401 }
  2402 
  2403 DECLSPEC void SDLCALL
  2404 SDL_GetClipRect(SDL12_Surface *surface12, SDL12_Rect *rect)
  2405 {
  2406     if (surface12 && rect) {
  2407         SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL12_Rect));
  2408     }
  2409 }
  2410 
  2411 DECLSPEC SDL_bool SDLCALL
  2412 SDL_SetClipRect(SDL12_Surface *surface12, const SDL12_Rect *rect12)
  2413 {
  2414     SDL_bool retval = SDL_FALSE;
  2415     if (surface12)
  2416     {
  2417         SDL_Rect rect20;
  2418         retval = SDL20_SetClipRect(surface12->surface20, rect12 ? Rect12to20(rect12, &rect20) : NULL);
  2419         SDL20_GetClipRect(surface12->surface20, &rect20);
  2420         Rect20to12(&rect20, &surface12->clip_rect);
  2421     }
  2422     return retval;
  2423 }
  2424 
  2425 DECLSPEC int SDLCALL
  2426 SDL_FillRect(SDL12_Surface *dst, SDL12_Rect *dstrect12, Uint32 color)
  2427 {
  2428     SDL_Rect dstrect20;
  2429     const int retval = SDL20_FillRect(dst->surface20, dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL, color);
  2430     if (retval != -1)
  2431     {
  2432         if (dstrect12) {  /* 1.2 stores the clip intersection in dstrect */
  2433             SDL_Rect intersected20;
  2434             SDL20_IntersectRect(&dstrect20, &dst->surface20->clip_rect, &intersected20);
  2435             Rect20to12(&intersected20, dstrect12);
  2436         }
  2437     }
  2438     return retval;
  2439 }
  2440 
  2441 DECLSPEC Uint32 SDLCALL
  2442 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  2443 {
  2444     /* This is probably way slower than apps expect. */
  2445     SDL_PixelFormat format20;
  2446     SDL_Palette palette20;
  2447     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  2448 }
  2449 
  2450 DECLSPEC Uint32 SDLCALL
  2451 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  2452 {
  2453     /* This is probably way slower than apps expect. */
  2454     SDL_PixelFormat format20;
  2455     SDL_Palette palette20;
  2456     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  2457 }
  2458 
  2459 DECLSPEC void SDLCALL
  2460 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  2461 {
  2462     /* This is probably way slower than apps expect. */
  2463     SDL_PixelFormat format20;
  2464     SDL_Palette palette20;
  2465     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  2466 }
  2467 
  2468 DECLSPEC void SDLCALL
  2469 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  2470 {
  2471     /* This is probably way slower than apps expect. */
  2472     SDL_PixelFormat format20;
  2473     SDL_Palette palette20;
  2474     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  2475 }
  2476 
  2477 DECLSPEC const SDL12_VideoInfo * SDLCALL
  2478 SDL_GetVideoInfo(void)
  2479 {
  2480     return VideoInfo12.vfmt ? &VideoInfo12 : NULL;
  2481 }
  2482 
  2483 DECLSPEC int SDLCALL
  2484 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  2485 {
  2486     int i, nummodes, actual_bpp = 0;
  2487 
  2488     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  2489         return 0;
  2490     }
  2491 
  2492     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  2493         SDL_DisplayMode mode;
  2494         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  2495         return SDL_BITSPERPIXEL(mode.format);
  2496     }
  2497 
  2498     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  2499     for (i = 0; i < nummodes; ++i) {
  2500         SDL_DisplayMode mode;
  2501         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  2502         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  2503             if (!mode.format) {
  2504                 return bpp;
  2505             }
  2506             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  2507                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  2508             }
  2509         }
  2510     }
  2511     return actual_bpp;
  2512 }
  2513 
  2514 DECLSPEC SDL12_Rect ** SDLCALL
  2515 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  2516 {
  2517     Uint32 fmt;
  2518     int i;
  2519 
  2520     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  2521         SDL20_SetError("Video subsystem not initialized");
  2522         return NULL;
  2523     }
  2524 
  2525     if ((!format12) && (!VideoInfo12.vfmt)) {
  2526         SDL20_SetError("No pixel format specified");
  2527         return NULL;
  2528     }
  2529 
  2530     if (!(flags & SDL12_FULLSCREEN)) {
  2531         return (SDL12_Rect **) (-1);  /* any resolution is fine. */
  2532     }
  2533 
  2534     if (format12 && (format12 != VideoInfo12.vfmt)) {
  2535         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  2536     } else {
  2537         fmt = VideoInfoVfmt20->format;
  2538     }
  2539 
  2540     for (i = 0; i < VideoModesCount; i++) {
  2541         VideoModeList *modes = &VideoModes[i];
  2542         if (modes->format == fmt) {
  2543             return modes->modes12;
  2544         }
  2545     }
  2546 
  2547     SDL20_SetError("No modes support requested pixel format");
  2548     return NULL;
  2549 }
  2550 
  2551 DECLSPEC void SDLCALL
  2552 SDL_FreeCursor(SDL12_Cursor *cursor12)
  2553 {
  2554     if (cursor12) {
  2555         if (cursor12->wm_cursor)
  2556             SDL20_FreeCursor(cursor12->wm_cursor);
  2557         SDL20_free(cursor12->data);
  2558         SDL20_free(cursor12->mask);
  2559         SDL20_free(cursor12);
  2560     }
  2561 }
  2562 
  2563 DECLSPEC SDL12_Cursor * SDLCALL
  2564 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  2565 {
  2566     const size_t datasize = h * (w / 8);
  2567     SDL_Cursor *cursor20 = NULL;
  2568     SDL12_Cursor *retval = NULL;
  2569 
  2570     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  2571     if (!retval)
  2572         goto outofmem;
  2573 
  2574     SDL20_zerop(retval);
  2575 
  2576     retval->data = (Uint8 *) SDL20_malloc(datasize);
  2577     if (!retval->data)
  2578         goto outofmem;
  2579 
  2580     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  2581     if (!retval->mask)
  2582         goto outofmem;
  2583 
  2584     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  2585     if (!cursor20)
  2586         goto failed;
  2587 
  2588     retval->area.w = w;
  2589     retval->area.h = h;
  2590     retval->hot_x = hot_x;
  2591     retval->hot_y = hot_y;
  2592     retval->wm_cursor = cursor20;
  2593     /* we always leave retval->save as null pointers. */
  2594 
  2595     SDL20_memcpy(retval->data, data, datasize);
  2596     SDL20_memcpy(retval->mask, mask, datasize);
  2597 
  2598     return retval;
  2599 
  2600 outofmem:
  2601     SDL20_OutOfMemory();
  2602 
  2603 failed:
  2604     SDL_FreeCursor(retval);
  2605     return NULL;
  2606 }
  2607 
  2608 DECLSPEC void SDLCALL
  2609 SDL_SetCursor(SDL12_Cursor *cursor)
  2610 {
  2611     CurrentCursor12 = cursor;
  2612     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  2613 }
  2614 
  2615 DECLSPEC SDL12_Cursor * SDLCALL
  2616 SDL_GetCursor(void)
  2617 {
  2618     return CurrentCursor12;
  2619 }
  2620 
  2621 static void
  2622 GetEnvironmentWindowPosition(int *x, int *y)
  2623 {
  2624     int display = VideoDisplayIndex;
  2625     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  2626     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  2627     if (window) {
  2628         if (SDL20_strcmp(window, "center") == 0) {
  2629             center = window;
  2630         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  2631             return;
  2632         }
  2633     }
  2634 
  2635     if (center) {
  2636         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  2637         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  2638     }
  2639 }
  2640 
  2641 static void
  2642 SetupScreenSaver(const int flags12)
  2643 {
  2644     const char *env;
  2645     SDL_bool allow_screensaver;
  2646 
  2647     /* Allow environment override of screensaver disable */
  2648     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  2649     if (env) {
  2650         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  2651     } else if (flags12 & SDL12_FULLSCREEN) {
  2652         allow_screensaver = SDL_FALSE;
  2653     } else {
  2654         allow_screensaver = SDL_TRUE;
  2655     }
  2656     if (allow_screensaver) {
  2657         SDL20_EnableScreenSaver();
  2658     } else {
  2659         SDL20_DisableScreenSaver();
  2660     }
  2661 }
  2662 
  2663 
  2664 static SDL12_Surface *
  2665 EndVidModeCreate(void)
  2666 {
  2667     if (VideoTexture20) {
  2668         SDL20_DestroyTexture(VideoTexture20);
  2669         VideoTexture20 = NULL;
  2670     }
  2671     if (VideoRenderer20) {
  2672         SDL20_DestroyRenderer(VideoRenderer20);
  2673         VideoRenderer20 = NULL;
  2674     }
  2675     if (VideoGLContext20) {
  2676         SDL20_GL_MakeCurrent(NULL, NULL);
  2677         SDL20_GL_DeleteContext(VideoGLContext20);
  2678         VideoGLContext20 = NULL;
  2679     }
  2680     if (VideoWindow20) {
  2681         SDL20_DestroyWindow(VideoWindow20);
  2682         VideoWindow20 = NULL;
  2683     }
  2684     if (VideoSurface12) {
  2685         SDL20_free(VideoSurface12->pixels);
  2686         VideoSurface12->pixels = NULL;
  2687         SDL_FreeSurface(VideoSurface12);
  2688         VideoSurface12 = NULL;
  2689     }
  2690     if (VideoConvertSurface20) {
  2691         SDL20_FreeSurface(VideoConvertSurface20);
  2692         VideoConvertSurface20 = NULL;
  2693     }
  2694     return NULL;
  2695 }
  2696 
  2697 
  2698 static SDL12_Surface *
  2699 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  2700 {
  2701     Uint32 rmask, gmask, bmask, amask;
  2702     int bpp;
  2703     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  2704         return NULL;
  2705     }
  2706     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  2707 }
  2708 
  2709 static SDL_Surface *
  2710 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  2711 {
  2712     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  2713     if (surface20) {
  2714         surface20->flags |= SDL_PREALLOC;
  2715         surface20->pixels = NULL;
  2716         surface20->w = width;
  2717         surface20->h = height;
  2718         surface20->pitch = 0;
  2719         SDL20_SetClipRect(surface20, NULL);
  2720     }
  2721     return surface20;
  2722 }
  2723 
  2724 
  2725 DECLSPEC SDL12_Surface * SDLCALL
  2726 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  2727 {
  2728     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  2729     SDL_DisplayMode dmode;
  2730     Uint32 fullscreen_flags20 = 0;
  2731     Uint32 appfmt;
  2732 
  2733     /* SDL_SetVideoMode() implicitly inits if necessary. */
  2734     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  2735         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  2736             return NULL;
  2737         }
  2738     }
  2739 
  2740     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  2741         FIXME("No OPENGLBLIT support at the moment");
  2742         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  2743         return NULL;
  2744     }
  2745 
  2746     FIXME("handle SDL_ANYFORMAT");
  2747 
  2748     if ((width < 0) || (height < 0)) {
  2749         SDL20_SetError("Invalid width or height");
  2750         return NULL;
  2751     }
  2752 
  2753     FIXME("There's an environment variable to choose a display");
  2754     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  2755         return NULL;
  2756     }
  2757 
  2758     if (width == 0) {
  2759         width = dmode.w;
  2760     }
  2761 
  2762     if (height == 0) {
  2763         height = dmode.h;
  2764     }
  2765 
  2766     if (bpp == 0) {
  2767         bpp = SDL_BITSPERPIXEL(dmode.format);
  2768     }
  2769 
  2770     switch (bpp) {
  2771         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  2772         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  2773         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  2774         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  2775         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  2776     }
  2777 
  2778     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  2779 
  2780     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  2781     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  2782 
  2783     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  2784         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  2785     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  2786         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  2787     } else if (VideoGLContext20) {
  2788         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  2789         SDL20_GL_MakeCurrent(NULL, NULL);
  2790         SDL20_GL_DeleteContext(VideoGLContext20);
  2791         VideoGLContext20 = NULL;
  2792     }
  2793 
  2794     if (flags12 & SDL12_FULLSCREEN) {
  2795         // OpenGL tries to force the real resolution requested, but for
  2796         //  software rendering, we're just going to push it off onto the
  2797         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  2798         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  2799         if (((flags12 & SDL12_OPENGL) == 0) || ((dmode.w == width) && (dmode.h == height))) {
  2800             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  2801         } else {
  2802             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  2803         }
  2804     }
  2805 
  2806     if (!VideoWindow20) {  /* create it */
  2807         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  2808         Uint32 flags20 = fullscreen_flags20;
  2809         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  2810         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  2811         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  2812 
  2813         /* most platforms didn't check these environment variables, but the major
  2814            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  2815         GetEnvironmentWindowPosition(&x, &y);
  2816 
  2817         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  2818         if (!VideoWindow20) {
  2819             return EndVidModeCreate();
  2820         }
  2821         if (VideoIcon20) {
  2822             SDL20_SetWindowIcon(VideoWindow20, VideoIcon20);
  2823         }
  2824     } else {  /* resize it */
  2825         SDL20_SetWindowSize(VideoWindow20, width, height);
  2826         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  2827         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  2828         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  2829     }
  2830 
  2831     if (VideoSurface12) {
  2832         SDL20_free(VideoSurface12->pixels);
  2833     } else {
  2834         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  2835         if (!VideoSurface12) {
  2836             return EndVidModeCreate();
  2837         }
  2838     }
  2839 
  2840     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  2841     VideoSurface12->flags |= SDL12_PREALLOC;
  2842     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  2843     VideoSurface12->w = VideoSurface12->surface20->w = width;
  2844     VideoSurface12->h = VideoSurface12->surface20->h = height;
  2845     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  2846     SDL_SetClipRect(VideoSurface12, NULL);
  2847 
  2848     if (flags12 & SDL12_FULLSCREEN) {
  2849         VideoSurface12->flags |= SDL12_FULLSCREEN;
  2850     } else {
  2851         VideoSurface12->flags &= ~SDL12_FULLSCREEN;
  2852     }
  2853 
  2854     if (flags12 & SDL12_OPENGL) {
  2855         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  2856         SDL_assert(!VideoRenderer20);
  2857         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  2858         if (!VideoGLContext20) {
  2859             return EndVidModeCreate();
  2860         }
  2861 
  2862         VideoSurface12->flags |= SDL12_OPENGL;
  2863     } else {
  2864         /* always use a renderer for non-OpenGL windows. */
  2865         SDL_RendererInfo rinfo;
  2866         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  2867         if (!VideoRenderer20) {
  2868             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  2869         }
  2870         if (!VideoRenderer20) {
  2871             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED);
  2872         }
  2873         if (!VideoRenderer20) {
  2874             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  2875         }
  2876         if (!VideoRenderer20) {
  2877             return EndVidModeCreate();
  2878         }
  2879 
  2880         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  2881         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  2882         SDL20_RenderClear(VideoRenderer20);
  2883         SDL20_RenderPresent(VideoRenderer20);
  2884         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  2885 
  2886         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  2887             return EndVidModeCreate();
  2888         }
  2889 
  2890         if (VideoTexture20) {
  2891             SDL20_DestroyTexture(VideoTexture20);
  2892         }
  2893 
  2894         if (VideoConvertSurface20) {
  2895             SDL20_FreeSurface(VideoConvertSurface20);
  2896             VideoConvertSurface20 = NULL;
  2897         }
  2898 
  2899         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  2900         if (!VideoTexture20) {
  2901             return EndVidModeCreate();
  2902         }
  2903 
  2904         if (rinfo.texture_formats[0] != appfmt) {
  2905             /* need to convert between app's format and texture format */
  2906             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  2907             if (!VideoConvertSurface20) {
  2908                 return EndVidModeCreate();
  2909             }
  2910         }
  2911 
  2912         VideoSurface12->flags &= ~SDL12_OPENGL;
  2913         VideoSurface12->flags |= SDL12_DOUBLEBUF;
  2914         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  2915         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  2916         if (!VideoSurface12->pixels) {
  2917             SDL20_OutOfMemory();
  2918             return EndVidModeCreate();
  2919         }
  2920 
  2921         /* fill in the same default palette that SDL 1.2 does... */
  2922         if (VideoSurface12->format->BitsPerPixel == 8) {
  2923             int i;
  2924             SDL_Color *color = VideoSurface12->format->palette->colors;
  2925             for (i = 0; i < 256; i++, color++) {
  2926                 { const int x = i & 0xe0; color->r = x | x >> 3 | x >> 6; }
  2927                 { const int x = (i << 3) & 0xe0; color->g = x | x >> 3 | x >> 6; }
  2928                 { const int x = (i & 0x3) | ((i & 0x3) << 2); color->b = x | x << 4; }
  2929                 color->a = 255;
  2930             }
  2931         }
  2932     }
  2933 
  2934     SDL20_RaiseWindow(VideoWindow20);
  2935 
  2936     FIXME("setup screen saver");
  2937 
  2938     VideoSurfacePresentTicks = 0;
  2939     VideoSurfaceLastPresentTicks = 0;
  2940 
  2941     return VideoSurface12;
  2942 }
  2943 
  2944 DECLSPEC SDL12_Surface * SDLCALL
  2945 SDL_GetVideoSurface(void)
  2946 {
  2947     return VideoSurface12;
  2948 }
  2949 
  2950 static int
  2951 SaveDestAlpha(SDL12_Surface *src12, SDL12_Surface *dst12, Uint8 **retval)
  2952 {
  2953     FIXME("This should only save the dst rect in use");
  2954 
  2955     /* The 1.2 docs say this:
  2956      * RGBA->RGBA:
  2957      *     SDL_SRCALPHA set:
  2958      * 	alpha-blend (using the source alpha channel) the RGB values;
  2959      * 	leave destination alpha untouched. [Note: is this correct?]
  2960      *
  2961      * In SDL2, we change the destination alpha. We have to save it off in this case, which sucks.
  2962      */
  2963     Uint8 *dstalpha = NULL;
  2964     const SDL_bool save_dstalpha = ((src12->flags & SDL12_SRCALPHA) && dst12->format->Amask && ((src12->format->alpha != 255) || src12->format->Amask)) ? SDL_TRUE : SDL_FALSE;
  2965     if (save_dstalpha) {
  2966         const int w = dst12->w;
  2967         const int h = dst12->h;
  2968         dstalpha = (Uint8 *) SDL_malloc(w * h);
  2969         if (!dstalpha) {
  2970             *retval = NULL;
  2971             return SDL20_OutOfMemory();
  2972         }
  2973 
  2974         Uint8 *dptr = dstalpha;
  2975         const Uint32 amask = dst12->format->Amask;
  2976         const Uint32 ashift = dst12->format->Ashift;
  2977         const Uint16 pitch = dst12->pitch;
  2978         if ((amask == 0xFF) || (amask == 0xFF00) || (amask == 0xFF0000) ||(amask == 0xFF000000)) {
  2979             FIXME("this could be SIMD'd");
  2980         }
  2981         if (dst12->format->BytesPerPixel == 2) {
  2982             const Uint16 *sptr = (const Uint16 *) dst12->pixels;
  2983             for (int y = 0; y < h; y++) {
  2984                 for (int x = 0; x < w; x++) {
  2985                     *(dptr++) = (Uint8) ((sptr[x] & amask) >> ashift);
  2986                 }
  2987                 sptr = (Uint16 *) (((Uint8 *) sptr) + pitch);
  2988             }
  2989         } else if (dst12->format->BytesPerPixel == 4) {
  2990             const Uint32 *sptr = (const Uint32 *) dst12->pixels;
  2991             for (int y = 0; y < h; y++) {
  2992                 for (int x = 0; x < w; x++) {
  2993                     *(dptr++) = (Uint8) ((sptr[x] & amask) >> ashift);
  2994                 }
  2995                 sptr = (Uint32 *) (((Uint8 *) sptr) + pitch);
  2996             }
  2997         } else {
  2998             FIXME("Unhandled dest alpha");
  2999         }
  3000     }
  3001 
  3002     *retval = dstalpha;
  3003     return 0;
  3004 }
  3005 
  3006 static void
  3007 RestoreDestAlpha(SDL12_Surface *dst12, Uint8 *dstalpha)
  3008 {
  3009     if (dstalpha) {
  3010         const int w = dst12->w;
  3011         const int h = dst12->h;
  3012         const Uint8 *sptr = dstalpha;
  3013         const Uint32 amask = dst12->format->Amask;
  3014         const Uint32 ashift = dst12->format->Ashift;
  3015         const Uint16 pitch = dst12->pitch;
  3016         if ((amask == 0xFF) || (amask == 0xFF00) || (amask == 0xFF0000) ||(amask == 0xFF000000)) {
  3017             FIXME("this could be SIMD'd");
  3018         }
  3019         if (dst12->format->BytesPerPixel == 2) {
  3020             Uint16 *dptr = (Uint16 *) dst12->pixels;
  3021             for (int y = 0; y < h; y++) {
  3022                 for (int x = 0; x < w; x++) {
  3023                     dptr[x] = (Uint16) ((dptr[x] & ~amask) | ((((Uint16) *(sptr++)) << ashift) & amask));
  3024                 }
  3025                 dptr = (Uint16 *) (((Uint8 *) dptr) + pitch);
  3026             }
  3027         } else if (dst12->format->BytesPerPixel == 4) {
  3028             Uint32 *dptr = (Uint32 *) dst12->pixels;
  3029             for (int y = 0; y < h; y++) {
  3030                 for (int x = 0; x < w; x++) {
  3031                     dptr[x] = (dptr[x] & ~amask) | ((((Uint32) *(sptr++)) << ashift) & amask);
  3032                 }
  3033                 dptr = (Uint32 *) (((Uint8 *) dptr) + pitch);
  3034             }
  3035         } else {
  3036             FIXME("Unhandled dest alpha");
  3037         }
  3038         SDL_free(dstalpha);
  3039     }
  3040 }
  3041 
  3042 DECLSPEC int SDLCALL
  3043 SDL_UpperBlit(SDL12_Surface *src12, SDL12_Rect *srcrect12, SDL12_Surface *dst12, SDL12_Rect *dstrect12)
  3044 {
  3045     Uint8 *dstalpha;
  3046     if (SaveDestAlpha(src12, dst12, &dstalpha) < 0) {
  3047         return -1;
  3048     }
  3049 
  3050     SDL_Rect srcrect20, dstrect20;
  3051     const int retval = SDL20_UpperBlit(src12->surface20,
  3052                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  3053                                        dst12->surface20,
  3054                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  3055 
  3056     RestoreDestAlpha(dst12, dstalpha);
  3057 
  3058     if (srcrect12) {
  3059         Rect20to12(&srcrect20, srcrect12);
  3060     }
  3061 
  3062     if (dstrect12) {
  3063         Rect20to12(&dstrect20, dstrect12);
  3064     }
  3065 
  3066     return retval;
  3067 }
  3068 
  3069 DECLSPEC int SDLCALL
  3070 SDL_LowerBlit(SDL12_Surface *src12, SDL12_Rect *srcrect12, SDL12_Surface *dst12, SDL12_Rect *dstrect12)
  3071 {
  3072     Uint8 *dstalpha;
  3073     if (SaveDestAlpha(src12, dst12, &dstalpha) < 0) {
  3074         return -1;
  3075     }
  3076 
  3077     SDL_Rect srcrect20, dstrect20;
  3078     const int retval = SDL20_LowerBlit(src12->surface20,
  3079                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  3080                                        dst12->surface20,
  3081                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  3082 
  3083     RestoreDestAlpha(dst12, dstalpha);
  3084 
  3085     if (srcrect12) {
  3086         Rect20to12(&srcrect20, srcrect12);
  3087     }
  3088 
  3089     if (srcrect12) {
  3090         Rect20to12(&dstrect20, dstrect12);
  3091     }
  3092 
  3093     return retval;
  3094 }
  3095 
  3096 DECLSPEC int SDLCALL
  3097 SDL_SetAlpha(SDL12_Surface *surface12, Uint32 flags12, Uint8 value)
  3098 {
  3099     const SDL_bool addkey = (flags12 & SDL12_SRCALPHA) ? SDL_TRUE : SDL_FALSE;
  3100     const int retval = SDL20_SetSurfaceAlphaMod(surface12->surface20, addkey ? value : 255);
  3101     if (SDL20_GetSurfaceAlphaMod(surface12->surface20, &surface12->format->alpha) < 0) {
  3102         surface12->format->alpha = 255;
  3103     }
  3104     FIXME("Should this set SDL12_SRCALPHA on the surface?");
  3105     return retval;
  3106 }
  3107 
  3108 DECLSPEC int SDLCALL
  3109 SDL_LockSurface(SDL12_Surface *surface12)
  3110 {
  3111     const int retval = SDL20_LockSurface(surface12->surface20);
  3112     surface12->pixels = surface12->surface20->pixels;
  3113     surface12->pitch = surface12->surface20->pitch;
  3114     return retval;
  3115 }
  3116 
  3117 DECLSPEC void SDLCALL
  3118 SDL_UnlockSurface(SDL12_Surface *surface12)
  3119 {
  3120     SDL20_UnlockSurface(surface12->surface20);
  3121     surface12->pixels = surface12->surface20->pixels;
  3122     surface12->pitch = surface12->surface20->pitch;
  3123 }
  3124 
  3125 DECLSPEC SDL12_Surface * SDLCALL
  3126 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
  3127 {
  3128     Uint32 flags20 = 0;
  3129     SDL_PixelFormat format20;
  3130     SDL_Palette palette20;
  3131     SDL_Surface *surface20;
  3132     SDL12_Surface *retval = NULL;
  3133 
  3134     if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
  3135     if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
  3136 
  3137     surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
  3138     if (surface20) {
  3139         retval = Surface20to12(surface20);
  3140         if (!retval) {
  3141             SDL20_FreeSurface(surface20);
  3142         } else {
  3143             if (flags12 & SDL12_SRCALPHA) {
  3144                 SDL20_SetSurfaceBlendMode(surface20, SDL_BLENDMODE_BLEND);
  3145                 retval->flags |= SDL12_SRCALPHA;
  3146             }
  3147         }
  3148     }
  3149     return retval;
  3150 }
  3151 
  3152 DECLSPEC SDL12_Surface * SDLCALL
  3153 SDL_DisplayFormat(SDL12_Surface *surface12)
  3154 {
  3155     const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
  3156     return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
  3157 }
  3158 
  3159 DECLSPEC SDL12_Surface * SDLCALL
  3160 SDL_DisplayFormatAlpha(SDL12_Surface *surface12)
  3161 {
  3162     return SDL_DisplayFormat(surface12);
  3163 }
  3164 
  3165 static void
  3166 PresentScreen(void)
  3167 {
  3168     void *pixels = NULL;
  3169     int pitch = 0;
  3170 
  3171     SDL_assert(VideoSurface12 != NULL);
  3172 
  3173     if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
  3174         return;  /* oh well */
  3175     }
  3176 
  3177     FIXME("Maybe lock texture always, until present, if no conversion needed?");
  3178     if (VideoConvertSurface20) {
  3179         VideoConvertSurface20->pixels = pixels;
  3180         VideoConvertSurface20->pitch = pitch;
  3181         SDL20_UpperBlit(VideoSurface12->surface20, NULL, VideoConvertSurface20, NULL);
  3182         VideoConvertSurface20->pixels = NULL;
  3183         VideoConvertSurface20->pitch = 0;
  3184     } else if (pitch == VideoSurface12->pitch) {
  3185         SDL_memcpy(pixels, VideoSurface12->pixels, pitch * VideoSurface12->h);
  3186     } else {
  3187         const int srcpitch = VideoSurface12->pitch;
  3188         const int cpy = SDL_min(srcpitch, pitch);
  3189         const int h = VideoSurface12->h;
  3190         char *dst = (char *) pixels;
  3191         char *src = (char *) VideoSurface12->pixels;
  3192         for (int i = 0; i < h; i++) {
  3193             SDL_memcpy(dst, src, cpy);
  3194             src += srcpitch;
  3195             dst += pitch;
  3196         }
  3197     }
  3198 
  3199     SDL20_UnlockTexture(VideoTexture20);
  3200     SDL20_RenderCopy(VideoRenderer20, VideoTexture20, NULL, NULL);
  3201     SDL20_RenderPresent(VideoRenderer20);
  3202     VideoSurfaceLastPresentTicks = SDL20_GetTicks();
  3203     VideoSurfacePresentTicks = 0;
  3204 }
  3205 
  3206 DECLSPEC void SDLCALL
  3207 SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
  3208 {
  3209     /* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
  3210     /* (UpdateRect, singular, does...) */
  3211     if (surface12->flags & SDL12_OPENGL) {
  3212         SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  3213         return;
  3214     }
  3215 
  3216     // everything else is marked SDL12_DOUBLEBUF and SHOULD BE a no-op here,
  3217     //  but in practice most apps never got a double-buffered surface and
  3218     //  don't handle it correctly, so we have to work around it.
  3219     if (surface12 == VideoSurface12) {
  3220         SDL_bool whole_screen = SDL_FALSE;
  3221         if (numrects == 1) {
  3222             const SDL12_Rect *r = rects12;
  3223             if (!r->x && !r->y && !r->w && !r->h) {
  3224                 whole_screen = SDL_TRUE;
  3225             } else if (!r->x && !r->y && (r->w == surface12->w) && (r->h == surface12->h)) {
  3226                 whole_screen = SDL_TRUE;
  3227             }
  3228         }
  3229                 
  3230         if (whole_screen) {  
  3231             PresentScreen();  // flip it now.
  3232         } else {
  3233             VideoSurfacePresentTicks = VideoSurfaceLastPresentTicks + 15;  // flip it later.
  3234         }
  3235     }
  3236 }
  3237 
  3238 DECLSPEC void SDLCALL
  3239 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  3240 {
  3241     if (screen12) {
  3242         SDL12_Rect rect12;
  3243         rect12.x = (Sint16) x;
  3244         rect12.y = (Sint16) y;
  3245         rect12.w = (Uint16) (w ? w : screen12->w);
  3246         rect12.h = (Uint16) (h ? h : screen12->h);
  3247         SDL_UpdateRects(screen12, 1, &rect12);
  3248     }
  3249 }
  3250 
  3251 DECLSPEC int SDLCALL
  3252 SDL_Flip(SDL12_Surface *surface12)
  3253 {
  3254     if (surface12->flags & SDL12_OPENGL) {
  3255         return SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  3256     }
  3257 
  3258     if (surface12 == VideoSurface12) {
  3259         PresentScreen();
  3260     }
  3261 
  3262     return 0;
  3263 }
  3264 
  3265 DECLSPEC void SDLCALL
  3266 SDL_PumpEvents(void)
  3267 {
  3268     // If the app is doing dirty rectangles, we set a flag and present the
  3269     //  screen surface when they pump for new events if we're close to 60Hz,
  3270     //  which we consider a sign that they are done rendering for the current
  3271     //  frame and it would make sense to send it to the screen.
  3272     if (VideoSurfacePresentTicks && SDL_TICKS_PASSED(SDL20_GetTicks(), VideoSurfacePresentTicks)) {
  3273         PresentScreen();
  3274     }
  3275     SDL20_PumpEvents();
  3276 }
  3277 
  3278 DECLSPEC void SDLCALL
  3279 SDL_WM_SetCaption(const char *title, const char *icon)
  3280 {
  3281     if (WindowTitle) {
  3282         SDL20_free(WindowTitle);
  3283     }
  3284     if (WindowIconTitle) {
  3285         SDL20_free(WindowIconTitle);
  3286     }
  3287     WindowTitle = title ? SDL_strdup(title) : NULL;
  3288     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  3289     if (VideoWindow20) {
  3290         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  3291     }
  3292 }
  3293 
  3294 DECLSPEC void SDLCALL
  3295 SDL_WM_GetCaption(const char **title, const char **icon)
  3296 {
  3297     if (title) {
  3298         *title = WindowTitle;
  3299     }
  3300     if (icon) {
  3301         *icon = WindowIconTitle;
  3302     }
  3303 }
  3304 
  3305 DECLSPEC void SDLCALL
  3306 SDL_WM_SetIcon(SDL12_Surface *icon12, Uint8 *mask)
  3307 {
  3308         if (VideoWindow20) {
  3309             SDL20_SetWindowIcon(VideoWindow20, icon12->surface20);
  3310 
  3311         }
  3312 return;
  3313 
  3314     // take the mask and zero out those alpha values.
  3315     SDL_BlendMode blendmode = SDL_BLENDMODE_NONE;
  3316     if (SDL20_GetSurfaceBlendMode(icon12->surface20, &blendmode) < 0) {
  3317         return;  // oh well.
  3318     }
  3319 
  3320     Uint32 rmask, gmask, bmask, amask;
  3321     int bpp;
  3322     if (!SDL20_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ARGB8888, &bpp, &rmask, &gmask, &bmask, &amask)) {
  3323         return;  // oh well.
  3324     }
  3325 
  3326     SDL_Surface *icon20 = SDL20_CreateRGBSurface(0, icon12->w, icon12->h, bpp, rmask, gmask, bmask, amask);
  3327     if (!icon20) {
  3328         return;  // oh well.
  3329     }
  3330 
  3331     SDL20_SetSurfaceBlendMode(icon12->surface20, SDL_BLENDMODE_NONE);
  3332     const int rc = SDL20_UpperBlit(icon12->surface20, NULL, icon20, NULL);
  3333     SDL20_SetSurfaceBlendMode(icon12->surface20, blendmode);
  3334     if (rc == 0) {
  3335         if (mask) {
  3336             SDL_assert(icon20->format->BytesPerPixel == 4);
  3337             SDL_assert(icon20->pitch == icon20->w * 4);
  3338             const int w = icon12->w;
  3339             const int h = icon12->h;
  3340             const int mpitch = (w + 7) / 8;
  3341             Uint32 *ptr = (Uint32 *) icon20->pixels;
  3342             for (int y = 0; y < h; y++) {
  3343                 for (int x = 0; x < w; x++, ptr++) {
  3344                     if (!(mask[y*mpitch + x/8] & (128 >> (x % 8)))) {
  3345                         *ptr &= ~amask;
  3346 } else {
  3347 *ptr |= amask;
  3348                     }
  3349                 }
  3350             }
  3351         }
  3352 
  3353         if (VideoWindow20) {
  3354             SDL20_SetWindowIcon(VideoWindow20, icon20);
  3355         }
  3356         SDL20_FreeSurface(VideoIcon20);
  3357         VideoIcon20 = icon20;
  3358     }
  3359 }
  3360 
  3361 DECLSPEC int SDLCALL
  3362 SDL_WM_IconifyWindow(void)
  3363 {
  3364     SDL20_MinimizeWindow(VideoWindow20);
  3365     return 0;
  3366 }
  3367 
  3368 DECLSPEC int SDLCALL
  3369 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  3370 {
  3371     int retval = 0;
  3372     if (surface == VideoSurface12) {
  3373         SDL_assert(VideoWindow20);
  3374         const Uint32 flags20 = SDL20_GetWindowFlags(VideoWindow20);
  3375         if (flags20 & SDL_WINDOW_FULLSCREEN) {
  3376             SDL_assert(VideoSurface12->flags & SDL12_FULLSCREEN);
  3377             retval = (SDL20_SetWindowFullscreen(VideoWindow20, 0) == 0);
  3378             if (retval) {
  3379                 VideoSurface12->flags &= ~SDL12_FULLSCREEN;
  3380             }
  3381         } else {
  3382             SDL_assert((VideoSurface12->flags & SDL12_FULLSCREEN) == 0);
  3383             const Uint32 newflags20 = (VideoSurface12->flags & SDL12_OPENGL) ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;
  3384             retval = (SDL20_SetWindowFullscreen(VideoWindow20, newflags20) == 0);
  3385             if (retval) {
  3386                 VideoSurface12->flags |= SDL12_FULLSCREEN;
  3387             }
  3388         }
  3389         if (retval && VideoRenderer20) {
  3390             SDL20_RenderSetLogicalSize(VideoRenderer20, VideoSurface12->w, VideoSurface12->h);
  3391         }
  3392     }
  3393     return retval;
  3394 }
  3395 
  3396 typedef enum
  3397 {
  3398     SDL12_GRAB_QUERY = -1,
  3399     SDL12_GRAB_OFF = 0,
  3400     SDL12_GRAB_ON = 1
  3401 } SDL12_GrabMode;
  3402 
  3403 static void
  3404 UpdateRelativeMouseMode(void)
  3405 {
  3406     // in SDL 1.2, hiding+grabbing the cursor was like SDL2's relative mouse mode.
  3407     if (VideoWindow20) {
  3408         SDL20_SetRelativeMouseMode((VideoWindowGrabbed && VideoCursorHidden) ? SDL_TRUE : SDL_FALSE);
  3409     }
  3410 }
  3411 
  3412 DECLSPEC int SDLCALL
  3413 SDL_ShowCursor(int toggle)
  3414 {
  3415     const int retval = VideoCursorHidden ? 0 : 1;
  3416 
  3417     if (toggle >= 0) {
  3418         const SDL_bool wanthide = (toggle == 0) ? SDL_TRUE : SDL_FALSE;
  3419         if (VideoCursorHidden != wanthide) {
  3420             SDL20_ShowCursor(wanthide ? 0 : 1);
  3421             VideoCursorHidden = wanthide;
  3422             UpdateRelativeMouseMode();
  3423         }
  3424     }
  3425     return retval;
  3426 }
  3427 
  3428 
  3429 DECLSPEC SDL12_GrabMode SDLCALL
  3430 SDL_WM_GrabInput(SDL12_GrabMode mode)
  3431 {
  3432     if (mode != SDL12_GRAB_QUERY) {
  3433         const SDL_bool wantgrab = (mode == SDL12_GRAB_ON) ? SDL_TRUE : SDL_FALSE;
  3434         if (VideoWindowGrabbed != wantgrab) {
  3435             SDL20_SetWindowGrab(VideoWindow20, wantgrab);
  3436             VideoWindowGrabbed = wantgrab;
  3437             UpdateRelativeMouseMode();
  3438         }
  3439     }
  3440     return VideoWindowGrabbed ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  3441 }
  3442 
  3443 DECLSPEC void SDLCALL
  3444 SDL_WarpMouse(Uint16 x, Uint16 y)
  3445 {
  3446     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  3447 }
  3448 
  3449 DECLSPEC Uint8 SDLCALL
  3450 SDL_GetAppState(void)
  3451 {
  3452     Uint8 state12 = 0;
  3453     Uint32 flags20 = 0;
  3454 
  3455     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  3456     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  3457         state12 |= SDL12_APPACTIVE;
  3458     }
  3459     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  3460         state12 |= SDL12_APPINPUTFOCUS;
  3461     }
  3462     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  3463         state12 |= SDL12_APPMOUSEFOCUS;
  3464     }
  3465     return state12;
  3466 }
  3467 
  3468 DECLSPEC int SDLCALL
  3469 SDL_SetColorKey(SDL12_Surface *surface12, Uint32 flag12, Uint32 key)
  3470 {
  3471     const SDL_bool addkey = (flag12 & SDL12_SRCCOLORKEY) ? SDL_TRUE : SDL_FALSE;
  3472     const int retval = SDL20_SetColorKey(surface12->surface20, addkey, key);
  3473     if (SDL20_GetColorKey(surface12->surface20, &surface12->format->colorkey) < 0) {
  3474         surface12->format->colorkey = 0;
  3475     }
  3476 
  3477     if (addkey) {
  3478         surface12->flags |= SDL12_SRCCOLORKEY;
  3479     } else {
  3480         surface12->flags &= ~SDL12_SRCCOLORKEY;
  3481     }
  3482 
  3483     return retval;
  3484 }
  3485 
  3486 DECLSPEC int SDLCALL
  3487 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  3488                int firstcolor, int ncolors)
  3489 {
  3490     if (!surface12) {
  3491         return 0;  // not an error, a no-op.
  3492     }
  3493 
  3494     if ((flags & (SDL12_LOGPAL | SDL12_PHYSPAL)) == 0) {
  3495         return 0;  // nothing to do.
  3496     }
  3497 
  3498     SDL12_Palette *palette12 = surface12->format->palette;
  3499     if (!palette12) {
  3500         return 0;  // not an error, a no-op.
  3501     }
  3502 
  3503     SDL_Palette *palette20 = surface12->surface20->format->palette;
  3504     SDL_assert(palette20 != NULL);
  3505 
  3506     // we need to force the "unused" field to 255, since it's "alpha" in SDL2.
  3507     SDL_Color *opaquecolors = (SDL_Color *) SDL20_malloc(sizeof (SDL_Color) * ncolors);
  3508     if (!opaquecolors) {
  3509         return SDL20_OutOfMemory();
  3510     }
  3511 
  3512     // don't SDL_memcpy in case the 'a' field is uninitialized and upsets
  3513     //  memory tools like Valgrind.
  3514     for (int i = 0; i < ncolors; i++) {
  3515         opaquecolors[i].r = colors[i].r;
  3516         opaquecolors[i].g = colors[i].g;
  3517         opaquecolors[i].b = colors[i].b;
  3518         opaquecolors[i].a = 255;
  3519     }
  3520 
  3521     int retval = 0;
  3522 
  3523     if (flags & SDL12_LOGPAL) {
  3524         if (SDL20_SetPaletteColors(palette20, opaquecolors, firstcolor, ncolors) < 0) {
  3525             retval = -1;
  3526         }
  3527     }
  3528 
  3529     SDL20_free(opaquecolors);
  3530 
  3531     // in case this pointer changed...
  3532     palette12->colors = palette20->colors;
  3533 
  3534     FIXME("We need to store the physical palette somewhere");  // it might be different that logical palette and it will be needed for future blits.
  3535     if ((surface12 == VideoSurface12) && (flags & SDL12_PHYSPAL)) {
  3536         SDL_UpdateRect(surface12, 0, 0, 0, 0);   // force screen to reblit with new palette.
  3537     }
  3538 
  3539     return retval;
  3540 }
  3541 
  3542 DECLSPEC int SDLCALL
  3543 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  3544               int ncolors)
  3545 {
  3546     return SDL_SetPalette(surface12, SDL12_LOGPAL | SDL12_PHYSPAL, colors, firstcolor, ncolors);
  3547 }
  3548 
  3549 DECLSPEC int SDLCALL
  3550 SDL_GetWMInfo(SDL_SysWMinfo * info)
  3551 {
  3552     FIXME("write me");
  3553     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  3554     return SDL20_Unsupported();
  3555 }
  3556 
  3557 DECLSPEC SDL12_Overlay * SDLCALL
  3558 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  3559 {
  3560     FIXME("write me");
  3561     SDL20_Unsupported();
  3562     return NULL;
  3563 }
  3564 
  3565 DECLSPEC int SDLCALL
  3566 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  3567 {
  3568     FIXME("write me");
  3569     return SDL20_Unsupported();
  3570 }
  3571 
  3572 DECLSPEC void SDLCALL
  3573 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  3574 {
  3575     FIXME("write me");
  3576 }
  3577 
  3578 DECLSPEC int SDLCALL
  3579 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL12_Rect * dstrect12)
  3580 {
  3581     FIXME("write me");
  3582     return SDL20_Unsupported();
  3583 }
  3584 
  3585 DECLSPEC void SDLCALL
  3586 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  3587 {
  3588     FIXME("write me");
  3589 }
  3590 
  3591 DECLSPEC int SDLCALL
  3592 SDL_GL_LoadLibrary(const char *libname)
  3593 {
  3594     /* SDL 1.2 would unload the previous library if one was loaded. SDL2
  3595        reports an error if one is already loaded, and sometimes loads it
  3596        internally for some video targets, so unloading it probably isn't safe.
  3597        There really isn't a good reason to be using anything other than the
  3598        system OpenGL in 2019, so we ignore the error in this case to match 1.2
  3599        behavior, even if you were going to load a different library this time.
  3600        Oh well. */
  3601     const int rc = SDL20_GL_LoadLibrary(libname);
  3602     if (rc == -1) {
  3603         const char *err = SDL20_GetError();
  3604         if (SDL20_strcmp(err, "OpenGL library already loaded") == 0) {
  3605             return 0;
  3606         }
  3607 
  3608         /* reset the actual error. */
  3609         char *dup = SDL20_strdup(err);
  3610         if (!dup) {
  3611             SDL20_OutOfMemory();
  3612         } else {
  3613             SDL20_SetError(dup);
  3614             SDL20_free(dup);
  3615         }
  3616     }
  3617     return rc;
  3618 }
  3619 
  3620 
  3621 DECLSPEC int SDLCALL
  3622 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  3623 {
  3624     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  3625         return SDL20_SetError("Unknown GL attribute");
  3626 
  3627     /* swap control was moved out of this API, everything else lines up. */
  3628     if (attr == SDL12_GL_SWAP_CONTROL)
  3629     {
  3630         SwapInterval = value;
  3631         FIXME("Actually set swap interval somewhere");
  3632         return 0;
  3633     }
  3634 
  3635     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  3636 }
  3637 
  3638 DECLSPEC int SDLCALL
  3639 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  3640 {
  3641     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  3642         return SDL20_SetError("Unknown GL attribute");
  3643 
  3644     /* swap control was moved out of this API, everything else lines up. */
  3645     if (attr == SDL12_GL_SWAP_CONTROL)
  3646     {
  3647         *value = SDL20_GL_GetSwapInterval();
  3648         return 0;
  3649     }
  3650 
  3651     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  3652 }
  3653 
  3654 
  3655 DECLSPEC void SDLCALL
  3656 SDL_GL_SwapBuffers(void)
  3657 {
  3658     if (VideoWindow20)
  3659         SDL20_GL_SwapWindow(VideoWindow20);
  3660 }
  3661 
  3662 DECLSPEC int SDLCALL
  3663 SDL_SetGamma(float red, float green, float blue)
  3664 {
  3665     Uint16 red_ramp[256];
  3666     Uint16 green_ramp[256];
  3667     Uint16 blue_ramp[256];
  3668 
  3669     SDL20_CalculateGammaRamp(red, red_ramp);
  3670     if (green == red) {
  3671         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  3672     } else {
  3673         SDL20_CalculateGammaRamp(green, green_ramp);
  3674     }
  3675     if (blue == red) {
  3676         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  3677     } else if (blue == green) {
  3678         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  3679     } else {
  3680         SDL20_CalculateGammaRamp(blue, blue_ramp);
  3681     }
  3682     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  3683 }
  3684 
  3685 DECLSPEC int SDLCALL
  3686 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  3687 {
  3688     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  3689 }
  3690 
  3691 DECLSPEC int SDLCALL
  3692 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  3693 {
  3694     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  3695 }
  3696 
  3697 DECLSPEC int SDLCALL
  3698 SDL_EnableKeyRepeat(int delay, int interval)
  3699 {
  3700     FIXME("write me");
  3701     return 0;
  3702 }
  3703 
  3704 DECLSPEC void SDLCALL
  3705 SDL_GetKeyRepeat(int *delay, int *interval)
  3706 {
  3707     FIXME("write me");
  3708     if (delay) {
  3709         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  3710     }
  3711     if (interval) {
  3712         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  3713     }
  3714 }
  3715 
  3716 DECLSPEC int SDLCALL
  3717 SDL_EnableUNICODE(int enable)
  3718 {
  3719     FIXME("write me");
  3720     return SDL20_Unsupported();
  3721 }
  3722 
  3723 /* SDL 1.2 limited timers to a 10ms resolution. SDL 2.0 doesn't, so we might
  3724    have to round. This is the equation 1.2 uses: */
  3725 static Uint32 RoundTimerTo12Resolution(const Uint32 ms)
  3726 {
  3727     return (((ms + 10) - 1) / 10) * 10;
  3728 }
  3729 
  3730 
  3731 static Uint32 SDLCALL
  3732 SetTimerCallback12(Uint32 interval, void* param)
  3733 {
  3734     return RoundTimerTo12Resolution(((SDL12_TimerCallback)param)(interval));
  3735 }
  3736 
  3737 DECLSPEC int SDLCALL
  3738 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  3739 {
  3740     static SDL_TimerID compat_timer;
  3741 
  3742     if (compat_timer) {
  3743         SDL20_RemoveTimer(compat_timer);
  3744         compat_timer = 0;
  3745     }
  3746 
  3747     if (interval && callback) {
  3748         interval = RoundTimerTo12Resolution(interval);
  3749         compat_timer = SDL20_AddTimer(interval, SetTimerCallback12, callback);
  3750         if (!compat_timer) {
  3751             return -1;
  3752         }
  3753     }
  3754     return 0;
  3755 }
  3756 
  3757 DECLSPEC int SDLCALL
  3758 SDL_putenv(const char *_var)
  3759 {
  3760     char *ptr = NULL;
  3761     char *var = SDL20_strdup(_var);
  3762     if (var == NULL) {
  3763         return -1;  /* we don't set errno. */
  3764     }
  3765 
  3766     ptr = SDL20_strchr(var, '=');
  3767     if (ptr == NULL) {
  3768         SDL20_free(var);
  3769         return -1;
  3770     }
  3771 
  3772     *ptr = '\0';  /* split the string into name and value. */
  3773     SDL20_setenv(var, ptr + 1, 1);
  3774     SDL20_free(var);
  3775     return 0;
  3776 }
  3777 
  3778 
  3779 
  3780 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  3781 
  3782 typedef void *SDL12_CD;  /* close enough.  :) */
  3783 typedef int SDL12_CDstatus;  /* close enough.  :) */
  3784 
  3785 DECLSPEC int SDLCALL
  3786 SDL_CDNumDrives(void)
  3787 {
  3788     FIXME("should return -1 without SDL_INIT_CDROM");
  3789     return 0;
  3790 }
  3791 
  3792 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  3793 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  3794 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3795 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  3796 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  3797 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3798 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3799 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3800 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3801 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  3802 
  3803 
  3804 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  3805 DECLSPEC SDL_Thread * SDLCALL
  3806 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  3807 {
  3808     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  3809 }
  3810 #else
  3811 DECLSPEC SDL_Thread * SDLCALL
  3812 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  3813 {
  3814     return SDL20_CreateThread(fn, NULL, data);
  3815 }
  3816 #endif
  3817 
  3818 DECLSPEC int SDLCALL
  3819 SDL_mutexP(SDL_mutex *mutex)
  3820 {
  3821     return SDL20_LockMutex(mutex);
  3822 }
  3823 
  3824 DECLSPEC int SDLCALL
  3825 SDL_mutexV(SDL_mutex *mutex)
  3826 {
  3827     return SDL20_UnlockMutex(mutex);
  3828 }
  3829 
  3830 DECLSPEC void SDLCALL
  3831 SDL_KillThread(SDL_Thread *thread)
  3832 {
  3833     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  3834     fprintf(stderr,
  3835         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  3836         "This program should be fixed. No thread was actually harmed.\n");
  3837 }
  3838 
  3839 typedef struct SDL12_TimerID_Data
  3840 {
  3841     SDL_TimerID timer_id;
  3842     SDL12_NewTimerCallback callback;
  3843     void *param;
  3844 } SDL12_TimerID_Data;
  3845 
  3846 /* This changed from an opaque pointer to an int in 2.0. */
  3847 typedef SDL12_TimerID_Data *SDL12_TimerID;
  3848 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  3849 
  3850 
  3851 static Uint32 SDLCALL
  3852 AddTimerCallback12(Uint32 interval, void *param)
  3853 {
  3854     SDL12_TimerID data = (SDL12_TimerID) param;
  3855     return RoundTimerTo12Resolution(data->callback(interval, data->param));
  3856 }
  3857 
  3858 DECLSPEC SDL12_TimerID SDLCALL
  3859 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  3860 {
  3861     SDL12_TimerID data = (SDL12_TimerID) SDL_malloc(sizeof (SDL12_TimerID_Data));
  3862     if (!data) {
  3863         SDL20_OutOfMemory();
  3864         return NULL;
  3865     }
  3866 
  3867     interval = RoundTimerTo12Resolution(interval);
  3868     data->callback = callback;
  3869     data->param = param;
  3870     data->timer_id = SDL20_AddTimer(interval, AddTimerCallback12, data);
  3871 
  3872     if (!data->timer_id) {
  3873         SDL_free(data);
  3874         return NULL;
  3875     }
  3876 
  3877     return data;
  3878 }
  3879 
  3880 DECLSPEC SDL_bool SDLCALL
  3881 SDL_RemoveTimer(SDL12_TimerID data)
  3882 {
  3883     // !!! FIXME: classic 1.2 will safely return SDL_FALSE if this is a bogus
  3884     // !!! FIXME:  timer. This code will dereference a bogus pointer.
  3885     const SDL_bool retval = SDL20_RemoveTimer(data->timer_id);
  3886     if (retval) {
  3887         SDL_free(data);
  3888     }
  3889     return retval;
  3890 }
  3891 
  3892 
  3893 typedef struct SDL12_RWops {
  3894     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  3895     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  3896     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  3897     int (SDLCALL *close)(struct SDL12_RWops *context);
  3898     Uint32 type;
  3899     void *padding[8];
  3900     SDL_RWops *rwops20;
  3901 } SDL12_RWops;
  3902 
  3903 
  3904 DECLSPEC SDL12_RWops * SDLCALL
  3905 SDL_AllocRW(void)
  3906 {
  3907     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  3908     if (!rwops)
  3909         SDL20_OutOfMemory();
  3910     return rwops;
  3911 }
  3912 
  3913 DECLSPEC void SDLCALL
  3914 SDL_FreeRW(SDL12_RWops *rwops12)
  3915 {
  3916     SDL20_free(rwops12);
  3917 }
  3918 
  3919 static int SDLCALL
  3920 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  3921 {
  3922     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  3923 }
  3924 
  3925 static int SDLCALL
  3926 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  3927 {
  3928     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  3929 }
  3930 
  3931 static int SDLCALL
  3932 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  3933 {
  3934     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  3935 }
  3936 
  3937 static int SDLCALL
  3938 RWops20to12_close(struct SDL12_RWops *rwops12)
  3939 {
  3940     int rc = 0;
  3941     if (rwops12)
  3942     {
  3943         rc = rwops12->rwops20->close(rwops12->rwops20);
  3944         if (rc == 0)
  3945             SDL_FreeRW(rwops12);
  3946     }
  3947     return rc;
  3948 }
  3949 
  3950 static SDL12_RWops *
  3951 RWops20to12(SDL_RWops *rwops20)
  3952 {
  3953     SDL12_RWops *rwops12;
  3954 
  3955     if (!rwops20)
  3956         return NULL;
  3957 
  3958     rwops12 = SDL_AllocRW();
  3959     if (!rwops12)
  3960         return NULL;
  3961 
  3962     SDL20_zerop(rwops12);
  3963     rwops12->type = rwops20->type;
  3964     rwops12->rwops20 = rwops20;
  3965     rwops12->seek = RWops20to12_seek;
  3966     rwops12->read = RWops20to12_read;
  3967     rwops12->write = RWops20to12_write;
  3968     rwops12->close = RWops20to12_close;
  3969 
  3970     return rwops12;
  3971 }
  3972 
  3973 DECLSPEC SDL12_RWops * SDLCALL
  3974 SDL_RWFromFile(const char *file, const char *mode)
  3975 {
  3976     if ( !file || !*file || !mode || !*mode ) {
  3977         SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
  3978         return NULL;
  3979     }
  3980     return RWops20to12(SDL20_RWFromFile(file, mode));
  3981 }
  3982 
  3983 DECLSPEC SDL12_RWops * SDLCALL
  3984 SDL_RWFromFP(FILE *io, int autoclose)
  3985 {
  3986     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  3987 }
  3988 
  3989 DECLSPEC SDL12_RWops * SDLCALL
  3990 SDL_RWFromMem(void *mem, int size)
  3991 {
  3992     return RWops20to12(SDL20_RWFromMem(mem, size));
  3993 }
  3994 
  3995 DECLSPEC SDL12_RWops * SDLCALL
  3996 SDL_RWFromConstMem(const void *mem, int size)
  3997 {
  3998     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  3999 }
  4000 
  4001 #define READ_AND_BYTESWAP(endian, bits) \
  4002     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  4003         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  4004         return SDL_Swap##endian##bits(val); \
  4005     }
  4006 
  4007 READ_AND_BYTESWAP(LE,16)
  4008 READ_AND_BYTESWAP(BE,16)
  4009 READ_AND_BYTESWAP(LE,32)
  4010 READ_AND_BYTESWAP(BE,32)
  4011 READ_AND_BYTESWAP(LE,64)
  4012 READ_AND_BYTESWAP(BE,64)
  4013 #undef READ_AND_BYTESWAP
  4014 
  4015 #define BYTESWAP_AND_WRITE(endian, bits) \
  4016     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  4017         val = SDL_Swap##endian##bits(val); \
  4018         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  4019     }
  4020 BYTESWAP_AND_WRITE(LE,16)
  4021 BYTESWAP_AND_WRITE(BE,16)
  4022 BYTESWAP_AND_WRITE(LE,32)
  4023 BYTESWAP_AND_WRITE(BE,32)
  4024 BYTESWAP_AND_WRITE(LE,64)
  4025 BYTESWAP_AND_WRITE(BE,64)
  4026 #undef BYTESWAP_AND_WRITE
  4027 
  4028 
  4029 static Sint64 SDLCALL
  4030 RWops12to20_size(struct SDL_RWops *rwops20)
  4031 {
  4032     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  4033     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  4034     int pos;
  4035 
  4036     if (size != -1)
  4037         return size;
  4038 
  4039     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  4040     if (pos == -1)
  4041         return -1;
  4042 
  4043     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  4044     if (size == -1)
  4045         return -1;
  4046 
  4047     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  4048     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  4049     return size;
  4050 }
  4051 
  4052 static Sint64 SDLCALL
  4053 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  4054 {
  4055     FIXME("fail if (offset) is too big");
  4056     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  4057     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  4058 }
  4059 
  4060 static size_t SDLCALL
  4061 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  4062 {
  4063     FIXME("fail if (size) or (maxnum) is too big");
  4064     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  4065     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  4066 }
  4067 
  4068 static size_t SDLCALL
  4069 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  4070 {
  4071     FIXME("fail if (size) or (maxnum) is too big");
  4072     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  4073     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  4074 }
  4075 
  4076 static int SDLCALL
  4077 RWops12to20_close(struct SDL_RWops *rwops20)
  4078 {
  4079     int rc = 0;
  4080     if (rwops20)
  4081     {
  4082         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  4083         rc = rwops12->close(rwops12);
  4084         if (rc == 0)
  4085             SDL20_FreeRW(rwops20);
  4086     }
  4087     return rc;
  4088 }
  4089 
  4090 static SDL_RWops *
  4091 RWops12to20(SDL12_RWops *rwops12)
  4092 {
  4093     SDL_RWops *rwops20;
  4094 
  4095     if (!rwops12)
  4096         return NULL;
  4097 
  4098     rwops20 = SDL20_AllocRW();
  4099     if (!rwops20)
  4100         return NULL;
  4101 
  4102     SDL20_zerop(rwops20);
  4103     rwops20->type = rwops12->type;
  4104     rwops20->hidden.unknown.data1 = rwops12;
  4105     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  4106     rwops20->size = RWops12to20_size;
  4107     rwops20->seek = RWops12to20_seek;
  4108     rwops20->read = RWops12to20_read;
  4109     rwops20->write = RWops12to20_write;
  4110     rwops20->close = RWops12to20_close;
  4111     return rwops20;
  4112 }
  4113 
  4114 DECLSPEC SDL12_Surface * SDLCALL
  4115 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  4116 {
  4117     SDL_RWops *rwops20 = RWops12to20(rwops12);
  4118     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  4119     SDL12_Surface *surface12 = Surface20to12(surface20);
  4120     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  4121         SDL20_FreeRW(rwops20);
  4122     if ((!surface12) && (surface20))
  4123         SDL20_FreeSurface(surface20);
  4124     return surface12;
  4125 }
  4126 
  4127 DECLSPEC int SDLCALL
  4128 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  4129 {
  4130     FIXME("wrap surface");
  4131     SDL_RWops *rwops20 = RWops12to20(rwops12);
  4132     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  4133     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  4134         SDL20_FreeRW(rwops20);
  4135     return retval;
  4136 }
  4137 
  4138 DECLSPEC SDL_AudioSpec * SDLCALL
  4139 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  4140                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  4141 {
  4142     SDL_RWops *rwops20 = RWops12to20(rwops12);
  4143     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  4144     FIXME("deal with non-1.2 formats, like float32");
  4145     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  4146         SDL20_FreeRW(rwops20);
  4147     return retval;
  4148 }
  4149 
  4150 typedef struct
  4151 {
  4152     void (SDLCALL *app_callback)(void *userdata, Uint8 *stream, int len);
  4153     void *app_userdata;
  4154     Uint8 silence;
  4155 } AudioCallbackWrapperData;
  4156 
  4157 static void SDLCALL
  4158 AudioCallbackWrapper(void *userdata, Uint8 *stream, int len)
  4159 {
  4160     AudioCallbackWrapperData *data = (AudioCallbackWrapperData *) userdata;
  4161     SDL_memset(stream, data->silence, len);  // SDL2 doesn't clear the stream before calling in here, but 1.2 expects it.
  4162     data->app_callback(data->app_userdata, stream, len);
  4163 }
  4164 
  4165 
  4166 DECLSPEC int SDLCALL
  4167 SDL_OpenAudio(SDL_AudioSpec *want, SDL_AudioSpec *obtained)
  4168 {
  4169     // SDL2 uses a NULL callback to mean "we play to use SDL_QueueAudio()"
  4170     if (want && (want->callback == NULL)) {
  4171         return SDL20_SetError("Callback can't be NULL");
  4172     }
  4173 
  4174     AudioCallbackWrapperData *data = (AudioCallbackWrapperData *) SDL20_calloc(1, sizeof (AudioCallbackWrapperData));
  4175     if (!data) {
  4176         return SDL20_OutOfMemory();
  4177     }
  4178     data->app_callback = want->callback;
  4179     data->app_userdata = want->userdata;
  4180     want->callback = AudioCallbackWrapper;
  4181     want->userdata = data;
  4182 
  4183     FIXME("Don't allow int32 or float32");
  4184     FIXME("clamp output to mono/stereo");
  4185     const int retval = SDL20_OpenAudio(want, obtained);
  4186     want->callback = data->app_callback;
  4187     want->userdata = data->app_userdata;
  4188     if (retval == -1) {
  4189         SDL20_free(data);
  4190     } else {
  4191         FIXME("memory leak on callback data");
  4192         if (!obtained) {
  4193             data->silence = want->silence;
  4194         } else {
  4195             data->silence = obtained->silence;
  4196             obtained->callback = data->app_callback;
  4197             obtained->userdata = data->app_userdata;
  4198         }
  4199     }
  4200 
  4201     return retval;
  4202 }
  4203 
  4204 
  4205 /* SDL_GL_DisableContext and SDL_GL_EnableContext_Thread are not real SDL 1.2
  4206    APIs, but some idTech4 games shipped with a custom SDL 1.2 build that added
  4207    these functions, to let them make a GL context current on a background thread,
  4208    so we supply them as well to be binary compatible for those games. */
  4209 
  4210 DECLSPEC void SDLCALL
  4211 SDL_GL_DisableContext(void)
  4212 {
  4213     SDL20_GL_MakeCurrent(NULL, NULL);
  4214 }
  4215 
  4216 DECLSPEC void SDLCALL
  4217 SDL_GL_EnableContext_Thread(void)
  4218 {
  4219     const SDL_bool enable = (VideoGLContext20 && VideoWindow20);
  4220     SDL20_GL_MakeCurrent(enable ? VideoWindow20 : NULL, enable ? VideoGLContext20 : NULL);
  4221 }
  4222 
  4223 /* vi: set ts=4 sw=4 expandtab: */