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