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