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