src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 10 Mar 2019 00:18:10 -0500
changeset 113 ed19faa58a82
parent 112 be327fd46284
child 114 f4f3bf9e36e1
permissions -rw-r--r--
Call SDL_StopTextInput() during init.

Otherwise, macOS might pop up a choose-an-accented-letter window if you hold
down a key, which looks really weird in an FPS.

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