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