src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 06 Mar 2019 03:08:45 -0500
changeset 103 685c0014eda1
parent 102 d45dadba9ff2
child 104 f3976d9769ab
permissions -rw-r--r--
Optimize dirty rectangle rendering.

Only push the video surface to a texture immediately when the app does
SDL_Flip() or SDL_UpdateRect(0,0,0,0). If it looks like dirty rectangle
rendering, only push when we're in a PumpEvents that's close to 60Hz, under
the assumption that the app isn't in the middle of rendering if they're
pumping the event queue, and that updates to the texture faster than the
refresh rate aren't seen anyhow.

This lets things that render a little in response to every mouse event, like
TuxPaint, run at reasonable speeds and still look correct.

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