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