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