src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Sat, 02 Mar 2019 08:19:49 -0500
changeset 99 db10b95d4059
parent 98 55027ad695d6
child 100 6384c83ea0e8
permissions -rw-r--r--
Fixed SDL_PushEvent() messing up the queue.
     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 
  1321     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
  1322     next = EventQueueHead->next;
  1323     EventQueueHead->next = EventQueueAvailable;
  1324     EventQueueAvailable = EventQueueHead;
  1325     EventQueueHead = next;
  1326     if (!next) {
  1327         EventQueueTail = NULL;
  1328     }
  1329 
  1330     return 1;
  1331 }
  1332 
  1333 DECLSPEC int SDLCALL
  1334 SDL_PushEvent(SDL12_Event *event12)
  1335 {
  1336     EventQueueType *item = EventQueueAvailable;
  1337     if (item == NULL) {
  1338         return -1;  /* no space available at the moment. */
  1339     }
  1340 
  1341     EventQueueAvailable = item->next;
  1342     if (EventQueueTail) {
  1343         EventQueueTail->next = item;
  1344         EventQueueTail = item;
  1345     } else {
  1346         EventQueueHead = EventQueueTail = item;
  1347     }
  1348     item->next = NULL;
  1349 
  1350     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
  1351 
  1352     return 0;
  1353 }
  1354 
  1355 DECLSPEC int SDLCALL
  1356 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
  1357 {
  1358     if (action == SDL_ADDEVENT)
  1359     {
  1360         int i;
  1361         for (i = 0; i < numevents; i++)
  1362         {
  1363             if (SDL_PushEvent(&events12[i]) == -1)
  1364                 break;  /* out of space for more events. */
  1365         }
  1366         return i;
  1367     }
  1368     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
  1369     {
  1370         const SDL_bool isGet = (action == SDL_GETEVENT);
  1371         EventQueueType *prev = NULL;
  1372         EventQueueType *item = EventQueueHead;
  1373         EventQueueType *next = NULL;
  1374         int chosen = 0;
  1375         while (chosen < numevents)
  1376         {
  1377             EventQueueType *nextPrev = item;
  1378             if (!item)
  1379                 break;  /* no more events at the moment. */
  1380 
  1381             next = item->next;  /* copy, since we might overwrite item->next */
  1382 
  1383             if (mask & (1<<item->event12.type))
  1384             {
  1385                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
  1386                 if (isGet)  /* remove from list? */
  1387                 {
  1388                     if (prev != NULL)
  1389                         prev->next = next;
  1390                     if (item == EventQueueHead)
  1391                         EventQueueHead = next;
  1392                     if (item == EventQueueTail)
  1393                         EventQueueTail = prev;
  1394 
  1395                     /* put it back in the free pool. */
  1396                     item->next = EventQueueAvailable;
  1397                     EventQueueAvailable = item;
  1398                     nextPrev = prev;  /* previous item doesn't change. */
  1399                 }
  1400             }
  1401 
  1402             item = next;
  1403             prev = nextPrev;
  1404         }
  1405         return chosen;
  1406     }
  1407 
  1408     return 0;
  1409 }
  1410 
  1411 DECLSPEC int SDLCALL
  1412 SDL_WaitEvent(SDL12_Event *event12)
  1413 {
  1414     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1415     while (!SDL_PollEvent(event12))
  1416         SDL20_Delay(10);
  1417     return 1;
  1418 }
  1419 
  1420 static SDL_bool
  1421 PushEventIfNotFiltered(SDL12_Event *event12)
  1422 {
  1423     if (event12->type != SDL12_NOEVENT)
  1424     {
  1425         if (EventStates[event12->type] != SDL_IGNORE)
  1426         {
  1427             if ((!EventFilter12) || (EventFilter12(event12)))
  1428                 return (SDL_PushEvent(event12) == 0);
  1429         }
  1430     }
  1431     return SDL_FALSE;
  1432 }
  1433 
  1434 DECLSPEC Uint8 SDLCALL
  1435 SDL_EventState(Uint8 type, int state)
  1436 {
  1437     /* the values of "state" match between 1.2 and 2.0 */
  1438     const Uint8 retval = EventStates[type];
  1439     SDL12_Event e;
  1440 
  1441     if (state != SDL_QUERY)
  1442         EventStates[type] = state;
  1443     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1444         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1445 
  1446     return retval;
  1447 }
  1448 
  1449 DECLSPEC Uint8 SDLCALL
  1450 SDL_GetMouseState(int *x, int *y)
  1451 {
  1452     const Uint32 state20 = SDL20_GetMouseState(x, y);
  1453     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1454 
  1455     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1456     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  1457         retval |= (1<<5);
  1458     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  1459         retval |= (1<<6);
  1460 
  1461     return retval;
  1462 }
  1463 
  1464 DECLSPEC char * SDLCALL
  1465 SDL_GetKeyName(SDL12Key key)
  1466 {
  1467     switch (key) {
  1468         #define CASESDLK12TONAME(k, n) case k: return (char *) n
  1469 	    CASESDLK12TONAME(SDLK12_BACKSPACE, "backspace");
  1470 	    CASESDLK12TONAME(SDLK12_TAB, "tab");
  1471 	    CASESDLK12TONAME(SDLK12_CLEAR, "clear");
  1472 	    CASESDLK12TONAME(SDLK12_RETURN, "return");
  1473 	    CASESDLK12TONAME(SDLK12_PAUSE, "pause");
  1474 	    CASESDLK12TONAME(SDLK12_ESCAPE, "escape");
  1475 	    CASESDLK12TONAME(SDLK12_SPACE, "space");
  1476 	    CASESDLK12TONAME(SDLK12_EXCLAIM, "!");
  1477 	    CASESDLK12TONAME(SDLK12_QUOTEDBL, "\"");
  1478 	    CASESDLK12TONAME(SDLK12_HASH, "#");
  1479 	    CASESDLK12TONAME(SDLK12_DOLLAR, "$");
  1480 	    CASESDLK12TONAME(SDLK12_AMPERSAND, "&");
  1481 	    CASESDLK12TONAME(SDLK12_QUOTE, "'");
  1482 	    CASESDLK12TONAME(SDLK12_LEFTPAREN, "(");
  1483 	    CASESDLK12TONAME(SDLK12_RIGHTPAREN, ")");
  1484 	    CASESDLK12TONAME(SDLK12_ASTERISK, "*");
  1485 	    CASESDLK12TONAME(SDLK12_PLUS, "+");
  1486 	    CASESDLK12TONAME(SDLK12_COMMA, ",");
  1487 	    CASESDLK12TONAME(SDLK12_MINUS, "-");
  1488 	    CASESDLK12TONAME(SDLK12_PERIOD, ".");
  1489 	    CASESDLK12TONAME(SDLK12_SLASH, "/");
  1490 	    CASESDLK12TONAME(SDLK12_0, "0");
  1491 	    CASESDLK12TONAME(SDLK12_1, "1");
  1492 	    CASESDLK12TONAME(SDLK12_2, "2");
  1493 	    CASESDLK12TONAME(SDLK12_3, "3");
  1494 	    CASESDLK12TONAME(SDLK12_4, "4");
  1495 	    CASESDLK12TONAME(SDLK12_5, "5");
  1496 	    CASESDLK12TONAME(SDLK12_6, "6");
  1497 	    CASESDLK12TONAME(SDLK12_7, "7");
  1498 	    CASESDLK12TONAME(SDLK12_8, "8");
  1499 	    CASESDLK12TONAME(SDLK12_9, "9");
  1500 	    CASESDLK12TONAME(SDLK12_COLON, ":");
  1501 	    CASESDLK12TONAME(SDLK12_SEMICOLON, ");");
  1502 	    CASESDLK12TONAME(SDLK12_LESS, "<");
  1503 	    CASESDLK12TONAME(SDLK12_EQUALS, "=");
  1504 	    CASESDLK12TONAME(SDLK12_GREATER, ">");
  1505 	    CASESDLK12TONAME(SDLK12_QUESTION, "?");
  1506 	    CASESDLK12TONAME(SDLK12_AT, "@");
  1507 	    CASESDLK12TONAME(SDLK12_LEFTBRACKET, "[");
  1508 	    CASESDLK12TONAME(SDLK12_BACKSLASH, "\\");
  1509 	    CASESDLK12TONAME(SDLK12_RIGHTBRACKET, "]");
  1510 	    CASESDLK12TONAME(SDLK12_CARET, "^");
  1511 	    CASESDLK12TONAME(SDLK12_UNDERSCORE, "_");
  1512 	    CASESDLK12TONAME(SDLK12_BACKQUOTE, "`");
  1513 	    CASESDLK12TONAME(SDLK12_a, "a");
  1514 	    CASESDLK12TONAME(SDLK12_b, "b");
  1515 	    CASESDLK12TONAME(SDLK12_c, "c");
  1516 	    CASESDLK12TONAME(SDLK12_d, "d");
  1517 	    CASESDLK12TONAME(SDLK12_e, "e");
  1518 	    CASESDLK12TONAME(SDLK12_f, "f");
  1519 	    CASESDLK12TONAME(SDLK12_g, "g");
  1520 	    CASESDLK12TONAME(SDLK12_h, "h");
  1521 	    CASESDLK12TONAME(SDLK12_i, "i");
  1522 	    CASESDLK12TONAME(SDLK12_j, "j");
  1523 	    CASESDLK12TONAME(SDLK12_k, "k");
  1524 	    CASESDLK12TONAME(SDLK12_l, "l");
  1525 	    CASESDLK12TONAME(SDLK12_m, "m");
  1526 	    CASESDLK12TONAME(SDLK12_n, "n");
  1527 	    CASESDLK12TONAME(SDLK12_o, "o");
  1528 	    CASESDLK12TONAME(SDLK12_p, "p");
  1529 	    CASESDLK12TONAME(SDLK12_q, "q");
  1530 	    CASESDLK12TONAME(SDLK12_r, "r");
  1531 	    CASESDLK12TONAME(SDLK12_s, "s");
  1532 	    CASESDLK12TONAME(SDLK12_t, "t");
  1533 	    CASESDLK12TONAME(SDLK12_u, "u");
  1534 	    CASESDLK12TONAME(SDLK12_v, "v");
  1535 	    CASESDLK12TONAME(SDLK12_w, "w");
  1536 	    CASESDLK12TONAME(SDLK12_x, "x");
  1537 	    CASESDLK12TONAME(SDLK12_y, "y");
  1538 	    CASESDLK12TONAME(SDLK12_z, "z");
  1539 	    CASESDLK12TONAME(SDLK12_DELETE, "delete");
  1540 
  1541 	    CASESDLK12TONAME(SDLK12_WORLD_0, "world 0");
  1542 	    CASESDLK12TONAME(SDLK12_WORLD_1, "world 1");
  1543 	    CASESDLK12TONAME(SDLK12_WORLD_2, "world 2");
  1544 	    CASESDLK12TONAME(SDLK12_WORLD_3, "world 3");
  1545 	    CASESDLK12TONAME(SDLK12_WORLD_4, "world 4");
  1546 	    CASESDLK12TONAME(SDLK12_WORLD_5, "world 5");
  1547 	    CASESDLK12TONAME(SDLK12_WORLD_6, "world 6");
  1548 	    CASESDLK12TONAME(SDLK12_WORLD_7, "world 7");
  1549 	    CASESDLK12TONAME(SDLK12_WORLD_8, "world 8");
  1550 	    CASESDLK12TONAME(SDLK12_WORLD_9, "world 9");
  1551 	    CASESDLK12TONAME(SDLK12_WORLD_10, "world 10");
  1552 	    CASESDLK12TONAME(SDLK12_WORLD_11, "world 11");
  1553 	    CASESDLK12TONAME(SDLK12_WORLD_12, "world 12");
  1554 	    CASESDLK12TONAME(SDLK12_WORLD_13, "world 13");
  1555 	    CASESDLK12TONAME(SDLK12_WORLD_14, "world 14");
  1556 	    CASESDLK12TONAME(SDLK12_WORLD_15, "world 15");
  1557 	    CASESDLK12TONAME(SDLK12_WORLD_16, "world 16");
  1558 	    CASESDLK12TONAME(SDLK12_WORLD_17, "world 17");
  1559 	    CASESDLK12TONAME(SDLK12_WORLD_18, "world 18");
  1560 	    CASESDLK12TONAME(SDLK12_WORLD_19, "world 19");
  1561 	    CASESDLK12TONAME(SDLK12_WORLD_20, "world 20");
  1562 	    CASESDLK12TONAME(SDLK12_WORLD_21, "world 21");
  1563 	    CASESDLK12TONAME(SDLK12_WORLD_22, "world 22");
  1564 	    CASESDLK12TONAME(SDLK12_WORLD_23, "world 23");
  1565 	    CASESDLK12TONAME(SDLK12_WORLD_24, "world 24");
  1566 	    CASESDLK12TONAME(SDLK12_WORLD_25, "world 25");
  1567 	    CASESDLK12TONAME(SDLK12_WORLD_26, "world 26");
  1568 	    CASESDLK12TONAME(SDLK12_WORLD_27, "world 27");
  1569 	    CASESDLK12TONAME(SDLK12_WORLD_28, "world 28");
  1570 	    CASESDLK12TONAME(SDLK12_WORLD_29, "world 29");
  1571 	    CASESDLK12TONAME(SDLK12_WORLD_30, "world 30");
  1572 	    CASESDLK12TONAME(SDLK12_WORLD_31, "world 31");
  1573 	    CASESDLK12TONAME(SDLK12_WORLD_32, "world 32");
  1574 	    CASESDLK12TONAME(SDLK12_WORLD_33, "world 33");
  1575 	    CASESDLK12TONAME(SDLK12_WORLD_34, "world 34");
  1576 	    CASESDLK12TONAME(SDLK12_WORLD_35, "world 35");
  1577 	    CASESDLK12TONAME(SDLK12_WORLD_36, "world 36");
  1578 	    CASESDLK12TONAME(SDLK12_WORLD_37, "world 37");
  1579 	    CASESDLK12TONAME(SDLK12_WORLD_38, "world 38");
  1580 	    CASESDLK12TONAME(SDLK12_WORLD_39, "world 39");
  1581 	    CASESDLK12TONAME(SDLK12_WORLD_40, "world 40");
  1582 	    CASESDLK12TONAME(SDLK12_WORLD_41, "world 41");
  1583 	    CASESDLK12TONAME(SDLK12_WORLD_42, "world 42");
  1584 	    CASESDLK12TONAME(SDLK12_WORLD_43, "world 43");
  1585 	    CASESDLK12TONAME(SDLK12_WORLD_44, "world 44");
  1586 	    CASESDLK12TONAME(SDLK12_WORLD_45, "world 45");
  1587 	    CASESDLK12TONAME(SDLK12_WORLD_46, "world 46");
  1588 	    CASESDLK12TONAME(SDLK12_WORLD_47, "world 47");
  1589 	    CASESDLK12TONAME(SDLK12_WORLD_48, "world 48");
  1590 	    CASESDLK12TONAME(SDLK12_WORLD_49, "world 49");
  1591 	    CASESDLK12TONAME(SDLK12_WORLD_50, "world 50");
  1592 	    CASESDLK12TONAME(SDLK12_WORLD_51, "world 51");
  1593 	    CASESDLK12TONAME(SDLK12_WORLD_52, "world 52");
  1594 	    CASESDLK12TONAME(SDLK12_WORLD_53, "world 53");
  1595 	    CASESDLK12TONAME(SDLK12_WORLD_54, "world 54");
  1596 	    CASESDLK12TONAME(SDLK12_WORLD_55, "world 55");
  1597 	    CASESDLK12TONAME(SDLK12_WORLD_56, "world 56");
  1598 	    CASESDLK12TONAME(SDLK12_WORLD_57, "world 57");
  1599 	    CASESDLK12TONAME(SDLK12_WORLD_58, "world 58");
  1600 	    CASESDLK12TONAME(SDLK12_WORLD_59, "world 59");
  1601 	    CASESDLK12TONAME(SDLK12_WORLD_60, "world 60");
  1602 	    CASESDLK12TONAME(SDLK12_WORLD_61, "world 61");
  1603 	    CASESDLK12TONAME(SDLK12_WORLD_62, "world 62");
  1604 	    CASESDLK12TONAME(SDLK12_WORLD_63, "world 63");
  1605 	    CASESDLK12TONAME(SDLK12_WORLD_64, "world 64");
  1606 	    CASESDLK12TONAME(SDLK12_WORLD_65, "world 65");
  1607 	    CASESDLK12TONAME(SDLK12_WORLD_66, "world 66");
  1608 	    CASESDLK12TONAME(SDLK12_WORLD_67, "world 67");
  1609 	    CASESDLK12TONAME(SDLK12_WORLD_68, "world 68");
  1610 	    CASESDLK12TONAME(SDLK12_WORLD_69, "world 69");
  1611 	    CASESDLK12TONAME(SDLK12_WORLD_70, "world 70");
  1612 	    CASESDLK12TONAME(SDLK12_WORLD_71, "world 71");
  1613 	    CASESDLK12TONAME(SDLK12_WORLD_72, "world 72");
  1614 	    CASESDLK12TONAME(SDLK12_WORLD_73, "world 73");
  1615 	    CASESDLK12TONAME(SDLK12_WORLD_74, "world 74");
  1616 	    CASESDLK12TONAME(SDLK12_WORLD_75, "world 75");
  1617 	    CASESDLK12TONAME(SDLK12_WORLD_76, "world 76");
  1618 	    CASESDLK12TONAME(SDLK12_WORLD_77, "world 77");
  1619 	    CASESDLK12TONAME(SDLK12_WORLD_78, "world 78");
  1620 	    CASESDLK12TONAME(SDLK12_WORLD_79, "world 79");
  1621 	    CASESDLK12TONAME(SDLK12_WORLD_80, "world 80");
  1622 	    CASESDLK12TONAME(SDLK12_WORLD_81, "world 81");
  1623 	    CASESDLK12TONAME(SDLK12_WORLD_82, "world 82");
  1624 	    CASESDLK12TONAME(SDLK12_WORLD_83, "world 83");
  1625 	    CASESDLK12TONAME(SDLK12_WORLD_84, "world 84");
  1626 	    CASESDLK12TONAME(SDLK12_WORLD_85, "world 85");
  1627 	    CASESDLK12TONAME(SDLK12_WORLD_86, "world 86");
  1628 	    CASESDLK12TONAME(SDLK12_WORLD_87, "world 87");
  1629 	    CASESDLK12TONAME(SDLK12_WORLD_88, "world 88");
  1630 	    CASESDLK12TONAME(SDLK12_WORLD_89, "world 89");
  1631 	    CASESDLK12TONAME(SDLK12_WORLD_90, "world 90");
  1632 	    CASESDLK12TONAME(SDLK12_WORLD_91, "world 91");
  1633 	    CASESDLK12TONAME(SDLK12_WORLD_92, "world 92");
  1634 	    CASESDLK12TONAME(SDLK12_WORLD_93, "world 93");
  1635 	    CASESDLK12TONAME(SDLK12_WORLD_94, "world 94");
  1636 	    CASESDLK12TONAME(SDLK12_WORLD_95, "world 95");
  1637 
  1638 	    CASESDLK12TONAME(SDLK12_KP0, "[0]");
  1639 	    CASESDLK12TONAME(SDLK12_KP1, "[1]");
  1640 	    CASESDLK12TONAME(SDLK12_KP2, "[2]");
  1641 	    CASESDLK12TONAME(SDLK12_KP3, "[3]");
  1642 	    CASESDLK12TONAME(SDLK12_KP4, "[4]");
  1643 	    CASESDLK12TONAME(SDLK12_KP5, "[5]");
  1644 	    CASESDLK12TONAME(SDLK12_KP6, "[6]");
  1645 	    CASESDLK12TONAME(SDLK12_KP7, "[7]");
  1646 	    CASESDLK12TONAME(SDLK12_KP8, "[8]");
  1647 	    CASESDLK12TONAME(SDLK12_KP9, "[9]");
  1648 	    CASESDLK12TONAME(SDLK12_KP_PERIOD, "[.]");
  1649 	    CASESDLK12TONAME(SDLK12_KP_DIVIDE, "[/]");
  1650 	    CASESDLK12TONAME(SDLK12_KP_MULTIPLY, "[*]");
  1651 	    CASESDLK12TONAME(SDLK12_KP_MINUS, "[-]");
  1652 	    CASESDLK12TONAME(SDLK12_KP_PLUS, "[+]");
  1653 	    CASESDLK12TONAME(SDLK12_KP_ENTER, "enter");
  1654 	    CASESDLK12TONAME(SDLK12_KP_EQUALS, "equals");
  1655 
  1656 	    CASESDLK12TONAME(SDLK12_UP, "up");
  1657 	    CASESDLK12TONAME(SDLK12_DOWN, "down");
  1658 	    CASESDLK12TONAME(SDLK12_RIGHT, "right");
  1659 	    CASESDLK12TONAME(SDLK12_LEFT, "left");
  1660 	    CASESDLK12TONAME(SDLK12_INSERT, "insert");
  1661 	    CASESDLK12TONAME(SDLK12_HOME, "home");
  1662 	    CASESDLK12TONAME(SDLK12_END, "end");
  1663 	    CASESDLK12TONAME(SDLK12_PAGEUP, "page up");
  1664 	    CASESDLK12TONAME(SDLK12_PAGEDOWN, "page down");
  1665 
  1666 	    CASESDLK12TONAME(SDLK12_F1, "f1");
  1667 	    CASESDLK12TONAME(SDLK12_F2, "f2");
  1668 	    CASESDLK12TONAME(SDLK12_F3, "f3");
  1669 	    CASESDLK12TONAME(SDLK12_F4, "f4");
  1670 	    CASESDLK12TONAME(SDLK12_F5, "f5");
  1671 	    CASESDLK12TONAME(SDLK12_F6, "f6");
  1672 	    CASESDLK12TONAME(SDLK12_F7, "f7");
  1673 	    CASESDLK12TONAME(SDLK12_F8, "f8");
  1674 	    CASESDLK12TONAME(SDLK12_F9, "f9");
  1675 	    CASESDLK12TONAME(SDLK12_F10, "f10");
  1676 	    CASESDLK12TONAME(SDLK12_F11, "f11");
  1677 	    CASESDLK12TONAME(SDLK12_F12, "f12");
  1678 	    CASESDLK12TONAME(SDLK12_F13, "f13");
  1679 	    CASESDLK12TONAME(SDLK12_F14, "f14");
  1680 	    CASESDLK12TONAME(SDLK12_F15, "f15");
  1681 
  1682 	    CASESDLK12TONAME(SDLK12_NUMLOCK, "numlock");
  1683 	    CASESDLK12TONAME(SDLK12_CAPSLOCK, "caps lock");
  1684 	    CASESDLK12TONAME(SDLK12_SCROLLOCK, "scroll lock");
  1685 	    CASESDLK12TONAME(SDLK12_RSHIFT, "right shift");
  1686 	    CASESDLK12TONAME(SDLK12_LSHIFT, "left shift");
  1687 	    CASESDLK12TONAME(SDLK12_RCTRL, "right ctrl");
  1688 	    CASESDLK12TONAME(SDLK12_LCTRL, "left ctrl");
  1689 	    CASESDLK12TONAME(SDLK12_RALT, "right alt");
  1690 	    CASESDLK12TONAME(SDLK12_LALT, "left alt");
  1691 	    CASESDLK12TONAME(SDLK12_RMETA, "right meta");
  1692 	    CASESDLK12TONAME(SDLK12_LMETA, "left meta");
  1693 	    CASESDLK12TONAME(SDLK12_LSUPER, "left super");	/* "Windows" keys */
  1694 	    CASESDLK12TONAME(SDLK12_RSUPER, "right super");	
  1695 	    CASESDLK12TONAME(SDLK12_MODE, "alt gr");
  1696 	    CASESDLK12TONAME(SDLK12_COMPOSE, "compose");
  1697 
  1698 	    CASESDLK12TONAME(SDLK12_HELP, "help");
  1699 	    CASESDLK12TONAME(SDLK12_PRINT, "print screen");
  1700 	    CASESDLK12TONAME(SDLK12_SYSREQ, "sys req");
  1701 	    CASESDLK12TONAME(SDLK12_BREAK, "break");
  1702 	    CASESDLK12TONAME(SDLK12_MENU, "menu");
  1703 	    CASESDLK12TONAME(SDLK12_POWER, "power");
  1704 	    CASESDLK12TONAME(SDLK12_EURO, "euro");
  1705 	    CASESDLK12TONAME(SDLK12_UNDO, "undo");
  1706         #undef CASESDLK12TONAME
  1707         default: break;
  1708     }
  1709 
  1710     return (char *) "unknown key";
  1711 }
  1712 
  1713 static SDL12Key
  1714 Keysym20to12(const SDL_Keycode keysym20)
  1715 {
  1716     if ( ((int) keysym20) < 127 ) {  /* (most of) low-ASCII maps directly */
  1717         if (keysym20 == SDLK_PAUSE) {
  1718             return SDLK12_PAUSE;
  1719         } else if (keysym20 == SDLK_CLEAR) {
  1720             return SDLK12_CLEAR;
  1721         }
  1722         return (SDL12Key) keysym20;
  1723     }
  1724 
  1725     switch (keysym20) {
  1726         #define CASEKEYSYM20TO12(k20, k12) case SDLK_##k20: return SDLK12_##k12
  1727         CASEKEYSYM20TO12(KP_0, KP0);
  1728         CASEKEYSYM20TO12(KP_1, KP1);
  1729         CASEKEYSYM20TO12(KP_2, KP2);
  1730         CASEKEYSYM20TO12(KP_3, KP3);
  1731         CASEKEYSYM20TO12(KP_4, KP4);
  1732         CASEKEYSYM20TO12(KP_5, KP5);
  1733         CASEKEYSYM20TO12(KP_6, KP6);
  1734         CASEKEYSYM20TO12(KP_7, KP7);
  1735         CASEKEYSYM20TO12(KP_8, KP8);
  1736         CASEKEYSYM20TO12(KP_9, KP9);
  1737         CASEKEYSYM20TO12(NUMLOCKCLEAR, NUMLOCK);
  1738         CASEKEYSYM20TO12(SCROLLLOCK, SCROLLOCK);
  1739         CASEKEYSYM20TO12(RGUI, RMETA);
  1740         CASEKEYSYM20TO12(LGUI, LMETA);
  1741         CASEKEYSYM20TO12(PRINTSCREEN, PRINT);
  1742         #undef CASEKEYSYM20TO12
  1743 
  1744         #define CASEKEYSYM20TO12(k) case SDLK_##k: return SDLK12_##k
  1745         CASEKEYSYM20TO12(CLEAR);
  1746         CASEKEYSYM20TO12(PAUSE);
  1747         CASEKEYSYM20TO12(KP_PERIOD);
  1748         CASEKEYSYM20TO12(KP_DIVIDE);
  1749         CASEKEYSYM20TO12(KP_MULTIPLY);
  1750         CASEKEYSYM20TO12(KP_MINUS);
  1751         CASEKEYSYM20TO12(KP_PLUS);
  1752         CASEKEYSYM20TO12(KP_ENTER);
  1753         CASEKEYSYM20TO12(KP_EQUALS);
  1754         CASEKEYSYM20TO12(UP);
  1755         CASEKEYSYM20TO12(DOWN);
  1756         CASEKEYSYM20TO12(RIGHT);
  1757         CASEKEYSYM20TO12(LEFT);
  1758         CASEKEYSYM20TO12(INSERT);
  1759         CASEKEYSYM20TO12(HOME);
  1760         CASEKEYSYM20TO12(END);
  1761         CASEKEYSYM20TO12(PAGEUP);
  1762         CASEKEYSYM20TO12(PAGEDOWN);
  1763         CASEKEYSYM20TO12(F1);
  1764         CASEKEYSYM20TO12(F2);
  1765         CASEKEYSYM20TO12(F3);
  1766         CASEKEYSYM20TO12(F4);
  1767         CASEKEYSYM20TO12(F5);
  1768         CASEKEYSYM20TO12(F6);
  1769         CASEKEYSYM20TO12(F7);
  1770         CASEKEYSYM20TO12(F8);
  1771         CASEKEYSYM20TO12(F9);
  1772         CASEKEYSYM20TO12(F10);
  1773         CASEKEYSYM20TO12(F11);
  1774         CASEKEYSYM20TO12(F12);
  1775         CASEKEYSYM20TO12(F13);
  1776         CASEKEYSYM20TO12(F14);
  1777         CASEKEYSYM20TO12(F15);
  1778         CASEKEYSYM20TO12(CAPSLOCK);
  1779         CASEKEYSYM20TO12(RSHIFT);
  1780         CASEKEYSYM20TO12(LSHIFT);
  1781         CASEKEYSYM20TO12(RCTRL);
  1782         CASEKEYSYM20TO12(LCTRL);
  1783         CASEKEYSYM20TO12(RALT);
  1784         CASEKEYSYM20TO12(LALT);
  1785         CASEKEYSYM20TO12(MODE);
  1786         CASEKEYSYM20TO12(HELP);
  1787         CASEKEYSYM20TO12(SYSREQ);;
  1788         CASEKEYSYM20TO12(MENU);
  1789         CASEKEYSYM20TO12(POWER);
  1790         CASEKEYSYM20TO12(UNDO);
  1791         #undef CASEKEYSYM20TO12
  1792         default: break;
  1793     }
  1794 
  1795     FIXME("nothing maps to SDLK12_COMPOSE, SDLK12_BREAK, or SDLK12_EURO ...?");
  1796     FIXME("map some of the SDLK12_WORLD keys");
  1797     return SDLK12_UNKNOWN;
  1798 }
  1799 
  1800 static int
  1801 EventFilter20to12(void *data, SDL_Event *event20)
  1802 {
  1803     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1804     SDL12_Event event12;
  1805     int x, y;
  1806 
  1807     SDL_assert(data == NULL);  /* currently unused. */
  1808 
  1809     SDL20_zero(event12);
  1810 
  1811     switch (event20->type)
  1812     {
  1813         case SDL_QUIT:
  1814             event12.type = SDL12_QUIT;
  1815             break;
  1816 
  1817         case SDL_WINDOWEVENT:
  1818             switch (event20->window.event)
  1819             {
  1820                 case SDL_WINDOWEVENT_CLOSE:
  1821                     event12.type = SDL12_QUIT;
  1822                     break;
  1823 
  1824                 case SDL_WINDOWEVENT_SHOWN:
  1825                 case SDL_WINDOWEVENT_EXPOSED:
  1826                     event12.type = SDL12_VIDEOEXPOSE;
  1827                     break;
  1828 
  1829                 case SDL_WINDOWEVENT_RESIZED:
  1830                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1831                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1832                     event12.type = SDL12_VIDEORESIZE;
  1833                     event12.resize.w = event20->window.data1;
  1834                     event12.resize.h = event20->window.data2;
  1835                     break;
  1836 
  1837                 case SDL_WINDOWEVENT_MINIMIZED:
  1838                     event12.type = SDL12_ACTIVEEVENT;
  1839                     event12.active.gain = 0;
  1840                     event12.active.state = SDL12_APPACTIVE;
  1841                     break;
  1842 
  1843                 case SDL_WINDOWEVENT_RESTORED:
  1844                     event12.type = SDL12_ACTIVEEVENT;
  1845                     event12.active.gain = 1;
  1846                     event12.active.state = SDL12_APPACTIVE;
  1847                     break;
  1848 
  1849                 case SDL_WINDOWEVENT_ENTER:
  1850                     event12.type = SDL12_ACTIVEEVENT;
  1851                     event12.active.gain = 1;
  1852                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1853                     break;
  1854 
  1855                 case SDL_WINDOWEVENT_LEAVE:
  1856                     event12.type = SDL12_ACTIVEEVENT;
  1857                     event12.active.gain = 0;
  1858                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1859                     break;
  1860 
  1861                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1862                     event12.type = SDL12_ACTIVEEVENT;
  1863                     event12.active.gain = 1;
  1864                     event12.active.state = SDL12_APPINPUTFOCUS;
  1865                     break;
  1866 
  1867                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1868                     event12.type = SDL12_ACTIVEEVENT;
  1869                     event12.active.gain = 0;
  1870                     event12.active.state = SDL12_APPINPUTFOCUS;
  1871                     break;
  1872             }
  1873             break;
  1874 
  1875         // !!! FIXME: this is sort of a mess to convert.
  1876         case SDL_SYSWMEVENT: FIXME("write me"); return 0;
  1877 
  1878         case SDL_KEYUP:
  1879         case SDL_KEYDOWN:
  1880             if (event20->key.repeat) {
  1881                 return 0;  /* ignore 2.0-style key repeat events */
  1882             }
  1883             event12.key.keysym.sym = Keysym20to12(event20->key.keysym.sym);
  1884             if (event12.key.keysym.sym == SDLK12_UNKNOWN) {
  1885                 return 0;  /* drop it if we can't map it */
  1886             }
  1887             event12.type = (event20->type == SDL_KEYDOWN) ? SDL12_KEYDOWN : SDL12_KEYUP;
  1888             event12.key.which = 0;
  1889             event12.key.state = event20->key.state;
  1890             event12.key.keysym.scancode = (event20->key.keysym.scancode < 256) ? (Uint8) event20->key.keysym.scancode : 0;
  1891             event12.key.keysym.mod = event20->key.keysym.mod;  /* these match up between 1.2 and 2.0! */
  1892             event12.key.keysym.unicode = 0;  FIXME("unicode");
  1893             break;
  1894 
  1895         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  1896         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  1897 
  1898         case SDL_MOUSEMOTION:
  1899         	event12.type = SDL12_MOUSEMOTION;
  1900             event12.motion.which = (Uint8) event20->motion.which;
  1901             event12.motion.state = event20->motion.state;
  1902             event12.motion.x = (Uint16) event20->motion.x;
  1903             event12.motion.y = (Uint16) event20->motion.y;
  1904             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1905             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1906             break;
  1907 
  1908         case SDL_MOUSEBUTTONDOWN:
  1909         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1910             event12.button.which = (Uint8) event20->button.which;
  1911             event12.button.button = event20->button.button;
  1912             event12.button.state = event20->button.state;
  1913             event12.button.x = (Uint16) event20->button.x;
  1914             event12.button.y = (Uint16) event20->button.y;
  1915             break;
  1916 
  1917         case SDL_MOUSEBUTTONUP:
  1918         	event12.type = SDL12_MOUSEBUTTONUP;
  1919             event12.button.which = (Uint8) event20->button.which;
  1920             event12.button.button = event20->button.button;
  1921             event12.button.state = event20->button.state;
  1922             event12.button.x = (Uint16) event20->button.x;
  1923             event12.button.y = (Uint16) event20->button.y;
  1924             break;
  1925 
  1926         case SDL_MOUSEWHEEL:
  1927             if (event20->wheel.y == 0)
  1928                 break;  /* don't support horizontal wheels in 1.2. */
  1929 
  1930             event12.type = SDL12_MOUSEBUTTONDOWN;
  1931             event12.button.which = (Uint8) event20->wheel.which;
  1932             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1933             event12.button.state = SDL_GetMouseState(&x, &y);
  1934             event12.button.x = (Uint16) x;
  1935             event12.button.y = (Uint16) y;
  1936             PushEventIfNotFiltered(&event12);
  1937 
  1938             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1939             break;
  1940 
  1941         case SDL_JOYAXISMOTION:
  1942             event12.type = SDL12_JOYAXISMOTION;
  1943             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1944             event12.jaxis.axis = event20->jaxis.axis;
  1945             event12.jaxis.value = event20->jaxis.value;
  1946             break;
  1947 
  1948         case SDL_JOYBALLMOTION:
  1949             event12.type = SDL12_JOYBALLMOTION;
  1950             event12.jball.which = (Uint8) event20->jball.which;
  1951             event12.jball.ball = event20->jball.ball;
  1952             event12.jball.xrel = event20->jball.xrel;
  1953             event12.jball.yrel = event20->jball.yrel;
  1954             break;
  1955 
  1956         case SDL_JOYHATMOTION:
  1957             event12.type = SDL12_JOYHATMOTION;
  1958             event12.jhat.which = (Uint8) event20->jhat.which;
  1959             event12.jhat.hat = event20->jhat.hat;
  1960             event12.jhat.value = event20->jhat.value;
  1961             break;
  1962 
  1963         case SDL_JOYBUTTONDOWN:
  1964             event12.type = SDL12_JOYBUTTONDOWN;
  1965             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1966             event12.jbutton.button = event20->jbutton.button;
  1967             event12.jbutton.state = event20->jbutton.state;
  1968             break;
  1969 
  1970         case SDL_JOYBUTTONUP:
  1971             event12.type = SDL12_JOYBUTTONUP;
  1972             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1973             event12.jbutton.button = event20->jbutton.button;
  1974             event12.jbutton.state = event20->jbutton.state;
  1975             break;
  1976 
  1977         //case SDL_JOYDEVICEADDED:
  1978         //case SDL_JOYDEVICEREMOVED:
  1979 	    //case SDL_CONTROLLERAXISMOTION:
  1980 	    //case SDL_CONTROLLERBUTTONDOWN:
  1981 	    //case SDL_CONTROLLERBUTTONUP:
  1982 	    //case SDL_CONTROLLERDEVICEADDED:
  1983 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1984 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1985         //case SDL_FINGERDOWN:
  1986         //case SDL_FINGERUP:
  1987         //case SDL_FINGERMOTION:
  1988         //case SDL_DOLLARGESTURE:
  1989         //case SDL_DOLLARRECORD:
  1990         //case SDL_MULTIGESTURE:
  1991         //case SDL_CLIPBOARDUPDATE:
  1992         //case SDL_DROPFILE:
  1993 
  1994         default:
  1995             return 0;  /* drop everything else. */
  1996     }
  1997 
  1998     PushEventIfNotFiltered(&event12);
  1999 
  2000     return 0;  /* always drop it from the 2.0 event queue. */
  2001 }
  2002 
  2003 DECLSPEC void SDLCALL
  2004 SDL_SetEventFilter(SDL12_EventFilter filter12)
  2005 {
  2006     /* We always have a filter installed, but will call the app's too. */
  2007     EventFilter12 = filter12;
  2008 }
  2009 
  2010 DECLSPEC SDL12_EventFilter SDLCALL
  2011 SDL_GetEventFilter(void)
  2012 {
  2013     return EventFilter12;
  2014 }
  2015 
  2016 
  2017 static SDL12_Rect *
  2018 Rect20to12(const SDL_Rect *rect20, SDL12_Rect *rect12)
  2019 {
  2020     rect12->x = (Sint16) rect20->x;
  2021     rect12->y = (Sint16) rect20->y;
  2022     rect12->w = (Uint16) rect20->w;
  2023     rect12->h = (Uint16) rect20->h;
  2024     return rect12;
  2025 }
  2026 
  2027 static SDL_Rect *
  2028 Rect12to20(const SDL12_Rect *rect12, SDL_Rect *rect20)
  2029 {
  2030     rect20->x = (int) rect12->x;
  2031     rect20->y = (int) rect12->y;
  2032     rect20->w = (int) rect12->w;
  2033     rect20->h = (int) rect12->h;
  2034     return rect20;
  2035 }
  2036 
  2037 static SDL12_Surface *
  2038 Surface20to12(SDL_Surface *surface20)
  2039 {
  2040     SDL12_Surface *surface12 = NULL;
  2041     SDL12_Palette *palette12 = NULL;
  2042     SDL12_PixelFormat *format12 = NULL;
  2043     Uint32 flags = 0;
  2044 
  2045     if (!surface20)
  2046         return NULL;
  2047 
  2048     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  2049     if (!surface12)
  2050         goto failed;
  2051 
  2052     if (surface20->format->palette) {
  2053         palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  2054         if (!palette12)
  2055             goto failed;
  2056     }
  2057 
  2058     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  2059     if (!format12)
  2060         goto failed;
  2061 
  2062     if (palette12) {
  2063         SDL20_zerop(palette12);
  2064         SDL_assert(surface20->format->palette);
  2065         palette12->ncolors = surface20->format->palette->ncolors;
  2066         palette12->colors = surface20->format->palette->colors;
  2067     }
  2068 
  2069     SDL20_zerop(format12);
  2070     format12->palette = palette12;
  2071     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  2072     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  2073     format12->Rloss = surface20->format->Rloss;
  2074     format12->Gloss = surface20->format->Gloss;
  2075     format12->Bloss = surface20->format->Bloss;
  2076     format12->Aloss = surface20->format->Aloss;
  2077     format12->Rshift = surface20->format->Rshift;
  2078     format12->Gshift = surface20->format->Gshift;
  2079     format12->Bshift = surface20->format->Bshift;
  2080     format12->Ashift = surface20->format->Ashift;
  2081     format12->Rmask = surface20->format->Rmask;
  2082     format12->Gmask = surface20->format->Gmask;
  2083     format12->Bmask = surface20->format->Bmask;
  2084     format12->Amask = surface20->format->Amask;
  2085     FIXME("format12->colorkey");
  2086     FIXME("format12->alpha");
  2087 
  2088     SDL20_zerop(surface12);
  2089     flags = surface20->flags;
  2090     #ifdef SDL_SIMD_ALIGNED
  2091     flags &= ~SDL_SIMD_ALIGNED;  /* we don't need to map this to 1.2 */
  2092     #endif
  2093     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  2094     MAPSURFACEFLAGS(PREALLOC);
  2095     MAPSURFACEFLAGS(RLEACCEL);
  2096     /*MAPSURFACEFLAGS(DONTFREE);*/
  2097     #undef MAPSURFACEFLAGS
  2098     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  2099 
  2100     surface12->format = format12;
  2101     surface12->w = surface20->w;
  2102     surface12->h = surface20->h;
  2103     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  2104     surface12->pixels = surface20->pixels;
  2105     surface12->offset = 0;
  2106     surface12->surface20 = surface20;
  2107     Rect20to12(&surface20->clip_rect, &surface12->clip_rect);
  2108     surface12->refcount = surface20->refcount;
  2109 
  2110     return surface12;
  2111 
  2112 failed:
  2113     SDL20_free(surface12);
  2114     SDL20_free(palette12);
  2115     SDL20_free(format12);
  2116     return NULL;
  2117 }
  2118 
  2119 DECLSPEC SDL12_Surface * SDLCALL
  2120 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  2121 {
  2122     if (depth == 8) {
  2123         Rmask = Gmask = Bmask = Amask = 0;  // force a paletted surface.
  2124     }
  2125     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  2126     SDL12_Surface *surface12 = Surface20to12(surface20);
  2127     if (!surface12) {
  2128         SDL20_FreeSurface(surface20);
  2129         return NULL;
  2130     }
  2131 
  2132     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  2133     return surface12;
  2134 }
  2135 
  2136 DECLSPEC SDL12_Surface * SDLCALL
  2137 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  2138 {
  2139     if (depth == 8) {
  2140         Rmask = Gmask = Bmask = Amask = 0;  // force a paletted surface.
  2141     }
  2142     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  2143     SDL12_Surface *surface12 = Surface20to12(surface20);
  2144     if (!surface12) {
  2145         SDL20_FreeSurface(surface20);
  2146         return NULL;
  2147     }
  2148 
  2149     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  2150     return surface12;
  2151 }
  2152 
  2153 DECLSPEC void SDLCALL
  2154 SDL_FreeSurface(SDL12_Surface *surface12)
  2155 {
  2156     if (surface12) {
  2157         SDL20_FreeSurface(surface12->surface20);
  2158         if (surface12->format) {
  2159             SDL20_free(surface12->format->palette);
  2160             SDL20_free(surface12->format);
  2161         }
  2162         SDL20_free(surface12);
  2163     }
  2164 }
  2165 
  2166 DECLSPEC void SDLCALL
  2167 SDL_GetClipRect(SDL12_Surface *surface12, SDL12_Rect *rect)
  2168 {
  2169     if (surface12 && rect) {
  2170         SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL12_Rect));
  2171     }
  2172 }
  2173 
  2174 DECLSPEC SDL_bool SDLCALL
  2175 SDL_SetClipRect(SDL12_Surface *surface12, const SDL12_Rect *rect12)
  2176 {
  2177     SDL_bool retval = SDL_FALSE;
  2178     if (surface12)
  2179     {
  2180         SDL_Rect rect20;
  2181         retval = SDL20_SetClipRect(surface12->surface20, rect12 ? Rect12to20(rect12, &rect20) : NULL);
  2182         SDL20_GetClipRect(surface12->surface20, &rect20);
  2183         Rect20to12(&rect20, &surface12->clip_rect);
  2184     }
  2185     return retval;
  2186 }
  2187 
  2188 DECLSPEC int SDLCALL
  2189 SDL_FillRect(SDL12_Surface *dst, SDL12_Rect *dstrect12, Uint32 color)
  2190 {
  2191     SDL_Rect dstrect20;
  2192     const int retval = SDL20_FillRect(dst->surface20, dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL, color);
  2193     if (retval != -1)
  2194     {
  2195         if (dstrect12) {  /* 1.2 stores the clip intersection in dstrect */
  2196             SDL_Rect intersected20;
  2197             SDL20_IntersectRect(&dstrect20, &dst->surface20->clip_rect, &intersected20);
  2198             Rect20to12(&intersected20, dstrect12);
  2199         }
  2200     }
  2201     return retval;
  2202 }
  2203 
  2204 
  2205 static SDL_PixelFormat *
  2206 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  2207 {
  2208     if (format12->palette) {
  2209         palette20->ncolors = format12->palette->ncolors;
  2210         palette20->colors = format12->palette->colors;
  2211         palette20->version = 1;
  2212         palette20->refcount = 1;
  2213         format20->palette = palette20;
  2214     } else {
  2215         format20->palette = NULL;
  2216     }
  2217 
  2218     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  2219     format20->BitsPerPixel = format12->BitsPerPixel;
  2220     format20->BytesPerPixel = format12->BytesPerPixel;
  2221     format20->Rmask = format12->Rmask;
  2222     format20->Gmask = format12->Gmask;
  2223     format20->Bmask = format12->Bmask;
  2224     format20->Amask = format12->Amask;
  2225     format20->Rloss = format12->Rloss;
  2226     format20->Gloss = format12->Gloss;
  2227     format20->Bloss = format12->Bloss;
  2228     format20->Aloss = format12->Aloss;
  2229     format20->Rshift = format12->Rshift;
  2230     format20->Gshift = format12->Gshift;
  2231     format20->Bshift = format12->Bshift;
  2232     format20->Ashift = format12->Ashift;
  2233     format20->refcount = 1;
  2234     format20->next = NULL;
  2235     return format20;
  2236 }
  2237 
  2238 DECLSPEC Uint32 SDLCALL
  2239 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  2240 {
  2241     /* This is probably way slower than apps expect. */
  2242     SDL_PixelFormat format20;
  2243     SDL_Palette palette20;
  2244     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  2245 }
  2246 
  2247 DECLSPEC Uint32 SDLCALL
  2248 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  2249 {
  2250     /* This is probably way slower than apps expect. */
  2251     SDL_PixelFormat format20;
  2252     SDL_Palette palette20;
  2253     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  2254 }
  2255 
  2256 DECLSPEC void SDLCALL
  2257 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  2258 {
  2259     /* This is probably way slower than apps expect. */
  2260     SDL_PixelFormat format20;
  2261     SDL_Palette palette20;
  2262     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  2263 }
  2264 
  2265 DECLSPEC void SDLCALL
  2266 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  2267 {
  2268     /* This is probably way slower than apps expect. */
  2269     SDL_PixelFormat format20;
  2270     SDL_Palette palette20;
  2271     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  2272 }
  2273 
  2274 DECLSPEC const SDL12_VideoInfo * SDLCALL
  2275 SDL_GetVideoInfo(void)
  2276 {
  2277     SDL_DisplayMode mode;
  2278 
  2279     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  2280 
  2281     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  2282         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  2283         VideoInfo12.current_w = mode.w;
  2284         VideoInfo12.current_h = mode.h;
  2285         FIXME("vidinfo details commented out");
  2286         //VideoInfo12.wm_available = 1;
  2287         //VideoInfo12.video_mem = 1024 * 256;
  2288     }
  2289     return &VideoInfo12;
  2290 }
  2291 
  2292 DECLSPEC int SDLCALL
  2293 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  2294 {
  2295     int i, nummodes, actual_bpp = 0;
  2296 
  2297     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  2298         return 0;
  2299     }
  2300 
  2301     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  2302         SDL_DisplayMode mode;
  2303         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  2304         return SDL_BITSPERPIXEL(mode.format);
  2305     }
  2306 
  2307     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  2308     for (i = 0; i < nummodes; ++i) {
  2309         SDL_DisplayMode mode;
  2310         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  2311         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  2312             if (!mode.format) {
  2313                 return bpp;
  2314             }
  2315             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  2316                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  2317             }
  2318         }
  2319     }
  2320     return actual_bpp;
  2321 }
  2322 
  2323 DECLSPEC SDL12_Rect ** SDLCALL
  2324 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  2325 {
  2326     Uint32 fmt;
  2327     int i;
  2328 
  2329     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  2330         return NULL;
  2331     }
  2332 
  2333     if ((!format12) && (!VideoInfo12.vfmt)) {
  2334         SDL20_SetError("No pixel format specified");
  2335         return NULL;
  2336     }
  2337 
  2338     if (!(flags & SDL12_FULLSCREEN)) {
  2339         return (SDL12_Rect **) (-1);  /* any resolution is fine. */
  2340     }
  2341 
  2342     if (format12) {
  2343         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  2344     } else {
  2345         fmt = VideoInfo12.vfmt->format;
  2346     }
  2347 
  2348     for (i = 0; i < VideoModesCount; i++) {
  2349         VideoModeList *modes = &VideoModes[i];
  2350         if (modes->format == fmt) {
  2351             return modes->modes12;
  2352         }
  2353     }
  2354 
  2355     SDL20_SetError("No modes support requested pixel format");
  2356     return NULL;
  2357 }
  2358 
  2359 DECLSPEC void SDLCALL
  2360 SDL_FreeCursor(SDL12_Cursor *cursor12)
  2361 {
  2362     if (cursor12) {
  2363         if (cursor12->wm_cursor)
  2364             SDL20_FreeCursor(cursor12->wm_cursor);
  2365         SDL20_free(cursor12->data);
  2366         SDL20_free(cursor12->mask);
  2367         SDL20_free(cursor12);
  2368     }
  2369 }
  2370 
  2371 DECLSPEC SDL12_Cursor * SDLCALL
  2372 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  2373 {
  2374     const size_t datasize = h * (w / 8);
  2375     SDL_Cursor *cursor20 = NULL;
  2376     SDL12_Cursor *retval = NULL;
  2377 
  2378     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  2379     if (!retval)
  2380         goto outofmem;
  2381 
  2382     SDL20_zerop(retval);
  2383 
  2384     retval->data = (Uint8 *) SDL20_malloc(datasize);
  2385     if (!retval->data)
  2386         goto outofmem;
  2387 
  2388     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  2389     if (!retval->mask)
  2390         goto outofmem;
  2391 
  2392     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  2393     if (!cursor20)
  2394         goto failed;
  2395 
  2396     retval->area.w = w;
  2397     retval->area.h = h;
  2398     retval->hot_x = hot_x;
  2399     retval->hot_y = hot_y;
  2400     retval->wm_cursor = cursor20;
  2401     /* we always leave retval->save as null pointers. */
  2402 
  2403     SDL20_memcpy(retval->data, data, datasize);
  2404     SDL20_memcpy(retval->mask, mask, datasize);
  2405 
  2406     return retval;
  2407 
  2408 outofmem:
  2409     SDL20_OutOfMemory();
  2410 
  2411 failed:
  2412     SDL_FreeCursor(retval);
  2413     return NULL;
  2414 }
  2415 
  2416 DECLSPEC void SDLCALL
  2417 SDL_SetCursor(SDL12_Cursor *cursor)
  2418 {
  2419     CurrentCursor12 = cursor;
  2420     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  2421 }
  2422 
  2423 DECLSPEC SDL12_Cursor * SDLCALL
  2424 SDL_GetCursor(void)
  2425 {
  2426     return CurrentCursor12;
  2427 }
  2428 
  2429 static void
  2430 GetEnvironmentWindowPosition(int *x, int *y)
  2431 {
  2432     int display = VideoDisplayIndex;
  2433     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  2434     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  2435     if (window) {
  2436         if (SDL20_strcmp(window, "center") == 0) {
  2437             center = window;
  2438         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  2439             return;
  2440         }
  2441     }
  2442 
  2443     if (center) {
  2444         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  2445         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  2446     }
  2447 }
  2448 
  2449 static void
  2450 SetupScreenSaver(const int flags12)
  2451 {
  2452     const char *env;
  2453     SDL_bool allow_screensaver;
  2454 
  2455     /* Allow environment override of screensaver disable */
  2456     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  2457     if (env) {
  2458         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  2459     } else if (flags12 & SDL12_FULLSCREEN) {
  2460         allow_screensaver = SDL_FALSE;
  2461     } else {
  2462         allow_screensaver = SDL_TRUE;
  2463     }
  2464     if (allow_screensaver) {
  2465         SDL20_EnableScreenSaver();
  2466     } else {
  2467         SDL20_DisableScreenSaver();
  2468     }
  2469 }
  2470 
  2471 
  2472 static SDL12_Surface *
  2473 EndVidModeCreate(void)
  2474 {
  2475     if (VideoTexture20) {
  2476         SDL20_DestroyTexture(VideoTexture20);
  2477         VideoTexture20 = NULL;
  2478     }
  2479     if (VideoRenderer20) {
  2480         SDL20_DestroyRenderer(VideoRenderer20);
  2481         VideoRenderer20 = NULL;
  2482     }
  2483     if (VideoGLContext20) {
  2484         SDL20_GL_MakeCurrent(NULL, NULL);
  2485         SDL20_GL_DeleteContext(VideoGLContext20);
  2486         VideoGLContext20 = NULL;
  2487     }
  2488     if (VideoWindow20) {
  2489         SDL20_DestroyWindow(VideoWindow20);
  2490         VideoWindow20 = NULL;
  2491     }
  2492     if (VideoSurface12) {
  2493         SDL20_free(VideoSurface12->pixels);
  2494         VideoSurface12->pixels = NULL;
  2495         SDL_FreeSurface(VideoSurface12);
  2496         VideoSurface12 = NULL;
  2497     }
  2498     if (VideoConvertSurface20) {
  2499         SDL20_FreeSurface(VideoConvertSurface20);
  2500         VideoConvertSurface20 = NULL;
  2501     }
  2502     return NULL;
  2503 }
  2504 
  2505 
  2506 static SDL12_Surface *
  2507 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  2508 {
  2509     Uint32 rmask, gmask, bmask, amask;
  2510     int bpp;
  2511     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  2512         return NULL;
  2513     }
  2514     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  2515 }
  2516 
  2517 static SDL_Surface *
  2518 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  2519 {
  2520     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  2521     if (surface20) {
  2522         surface20->flags |= SDL_PREALLOC;
  2523         surface20->pixels = NULL;
  2524         surface20->w = width;
  2525         surface20->h = height;
  2526         surface20->pitch = 0;
  2527         SDL20_SetClipRect(surface20, NULL);
  2528     }
  2529     return surface20;
  2530 }
  2531 
  2532 
  2533 DECLSPEC SDL12_Surface * SDLCALL
  2534 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  2535 {
  2536     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  2537     SDL_DisplayMode dmode;
  2538     Uint32 fullscreen_flags20 = 0;
  2539     Uint32 appfmt;
  2540 
  2541     /* SDL_SetVideoMode() implicitly inits if necessary. */
  2542     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  2543         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  2544             return NULL;
  2545         }
  2546     }
  2547 
  2548     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  2549         FIXME("No OPENGLBLIT support at the moment");
  2550         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  2551         return NULL;
  2552     }
  2553 
  2554     FIXME("handle SDL_ANYFORMAT");
  2555 
  2556     if ((width < 0) || (height < 0)) {
  2557         SDL20_SetError("Invalid width or height");
  2558         return NULL;
  2559     }
  2560 
  2561     FIXME("There's an environment variable to choose a display");
  2562     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  2563         return NULL;
  2564     }
  2565 
  2566     if (width == 0) {
  2567         width = dmode.w;
  2568     }
  2569 
  2570     if (height == 0) {
  2571         height = dmode.h;
  2572     }
  2573 
  2574     if (bpp == 0) {
  2575         bpp = SDL_BITSPERPIXEL(dmode.format);
  2576     }
  2577 
  2578     switch (bpp) {
  2579         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  2580         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  2581         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  2582         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  2583         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  2584     }
  2585 
  2586     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  2587 
  2588     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  2589     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  2590 
  2591     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  2592         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  2593     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  2594         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  2595     } else if (VideoGLContext20) {
  2596         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  2597         SDL20_GL_MakeCurrent(NULL, NULL);
  2598         SDL20_GL_DeleteContext(VideoGLContext20);
  2599         VideoGLContext20 = NULL;
  2600     }
  2601 
  2602     if (flags12 & SDL12_FULLSCREEN) {
  2603         // OpenGL tries to force the real resolution requested, but for
  2604         //  software rendering, we're just going to push it off onto the
  2605         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  2606         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  2607         if (flags12 & SDL12_OPENGL) {
  2608             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  2609         } else {
  2610             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  2611         }
  2612     }
  2613 
  2614     if (!VideoWindow20) {  /* create it */
  2615         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  2616         Uint32 flags20 = fullscreen_flags20;
  2617         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  2618         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  2619         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  2620 
  2621         /* most platforms didn't check these environment variables, but the major
  2622            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  2623         GetEnvironmentWindowPosition(&x, &y);
  2624 
  2625         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  2626         if (!VideoWindow20) {
  2627             return EndVidModeCreate();
  2628         }
  2629     } else {  /* resize it */
  2630         SDL20_SetWindowSize(VideoWindow20, width, height);
  2631         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  2632         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  2633         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  2634     }
  2635 
  2636     if (VideoSurface12) {
  2637         SDL20_free(VideoSurface12->pixels);
  2638     } else {
  2639         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  2640         if (!VideoSurface12) {
  2641             return EndVidModeCreate();
  2642         }
  2643     }
  2644 
  2645     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  2646     VideoSurface12->flags |= SDL12_PREALLOC;
  2647     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  2648     VideoSurface12->w = VideoSurface12->surface20->w = width;
  2649     VideoSurface12->h = VideoSurface12->surface20->h = height;
  2650     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  2651     SDL_SetClipRect(VideoSurface12, NULL);
  2652 
  2653     if (flags12 & SDL12_FULLSCREEN) {
  2654         VideoSurface12->flags |= SDL12_FULLSCREEN;
  2655     } else {
  2656         VideoSurface12->flags &= ~SDL12_FULLSCREEN;
  2657     }
  2658 
  2659     if (flags12 & SDL12_OPENGL) {
  2660         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  2661         SDL_assert(!VideoRenderer20);
  2662         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  2663         if (!VideoGLContext20) {
  2664             return EndVidModeCreate();
  2665         }
  2666 
  2667         VideoSurface12->flags |= SDL12_OPENGL;
  2668     } else {
  2669         /* always use a renderer for non-OpenGL windows. */
  2670         SDL_RendererInfo rinfo;
  2671         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  2672         if (!VideoRenderer20) {
  2673             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  2674         }
  2675         if (!VideoRenderer20) {
  2676             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_PRESENTVSYNC);
  2677         }
  2678         if (!VideoRenderer20) {
  2679             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  2680         }
  2681         if (!VideoRenderer20) {
  2682             return EndVidModeCreate();
  2683         }
  2684 
  2685         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  2686         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  2687         SDL20_RenderClear(VideoRenderer20);
  2688         SDL20_RenderPresent(VideoRenderer20);
  2689         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  2690 
  2691         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  2692             return EndVidModeCreate();
  2693         }
  2694 
  2695         if (VideoTexture20) {
  2696             SDL20_DestroyTexture(VideoTexture20);
  2697         }
  2698 
  2699         if (VideoConvertSurface20) {
  2700             SDL20_FreeSurface(VideoConvertSurface20);
  2701             VideoConvertSurface20 = NULL;
  2702         }
  2703 
  2704         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  2705         if (!VideoTexture20) {
  2706             return EndVidModeCreate();
  2707         }
  2708 
  2709         if (rinfo.texture_formats[0] != appfmt) {
  2710             /* need to convert between app's format and texture format */
  2711             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  2712             if (!VideoConvertSurface20) {
  2713                 return EndVidModeCreate();
  2714             }
  2715         }
  2716 
  2717         VideoSurface12->flags &= ~SDL12_OPENGL;
  2718         VideoSurface12->flags |= SDL12_DOUBLEBUF;
  2719         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  2720         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  2721         if (!VideoSurface12->pixels) {
  2722             SDL20_OutOfMemory();
  2723             return EndVidModeCreate();
  2724         }
  2725 
  2726         /* fill in the same default palette that SDL 1.2 does... */
  2727         if (VideoSurface12->format->BitsPerPixel == 8) {
  2728             int i;
  2729             SDL_Color *color = VideoSurface12->format->palette->colors;
  2730             for (i = 0; i < 256; i++, color++) {
  2731                 { const int x = i & 0xe0; color->r = x | x >> 3 | x >> 6; }
  2732                 { const int x = (i << 3) & 0xe0; color->g = x | x >> 3 | x >> 6; }
  2733                 { const int x = (i & 0x3) | ((i & 0x3) << 2); color->b = x | x << 4; }
  2734                 color->a = 255;
  2735             }
  2736         }
  2737     }
  2738 
  2739     SDL20_RaiseWindow(VideoWindow20);
  2740 
  2741     FIXME("setup screen saver");
  2742 
  2743     VideoSurfaceUpdated = SDL_FALSE;
  2744 
  2745     return VideoSurface12;
  2746 }
  2747 
  2748 DECLSPEC SDL12_Surface * SDLCALL
  2749 SDL_GetVideoSurface(void)
  2750 {
  2751     return VideoSurface12;
  2752 }
  2753 
  2754 DECLSPEC int SDLCALL
  2755 SDL_UpperBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
  2756 {
  2757     SDL_Rect srcrect20, dstrect20;
  2758     const int retval = SDL20_UpperBlit(src->surface20,
  2759                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  2760                                        dst->surface20,
  2761                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  2762 
  2763     if (srcrect12) {
  2764         Rect20to12(&srcrect20, srcrect12);
  2765     }
  2766 
  2767     if (dstrect12) {
  2768         Rect20to12(&dstrect20, dstrect12);
  2769     }
  2770 
  2771     return retval;
  2772 }
  2773 
  2774 DECLSPEC int SDLCALL
  2775 SDL_LowerBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
  2776 {
  2777     SDL_Rect srcrect20, dstrect20;
  2778     const int retval = SDL20_LowerBlit(src->surface20,
  2779                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  2780                                        dst->surface20,
  2781                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  2782 
  2783     if (srcrect12) {
  2784         Rect20to12(&srcrect20, srcrect12);
  2785     }
  2786 
  2787     if (srcrect12) {
  2788         Rect20to12(&dstrect20, dstrect12);
  2789     }
  2790 
  2791     return retval;
  2792 }
  2793 
  2794 DECLSPEC int SDLCALL
  2795 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  2796 {
  2797     FIXME("write me");
  2798     return SDL20_Unsupported();
  2799 }
  2800 
  2801 DECLSPEC int SDLCALL
  2802 SDL_LockSurface(SDL12_Surface *surface12)
  2803 {
  2804     const int retval = SDL20_LockSurface(surface12->surface20);
  2805     surface12->pixels = surface12->surface20->pixels;
  2806     surface12->pitch = surface12->surface20->pitch;
  2807     return retval;
  2808 }
  2809 
  2810 DECLSPEC void SDLCALL
  2811 SDL_UnlockSurface(SDL12_Surface *surface12)
  2812 {
  2813     SDL20_UnlockSurface(surface12->surface20);
  2814     surface12->pixels = surface12->surface20->pixels;
  2815     surface12->pitch = surface12->surface20->pitch;
  2816 }
  2817 
  2818 DECLSPEC SDL12_Surface * SDLCALL
  2819 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
  2820 {
  2821     Uint32 flags20 = 0;
  2822     SDL_PixelFormat format20;
  2823     SDL_Palette palette20;
  2824     SDL_Surface *surface20;
  2825     SDL12_Surface *retval = NULL;
  2826 
  2827     if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
  2828     if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
  2829 
  2830     surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
  2831     if (surface20) {
  2832         retval = Surface20to12(surface20);
  2833         if (!retval) {
  2834             SDL20_FreeSurface(surface20);
  2835         }
  2836     }
  2837     return retval;
  2838 }
  2839 
  2840 DECLSPEC SDL12_Surface * SDLCALL
  2841 SDL_DisplayFormat(SDL12_Surface *surface12)
  2842 {
  2843     const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
  2844     return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
  2845 }
  2846 
  2847 DECLSPEC SDL12_Surface * SDLCALL
  2848 SDL_DisplayFormatAlpha(SDL12_Surface *surface12)
  2849 {
  2850     return SDL_DisplayFormat(surface12);
  2851 }
  2852 
  2853 static void
  2854 PresentScreen(void)
  2855 {
  2856     void *pixels = NULL;
  2857     int pitch = 0;
  2858 
  2859     SDL_assert(VideoSurface12 != NULL);
  2860 
  2861     if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
  2862         return;  /* oh well */
  2863     }
  2864 
  2865     FIXME("Maybe lock texture always, until present, if no conversion needed?");
  2866     if (VideoConvertSurface20) {
  2867         VideoConvertSurface20->pixels = pixels;
  2868         VideoConvertSurface20->pitch = pitch;
  2869         SDL20_UpperBlit(VideoSurface12->surface20, NULL, VideoConvertSurface20, NULL);
  2870         VideoConvertSurface20->pixels = NULL;
  2871         VideoConvertSurface20->pitch = 0;
  2872     } else if (pitch == VideoSurface12->pitch) {
  2873         SDL_memcpy(pixels, VideoSurface12->pixels, pitch * VideoSurface12->h);
  2874     } else {
  2875         const int srcpitch = VideoSurface12->pitch;
  2876         const int cpy = SDL_min(srcpitch, pitch);
  2877         const int h = VideoSurface12->h;
  2878         char *dst = (char *) pixels;
  2879         char *src = (char *) VideoSurface12->pixels;
  2880         for (int i = 0; i < h; i++) {
  2881             SDL_memcpy(dst, src, cpy);
  2882             src += srcpitch;
  2883             dst += pitch;
  2884         }
  2885     }
  2886 
  2887     SDL20_UnlockTexture(VideoTexture20);
  2888     SDL20_RenderCopy(VideoRenderer20, VideoTexture20, NULL, NULL);
  2889     SDL20_RenderPresent(VideoRenderer20);
  2890     VideoSurfaceUpdated = SDL_FALSE;
  2891 }
  2892 
  2893 DECLSPEC void SDLCALL
  2894 SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
  2895 {
  2896     /* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
  2897     /* (UpdateRect, singular, does...) */
  2898     if (surface12->flags & SDL12_OPENGL) {
  2899         SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2900         return;
  2901     }
  2902 
  2903     // everything else is marked SDL12_DOUBLEBUF and SHOULD BE a no-op here,
  2904     //  but in practice most apps never got a double-buffered surface and
  2905     //  don't handle it correctly, so we have to work around it.
  2906     if (surface12 == VideoSurface12) {
  2907         SDL_bool whole_screen = SDL_FALSE;
  2908         if (numrects == 1) {
  2909             const SDL12_Rect *r = rects12;
  2910             if (!r->x && !r->y && !r->w && !r->h) {
  2911                 whole_screen = SDL_TRUE;
  2912             } else if (!r->x && !r->y && (r->w == surface12->w) && (r->h == surface12->h)) {
  2913                 whole_screen = SDL_TRUE;
  2914             }
  2915         }
  2916                 
  2917         if (whole_screen) {  
  2918             PresentScreen();  // flip it now.
  2919         } else {
  2920             VideoSurfaceUpdated = SDL_TRUE;  // flip it later.
  2921         }
  2922     }
  2923 }
  2924 
  2925 DECLSPEC void SDLCALL
  2926 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  2927 {
  2928     if (screen12) {
  2929         SDL12_Rect rect12;
  2930         rect12.x = (Sint16) x;
  2931         rect12.y = (Sint16) y;
  2932         rect12.w = (Uint16) (w ? w : screen12->w);
  2933         rect12.h = (Uint16) (h ? h : screen12->h);
  2934         SDL_UpdateRects(screen12, 1, &rect12);
  2935     }
  2936 }
  2937 
  2938 DECLSPEC int SDLCALL
  2939 SDL_Flip(SDL12_Surface *surface12)
  2940 {
  2941     if (surface12->flags & SDL12_OPENGL) {
  2942         return SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2943     }
  2944 
  2945     if (surface12 == VideoSurface12) {
  2946         PresentScreen();
  2947     }
  2948 
  2949     return 0;
  2950 }
  2951 
  2952 DECLSPEC void SDLCALL
  2953 SDL_PumpEvents(void)
  2954 {
  2955     // If the app is doing dirty rectangles, we set a flag and present the
  2956     //  screen surface when they pump for new events, which we consider a
  2957     //  sign that they are done rendering for the current frame.
  2958     if (VideoSurfaceUpdated) {
  2959         PresentScreen();
  2960     }
  2961     SDL20_PumpEvents();
  2962 }
  2963 
  2964 DECLSPEC void SDLCALL
  2965 SDL_WM_SetCaption(const char *title, const char *icon)
  2966 {
  2967     if (WindowTitle) {
  2968         SDL20_free(WindowTitle);
  2969     }
  2970     if (WindowIconTitle) {
  2971         SDL20_free(WindowIconTitle);
  2972     }
  2973     WindowTitle = title ? SDL_strdup(title) : NULL;
  2974     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  2975     if (VideoWindow20) {
  2976         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  2977     }
  2978 }
  2979 
  2980 DECLSPEC void SDLCALL
  2981 SDL_WM_GetCaption(const char **title, const char **icon)
  2982 {
  2983     if (title) {
  2984         *title = WindowTitle;
  2985     }
  2986     if (icon) {
  2987         *icon = WindowIconTitle;
  2988     }
  2989 }
  2990 
  2991 DECLSPEC void SDLCALL
  2992 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2993 {
  2994     FIXME("write me");
  2995     SDL20_Unsupported();
  2996 }
  2997 
  2998 DECLSPEC int SDLCALL
  2999 SDL_WM_IconifyWindow(void)
  3000 {
  3001     SDL20_MinimizeWindow(VideoWindow20);
  3002     return 0;
  3003 }
  3004 
  3005 DECLSPEC int SDLCALL
  3006 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  3007 {
  3008     int retval = 0;
  3009     if (surface == VideoSurface12) {
  3010         SDL_assert(VideoWindow20);
  3011         const Uint32 flags20 = SDL20_GetWindowFlags(VideoWindow20);
  3012         if (flags20 & SDL_WINDOW_FULLSCREEN) {
  3013             SDL_assert(VideoSurface12->flags & SDL12_FULLSCREEN);
  3014             retval = (SDL20_SetWindowFullscreen(VideoWindow20, 0) == 0);
  3015             if (retval) {
  3016                 VideoSurface12->flags &= ~SDL12_FULLSCREEN;
  3017             }
  3018         } else {
  3019             SDL_assert((VideoSurface12->flags & SDL12_FULLSCREEN) == 0);
  3020             const Uint32 newflags20 = (VideoSurface12->flags & SDL12_OPENGL) ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP;
  3021             retval = (SDL20_SetWindowFullscreen(VideoWindow20, newflags20) == 0);
  3022             if (retval) {
  3023                 VideoSurface12->flags |= SDL12_FULLSCREEN;
  3024             }
  3025         }
  3026         if (retval && VideoRenderer20) {
  3027             SDL20_RenderSetLogicalSize(VideoRenderer20, VideoSurface12->w, VideoSurface12->h);
  3028         }
  3029     }
  3030     return retval;
  3031 }
  3032 
  3033 typedef enum
  3034 {
  3035     SDL12_GRAB_QUERY = -1,
  3036     SDL12_GRAB_OFF = 0,
  3037     SDL12_GRAB_ON = 1
  3038 } SDL12_GrabMode;
  3039 
  3040 static void
  3041 UpdateRelativeMouseMode(void)
  3042 {
  3043     // in SDL 1.2, hiding+grabbing the cursor was like SDL2's relative mouse mode.
  3044     if (VideoWindow20) {
  3045         const int visible = SDL20_ShowCursor(-1);
  3046         const SDL_bool grabbed = SDL20_GetWindowGrab(VideoWindow20);
  3047         SDL20_SetRelativeMouseMode((!visible && grabbed) ? SDL_TRUE : SDL_FALSE);
  3048     }
  3049 }
  3050 
  3051 DECLSPEC int SDLCALL
  3052 SDL_ShowCursor(int toggle)
  3053 {
  3054     const int retval = SDL20_ShowCursor(toggle);
  3055     if (toggle >= 0) {
  3056         UpdateRelativeMouseMode();
  3057     }
  3058     return retval;
  3059 }
  3060 
  3061 
  3062 DECLSPEC SDL12_GrabMode SDLCALL
  3063 SDL_WM_GrabInput(SDL12_GrabMode mode)
  3064 {
  3065     if (mode != SDL12_GRAB_QUERY) {
  3066         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  3067         UpdateRelativeMouseMode();
  3068     }
  3069     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  3070 }
  3071 
  3072 DECLSPEC void SDLCALL
  3073 SDL_WarpMouse(Uint16 x, Uint16 y)
  3074 {
  3075     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  3076 }
  3077 
  3078 DECLSPEC Uint8 SDLCALL
  3079 SDL_GetAppState(void)
  3080 {
  3081     Uint8 state12 = 0;
  3082     Uint32 flags20 = 0;
  3083 
  3084     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  3085     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  3086         state12 |= SDL12_APPACTIVE;
  3087     }
  3088     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  3089         state12 |= SDL12_APPINPUTFOCUS;
  3090     }
  3091     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  3092         state12 |= SDL12_APPMOUSEFOCUS;
  3093     }
  3094     return state12;
  3095 }
  3096 
  3097 DECLSPEC int SDLCALL
  3098 SDL_SetColorKey(SDL12_Surface *surface12, Uint32 flag12, Uint32 key)
  3099 {
  3100     const SDL_bool addkey = (flag12 & SDL12_SRCCOLORKEY) ? SDL_TRUE : SDL_FALSE;
  3101     const int retval = SDL20_SetColorKey(surface12->surface20, addkey, key);
  3102     if (SDL20_GetColorKey(surface12->surface20, &surface12->format->colorkey) < 0) {
  3103         surface12->format->colorkey = 0;
  3104     }
  3105     return retval;
  3106 }
  3107 
  3108 DECLSPEC int SDLCALL
  3109 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  3110                int firstcolor, int ncolors)
  3111 {
  3112     FIXME("write me");
  3113     return SDL20_Unsupported();
  3114 }
  3115 
  3116 DECLSPEC int SDLCALL
  3117 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  3118               int ncolors)
  3119 {
  3120     FIXME("write me");
  3121     return SDL20_Unsupported();
  3122 }
  3123 
  3124 DECLSPEC int SDLCALL
  3125 SDL_GetWMInfo(SDL_SysWMinfo * info)
  3126 {
  3127     FIXME("write me");
  3128     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  3129     return SDL20_Unsupported();
  3130 }
  3131 
  3132 DECLSPEC SDL12_Overlay * SDLCALL
  3133 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  3134 {
  3135     FIXME("write me");
  3136     SDL20_Unsupported();
  3137     return NULL;
  3138 }
  3139 
  3140 DECLSPEC int SDLCALL
  3141 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  3142 {
  3143     FIXME("write me");
  3144     return SDL20_Unsupported();
  3145 }
  3146 
  3147 DECLSPEC void SDLCALL
  3148 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  3149 {
  3150     FIXME("write me");
  3151 }
  3152 
  3153 DECLSPEC int SDLCALL
  3154 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL12_Rect * dstrect12)
  3155 {
  3156     FIXME("write me");
  3157     return SDL20_Unsupported();
  3158 }
  3159 
  3160 DECLSPEC void SDLCALL
  3161 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  3162 {
  3163     FIXME("write me");
  3164 }
  3165 
  3166 DECLSPEC int SDLCALL
  3167 SDL_GL_LoadLibrary(const char *libname)
  3168 {
  3169     /* SDL 1.2 would unload the previous library if one was loaded. SDL2
  3170        reports an error if one is already loaded, and sometimes loads it
  3171        internally for some video targets, so unloading it probably isn't safe.
  3172        There really isn't a good reason to be using anything other than the
  3173        system OpenGL in 2019, so we ignore the error in this case to match 1.2
  3174        behavior, even if you were going to load a different library this time.
  3175        Oh well. */
  3176     const int rc = SDL20_GL_LoadLibrary(libname);
  3177     if (rc == -1) {
  3178         const char *err = SDL20_GetError();
  3179         if (SDL20_strcmp(err, "OpenGL library already loaded") == 0) {
  3180             return 0;
  3181         }
  3182 
  3183         /* reset the actual error. */
  3184         char *dup = SDL20_strdup(err);
  3185         if (!dup) {
  3186             SDL20_OutOfMemory();
  3187         } else {
  3188             SDL20_SetError(dup);
  3189             SDL20_free(dup);
  3190         }
  3191     }
  3192     return rc;
  3193 }
  3194 
  3195 
  3196 DECLSPEC int SDLCALL
  3197 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  3198 {
  3199     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  3200         return SDL20_SetError("Unknown GL attribute");
  3201 
  3202     /* swap control was moved out of this API, everything else lines up. */
  3203     if (attr == SDL12_GL_SWAP_CONTROL)
  3204     {
  3205         SwapInterval = value;
  3206         FIXME("Actually set swap interval somewhere");
  3207         return 0;
  3208     }
  3209 
  3210     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  3211 }
  3212 
  3213 DECLSPEC int SDLCALL
  3214 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  3215 {
  3216     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  3217         return SDL20_SetError("Unknown GL attribute");
  3218 
  3219     /* swap control was moved out of this API, everything else lines up. */
  3220     if (attr == SDL12_GL_SWAP_CONTROL)
  3221     {
  3222         *value = SDL20_GL_GetSwapInterval();
  3223         return 0;
  3224     }
  3225 
  3226     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  3227 }
  3228 
  3229 
  3230 DECLSPEC void SDLCALL
  3231 SDL_GL_SwapBuffers(void)
  3232 {
  3233     if (VideoWindow20)
  3234         SDL20_GL_SwapWindow(VideoWindow20);
  3235 }
  3236 
  3237 DECLSPEC int SDLCALL
  3238 SDL_SetGamma(float red, float green, float blue)
  3239 {
  3240     Uint16 red_ramp[256];
  3241     Uint16 green_ramp[256];
  3242     Uint16 blue_ramp[256];
  3243 
  3244     SDL20_CalculateGammaRamp(red, red_ramp);
  3245     if (green == red) {
  3246         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  3247     } else {
  3248         SDL20_CalculateGammaRamp(green, green_ramp);
  3249     }
  3250     if (blue == red) {
  3251         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  3252     } else if (blue == green) {
  3253         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  3254     } else {
  3255         SDL20_CalculateGammaRamp(blue, blue_ramp);
  3256     }
  3257     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  3258 }
  3259 
  3260 DECLSPEC int SDLCALL
  3261 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  3262 {
  3263     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  3264 }
  3265 
  3266 DECLSPEC int SDLCALL
  3267 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  3268 {
  3269     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  3270 }
  3271 
  3272 DECLSPEC int SDLCALL
  3273 SDL_EnableKeyRepeat(int delay, int interval)
  3274 {
  3275     FIXME("write me");
  3276     return 0;
  3277 }
  3278 
  3279 DECLSPEC void SDLCALL
  3280 SDL_GetKeyRepeat(int *delay, int *interval)
  3281 {
  3282     FIXME("write me");
  3283     if (delay) {
  3284         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  3285     }
  3286     if (interval) {
  3287         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  3288     }
  3289 }
  3290 
  3291 DECLSPEC int SDLCALL
  3292 SDL_EnableUNICODE(int enable)
  3293 {
  3294     FIXME("write me");
  3295     return SDL20_Unsupported();
  3296 }
  3297 
  3298 static Uint32
  3299 SetTimerOld_Callback(Uint32 interval, void* param)
  3300 {
  3301     return ((SDL12_TimerCallback)param)(interval);
  3302 }
  3303 
  3304 DECLSPEC int SDLCALL
  3305 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  3306 {
  3307     static SDL_TimerID compat_timer;
  3308 
  3309     if (compat_timer) {
  3310         SDL20_RemoveTimer(compat_timer);
  3311         compat_timer = 0;
  3312     }
  3313 
  3314     if (interval && callback) {
  3315         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  3316         if (!compat_timer) {
  3317             return -1;
  3318         }
  3319     }
  3320     return 0;
  3321 }
  3322 
  3323 DECLSPEC int SDLCALL
  3324 SDL_putenv(const char *_var)
  3325 {
  3326     char *ptr = NULL;
  3327     char *var = SDL20_strdup(_var);
  3328     if (var == NULL) {
  3329         return -1;  /* we don't set errno. */
  3330     }
  3331 
  3332     ptr = SDL20_strchr(var, '=');
  3333     if (ptr == NULL) {
  3334         SDL20_free(var);
  3335         return -1;
  3336     }
  3337 
  3338     *ptr = '\0';  /* split the string into name and value. */
  3339     SDL20_setenv(var, ptr + 1, 1);
  3340     SDL20_free(var);
  3341     return 0;
  3342 }
  3343 
  3344 
  3345 
  3346 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  3347 
  3348 typedef void *SDL12_CD;  /* close enough.  :) */
  3349 typedef int SDL12_CDstatus;  /* close enough.  :) */
  3350 
  3351 DECLSPEC int SDLCALL
  3352 SDL_CDNumDrives(void)
  3353 {
  3354     FIXME("should return -1 without SDL_INIT_CDROM");
  3355     return 0;
  3356 }
  3357 
  3358 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  3359 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  3360 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3361 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  3362 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  3363 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3364 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3365 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3366 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3367 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  3368 
  3369 
  3370 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  3371 DECLSPEC SDL_Thread * SDLCALL
  3372 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  3373 {
  3374     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  3375 }
  3376 #else
  3377 DECLSPEC SDL_Thread * SDLCALL
  3378 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  3379 {
  3380     return SDL20_CreateThread(fn, NULL, data);
  3381 }
  3382 #endif
  3383 
  3384 DECLSPEC int SDLCALL
  3385 SDL_mutexP(SDL_mutex *mutex)
  3386 {
  3387     return SDL20_LockMutex(mutex);
  3388 }
  3389 
  3390 DECLSPEC int SDLCALL
  3391 SDL_mutexV(SDL_mutex *mutex)
  3392 {
  3393     return SDL20_UnlockMutex(mutex);
  3394 }
  3395 
  3396 DECLSPEC void SDLCALL
  3397 SDL_KillThread(SDL_Thread *thread)
  3398 {
  3399     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  3400     fprintf(stderr,
  3401         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  3402         "This program should be fixed. No thread was actually harmed.\n");
  3403 }
  3404 
  3405 /* This changed from an opaque pointer to an int in 2.0. */
  3406 typedef struct _SDL12_TimerID *SDL12_TimerID;
  3407 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  3408 
  3409 
  3410 DECLSPEC SDL12_TimerID SDLCALL
  3411 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  3412 {
  3413     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  3414 }
  3415 
  3416 DECLSPEC SDL_bool SDLCALL
  3417 SDL_RemoveTimer(SDL12_TimerID id)
  3418 {
  3419     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  3420 }
  3421 
  3422 
  3423 typedef struct SDL12_RWops {
  3424     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  3425     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  3426     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  3427     int (SDLCALL *close)(struct SDL12_RWops *context);
  3428     Uint32 type;
  3429     void *padding[8];
  3430     SDL_RWops *rwops20;
  3431 } SDL12_RWops;
  3432 
  3433 
  3434 DECLSPEC SDL12_RWops * SDLCALL
  3435 SDL_AllocRW(void)
  3436 {
  3437     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  3438     if (!rwops)
  3439         SDL20_OutOfMemory();
  3440     return rwops;
  3441 }
  3442 
  3443 DECLSPEC void SDLCALL
  3444 SDL_FreeRW(SDL12_RWops *rwops12)
  3445 {
  3446     SDL20_free(rwops12);
  3447 }
  3448 
  3449 static int SDLCALL
  3450 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  3451 {
  3452     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  3453 }
  3454 
  3455 static int SDLCALL
  3456 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  3457 {
  3458     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  3459 }
  3460 
  3461 static int SDLCALL
  3462 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  3463 {
  3464     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  3465 }
  3466 
  3467 static int SDLCALL
  3468 RWops20to12_close(struct SDL12_RWops *rwops12)
  3469 {
  3470     int rc = 0;
  3471     if (rwops12)
  3472     {
  3473         rc = rwops12->rwops20->close(rwops12->rwops20);
  3474         if (rc == 0)
  3475             SDL_FreeRW(rwops12);
  3476     }
  3477     return rc;
  3478 }
  3479 
  3480 static SDL12_RWops *
  3481 RWops20to12(SDL_RWops *rwops20)
  3482 {
  3483     SDL12_RWops *rwops12;
  3484 
  3485     if (!rwops20)
  3486         return NULL;
  3487 
  3488     rwops12 = SDL_AllocRW();
  3489     if (!rwops12)
  3490         return NULL;
  3491 
  3492     SDL20_zerop(rwops12);
  3493     rwops12->type = rwops20->type;
  3494     rwops12->rwops20 = rwops20;
  3495     rwops12->seek = RWops20to12_seek;
  3496     rwops12->read = RWops20to12_read;
  3497     rwops12->write = RWops20to12_write;
  3498     rwops12->close = RWops20to12_close;
  3499 
  3500     return rwops12;
  3501 }
  3502 
  3503 DECLSPEC SDL12_RWops * SDLCALL
  3504 SDL_RWFromFile(const char *file, const char *mode)
  3505 {
  3506     if ( !file || !*file || !mode || !*mode ) {
  3507         SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
  3508         return NULL;
  3509     }
  3510     return RWops20to12(SDL20_RWFromFile(file, mode));
  3511 }
  3512 
  3513 DECLSPEC SDL12_RWops * SDLCALL
  3514 SDL_RWFromFP(FILE *io, int autoclose)
  3515 {
  3516     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  3517 }
  3518 
  3519 DECLSPEC SDL12_RWops * SDLCALL
  3520 SDL_RWFromMem(void *mem, int size)
  3521 {
  3522     return RWops20to12(SDL20_RWFromMem(mem, size));
  3523 }
  3524 
  3525 DECLSPEC SDL12_RWops * SDLCALL
  3526 SDL_RWFromConstMem(const void *mem, int size)
  3527 {
  3528     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  3529 }
  3530 
  3531 #define READ_AND_BYTESWAP(endian, bits) \
  3532     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  3533         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  3534         return SDL_Swap##endian##bits(val); \
  3535     }
  3536 
  3537 READ_AND_BYTESWAP(LE,16)
  3538 READ_AND_BYTESWAP(BE,16)
  3539 READ_AND_BYTESWAP(LE,32)
  3540 READ_AND_BYTESWAP(BE,32)
  3541 READ_AND_BYTESWAP(LE,64)
  3542 READ_AND_BYTESWAP(BE,64)
  3543 #undef READ_AND_BYTESWAP
  3544 
  3545 #define BYTESWAP_AND_WRITE(endian, bits) \
  3546     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  3547         val = SDL_Swap##endian##bits(val); \
  3548         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  3549     }
  3550 BYTESWAP_AND_WRITE(LE,16)
  3551 BYTESWAP_AND_WRITE(BE,16)
  3552 BYTESWAP_AND_WRITE(LE,32)
  3553 BYTESWAP_AND_WRITE(BE,32)
  3554 BYTESWAP_AND_WRITE(LE,64)
  3555 BYTESWAP_AND_WRITE(BE,64)
  3556 #undef BYTESWAP_AND_WRITE
  3557 
  3558 
  3559 static Sint64 SDLCALL
  3560 RWops12to20_size(struct SDL_RWops *rwops20)
  3561 {
  3562     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3563     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  3564     int pos;
  3565 
  3566     if (size != -1)
  3567         return size;
  3568 
  3569     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  3570     if (pos == -1)
  3571         return -1;
  3572 
  3573     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  3574     if (size == -1)
  3575         return -1;
  3576 
  3577     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  3578     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  3579     return size;
  3580 }
  3581 
  3582 static Sint64 SDLCALL
  3583 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  3584 {
  3585     FIXME("fail if (offset) is too big");
  3586     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3587     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  3588 }
  3589 
  3590 static size_t SDLCALL
  3591 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  3592 {
  3593     FIXME("fail if (size) or (maxnum) is too big");
  3594     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3595     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  3596 }
  3597 
  3598 static size_t SDLCALL
  3599 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  3600 {
  3601     FIXME("fail if (size) or (maxnum) is too big");
  3602     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3603     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  3604 }
  3605 
  3606 static int SDLCALL
  3607 RWops12to20_close(struct SDL_RWops *rwops20)
  3608 {
  3609     int rc = 0;
  3610     if (rwops20)
  3611     {
  3612         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3613         rc = rwops12->close(rwops12);
  3614         if (rc == 0)
  3615             SDL20_FreeRW(rwops20);
  3616     }
  3617     return rc;
  3618 }
  3619 
  3620 static SDL_RWops *
  3621 RWops12to20(SDL12_RWops *rwops12)
  3622 {
  3623     SDL_RWops *rwops20;
  3624 
  3625     if (!rwops12)
  3626         return NULL;
  3627 
  3628     rwops20 = SDL20_AllocRW();
  3629     if (!rwops20)
  3630         return NULL;
  3631 
  3632     SDL20_zerop(rwops20);
  3633     rwops20->type = rwops12->type;
  3634     rwops20->hidden.unknown.data1 = rwops12;
  3635     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  3636     rwops20->size = RWops12to20_size;
  3637     rwops20->seek = RWops12to20_seek;
  3638     rwops20->read = RWops12to20_read;
  3639     rwops20->write = RWops12to20_write;
  3640     rwops20->close = RWops12to20_close;
  3641     return rwops20;
  3642 }
  3643 
  3644 DECLSPEC SDL12_Surface * SDLCALL
  3645 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  3646 {
  3647     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3648     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  3649     SDL12_Surface *surface12 = Surface20to12(surface20);
  3650     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3651         SDL20_FreeRW(rwops20);
  3652     if ((!surface12) && (surface20))
  3653         SDL20_FreeSurface(surface20);
  3654     return surface12;
  3655 }
  3656 
  3657 DECLSPEC int SDLCALL
  3658 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  3659 {
  3660     FIXME("wrap surface");
  3661     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3662     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  3663     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3664         SDL20_FreeRW(rwops20);
  3665     return retval;
  3666 }
  3667 
  3668 DECLSPEC SDL_AudioSpec * SDLCALL
  3669 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  3670                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  3671 {
  3672     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3673     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  3674     FIXME("deal with non-1.2 formats, like float32");
  3675     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3676         SDL20_FreeRW(rwops20);
  3677     return retval;
  3678 }
  3679 
  3680 typedef struct
  3681 {
  3682     void (SDLCALL *app_callback)(void *userdata, Uint8 *stream, int len);
  3683     void *app_userdata;
  3684     Uint8 silence;
  3685 } AudioCallbackWrapperData;
  3686 
  3687 static void SDLCALL
  3688 AudioCallbackWrapper(void *userdata, Uint8 *stream, int len)
  3689 {
  3690     AudioCallbackWrapperData *data = (AudioCallbackWrapperData *) userdata;
  3691     SDL_memset(stream, data->silence, len);  // SDL2 doesn't clear the stream before calling in here, but 1.2 expects it.
  3692     data->app_callback(data->app_userdata, stream, len);
  3693 }
  3694 
  3695 
  3696 DECLSPEC int SDLCALL
  3697 SDL_OpenAudio(SDL_AudioSpec *want, SDL_AudioSpec *obtained)
  3698 {
  3699     // SDL2 uses a NULL callback to mean "we play to use SDL_QueueAudio()"
  3700     if (want && (want->callback == NULL)) {
  3701         return SDL20_SetError("Callback can't be NULL");
  3702     }
  3703 
  3704     AudioCallbackWrapperData *data = (AudioCallbackWrapperData *) SDL20_calloc(1, sizeof (AudioCallbackWrapperData));
  3705     if (!data) {
  3706         return SDL20_OutOfMemory();
  3707     }
  3708     data->app_callback = want->callback;
  3709     data->app_userdata = want->userdata;
  3710     want->callback = AudioCallbackWrapper;
  3711     want->userdata = data;
  3712 
  3713     FIXME("Don't allow int32 or float32");
  3714     FIXME("clamp output to mono/stereo");
  3715     const int retval = SDL20_OpenAudio(want, obtained);
  3716     want->callback = data->app_callback;
  3717     want->userdata = data->app_userdata;
  3718     if (retval == -1) {
  3719         SDL20_free(data);
  3720     } else {
  3721         FIXME("memory leak on callback data");
  3722         if (!obtained) {
  3723             data->silence = want->silence;
  3724         } else {
  3725             data->silence = obtained->silence;
  3726             obtained->callback = data->app_callback;
  3727             obtained->userdata = data->app_userdata;
  3728         }
  3729     }
  3730 
  3731     return retval;
  3732 }
  3733 
  3734 
  3735 
  3736 /* vi: set ts=4 sw=4 expandtab: */