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