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