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