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