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