src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 20 Feb 2019 23:56:10 -0500
changeset 77 ce9a1f04bb36
parent 76 76970160f0fb
child 78 faf3d269ede6
permissions -rw-r--r--
Got initial keyboard support working.
     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 
  1212     return 1;
  1213 }
  1214 
  1215 DECLSPEC int SDLCALL
  1216 SDL_PushEvent(SDL12_Event *event12)
  1217 {
  1218     EventQueueType *item = EventQueueAvailable;
  1219     if (item == NULL)
  1220         return -1;  /* no space available at the moment. */
  1221 
  1222     EventQueueAvailable = item->next;
  1223     if (EventQueueTail)
  1224         EventQueueTail->next = item;
  1225     else
  1226         EventQueueHead = EventQueueTail = item;
  1227     item->next = NULL;
  1228 
  1229     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
  1230     return 0;
  1231 }
  1232 
  1233 DECLSPEC int SDLCALL
  1234 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
  1235 {
  1236     if (action == SDL_ADDEVENT)
  1237     {
  1238         int i;
  1239         for (i = 0; i < numevents; i++)
  1240         {
  1241             if (SDL_PushEvent(&events12[i]) == -1)
  1242                 break;  /* out of space for more events. */
  1243         }
  1244         return i;
  1245     }
  1246     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
  1247     {
  1248         const SDL_bool isGet = (action == SDL_GETEVENT);
  1249         EventQueueType *prev = NULL;
  1250         EventQueueType *item = EventQueueHead;
  1251         EventQueueType *next = NULL;
  1252         int chosen = 0;
  1253         while (chosen < numevents)
  1254         {
  1255             EventQueueType *nextPrev = item;
  1256             if (!item)
  1257                 break;  /* no more events at the moment. */
  1258 
  1259             next = item->next;  /* copy, since we might overwrite item->next */
  1260 
  1261             if (mask & (1<<item->event12.type))
  1262             {
  1263                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
  1264                 if (isGet)  /* remove from list? */
  1265                 {
  1266                     if (prev != NULL)
  1267                         prev->next = next;
  1268                     if (item == EventQueueHead)
  1269                         EventQueueHead = next;
  1270                     if (item == EventQueueTail)
  1271                         EventQueueTail = prev;
  1272 
  1273                     /* put it back in the free pool. */
  1274                     item->next = EventQueueAvailable;
  1275                     EventQueueAvailable = item;
  1276                     nextPrev = prev;  /* previous item doesn't change. */
  1277                 }
  1278             }
  1279 
  1280             item = next;
  1281             prev = nextPrev;
  1282         }
  1283         return chosen;
  1284     }
  1285 
  1286     return 0;
  1287 }
  1288 
  1289 DECLSPEC int SDLCALL
  1290 SDL_WaitEvent(SDL12_Event *event12)
  1291 {
  1292     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1293     while (!SDL_PollEvent(event12))
  1294         SDL20_Delay(10);
  1295     return 1;
  1296 }
  1297 
  1298 static SDL_bool
  1299 PushEventIfNotFiltered(SDL12_Event *event12)
  1300 {
  1301     if (event12->type != SDL12_NOEVENT)
  1302     {
  1303         if (EventStates[event12->type] != SDL_IGNORE)
  1304         {
  1305             if ((!EventFilter12) || (EventFilter12(event12)))
  1306                 return (SDL_PushEvent(event12) == 0);
  1307         }
  1308     }
  1309     return SDL_FALSE;
  1310 }
  1311 
  1312 DECLSPEC Uint8 SDLCALL
  1313 SDL_EventState(Uint8 type, int state)
  1314 {
  1315     /* the values of "state" match between 1.2 and 2.0 */
  1316     const Uint8 retval = EventStates[type];
  1317     SDL12_Event e;
  1318 
  1319     if (state != SDL_QUERY)
  1320         EventStates[type] = state;
  1321     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1322         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1323 
  1324     return retval;
  1325 }
  1326 
  1327 DECLSPEC Uint8 SDLCALL
  1328 SDL_GetMouseState(int *x, int *y)
  1329 {
  1330     const Uint32 state20 = SDL20_GetMouseState(x, y);
  1331     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1332 
  1333     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1334     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  1335         retval |= (1<<5);
  1336     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  1337         retval |= (1<<6);
  1338 
  1339     return retval;
  1340 }
  1341 
  1342 DECLSPEC char * SDLCALL
  1343 SDL_GetKeyName(SDL12Key key)
  1344 {
  1345     switch (key) {
  1346         #define CASESDLK12TONAME(k, n) case k: return (char *) n
  1347 	    CASESDLK12TONAME(SDLK12_BACKSPACE, "backspace");
  1348 	    CASESDLK12TONAME(SDLK12_TAB, "tab");
  1349 	    CASESDLK12TONAME(SDLK12_CLEAR, "clear");
  1350 	    CASESDLK12TONAME(SDLK12_RETURN, "return");
  1351 	    CASESDLK12TONAME(SDLK12_PAUSE, "pause");
  1352 	    CASESDLK12TONAME(SDLK12_ESCAPE, "escape");
  1353 	    CASESDLK12TONAME(SDLK12_SPACE, "space");
  1354 	    CASESDLK12TONAME(SDLK12_EXCLAIM, "!");
  1355 	    CASESDLK12TONAME(SDLK12_QUOTEDBL, "\"");
  1356 	    CASESDLK12TONAME(SDLK12_HASH, "#");
  1357 	    CASESDLK12TONAME(SDLK12_DOLLAR, "$");
  1358 	    CASESDLK12TONAME(SDLK12_AMPERSAND, "&");
  1359 	    CASESDLK12TONAME(SDLK12_QUOTE, "'");
  1360 	    CASESDLK12TONAME(SDLK12_LEFTPAREN, "(");
  1361 	    CASESDLK12TONAME(SDLK12_RIGHTPAREN, ")");
  1362 	    CASESDLK12TONAME(SDLK12_ASTERISK, "*");
  1363 	    CASESDLK12TONAME(SDLK12_PLUS, "+");
  1364 	    CASESDLK12TONAME(SDLK12_COMMA, ",");
  1365 	    CASESDLK12TONAME(SDLK12_MINUS, "-");
  1366 	    CASESDLK12TONAME(SDLK12_PERIOD, ".");
  1367 	    CASESDLK12TONAME(SDLK12_SLASH, "/");
  1368 	    CASESDLK12TONAME(SDLK12_0, "0");
  1369 	    CASESDLK12TONAME(SDLK12_1, "1");
  1370 	    CASESDLK12TONAME(SDLK12_2, "2");
  1371 	    CASESDLK12TONAME(SDLK12_3, "3");
  1372 	    CASESDLK12TONAME(SDLK12_4, "4");
  1373 	    CASESDLK12TONAME(SDLK12_5, "5");
  1374 	    CASESDLK12TONAME(SDLK12_6, "6");
  1375 	    CASESDLK12TONAME(SDLK12_7, "7");
  1376 	    CASESDLK12TONAME(SDLK12_8, "8");
  1377 	    CASESDLK12TONAME(SDLK12_9, "9");
  1378 	    CASESDLK12TONAME(SDLK12_COLON, ":");
  1379 	    CASESDLK12TONAME(SDLK12_SEMICOLON, ");");
  1380 	    CASESDLK12TONAME(SDLK12_LESS, "<");
  1381 	    CASESDLK12TONAME(SDLK12_EQUALS, "=");
  1382 	    CASESDLK12TONAME(SDLK12_GREATER, ">");
  1383 	    CASESDLK12TONAME(SDLK12_QUESTION, "?");
  1384 	    CASESDLK12TONAME(SDLK12_AT, "@");
  1385 	    CASESDLK12TONAME(SDLK12_LEFTBRACKET, "[");
  1386 	    CASESDLK12TONAME(SDLK12_BACKSLASH, "\\");
  1387 	    CASESDLK12TONAME(SDLK12_RIGHTBRACKET, "]");
  1388 	    CASESDLK12TONAME(SDLK12_CARET, "^");
  1389 	    CASESDLK12TONAME(SDLK12_UNDERSCORE, "_");
  1390 	    CASESDLK12TONAME(SDLK12_BACKQUOTE, "`");
  1391 	    CASESDLK12TONAME(SDLK12_a, "a");
  1392 	    CASESDLK12TONAME(SDLK12_b, "b");
  1393 	    CASESDLK12TONAME(SDLK12_c, "c");
  1394 	    CASESDLK12TONAME(SDLK12_d, "d");
  1395 	    CASESDLK12TONAME(SDLK12_e, "e");
  1396 	    CASESDLK12TONAME(SDLK12_f, "f");
  1397 	    CASESDLK12TONAME(SDLK12_g, "g");
  1398 	    CASESDLK12TONAME(SDLK12_h, "h");
  1399 	    CASESDLK12TONAME(SDLK12_i, "i");
  1400 	    CASESDLK12TONAME(SDLK12_j, "j");
  1401 	    CASESDLK12TONAME(SDLK12_k, "k");
  1402 	    CASESDLK12TONAME(SDLK12_l, "l");
  1403 	    CASESDLK12TONAME(SDLK12_m, "m");
  1404 	    CASESDLK12TONAME(SDLK12_n, "n");
  1405 	    CASESDLK12TONAME(SDLK12_o, "o");
  1406 	    CASESDLK12TONAME(SDLK12_p, "p");
  1407 	    CASESDLK12TONAME(SDLK12_q, "q");
  1408 	    CASESDLK12TONAME(SDLK12_r, "r");
  1409 	    CASESDLK12TONAME(SDLK12_s, "s");
  1410 	    CASESDLK12TONAME(SDLK12_t, "t");
  1411 	    CASESDLK12TONAME(SDLK12_u, "u");
  1412 	    CASESDLK12TONAME(SDLK12_v, "v");
  1413 	    CASESDLK12TONAME(SDLK12_w, "w");
  1414 	    CASESDLK12TONAME(SDLK12_x, "x");
  1415 	    CASESDLK12TONAME(SDLK12_y, "y");
  1416 	    CASESDLK12TONAME(SDLK12_z, "z");
  1417 	    CASESDLK12TONAME(SDLK12_DELETE, "delete");
  1418 
  1419 	    CASESDLK12TONAME(SDLK12_WORLD_0, "world 0");
  1420 	    CASESDLK12TONAME(SDLK12_WORLD_1, "world 1");
  1421 	    CASESDLK12TONAME(SDLK12_WORLD_2, "world 2");
  1422 	    CASESDLK12TONAME(SDLK12_WORLD_3, "world 3");
  1423 	    CASESDLK12TONAME(SDLK12_WORLD_4, "world 4");
  1424 	    CASESDLK12TONAME(SDLK12_WORLD_5, "world 5");
  1425 	    CASESDLK12TONAME(SDLK12_WORLD_6, "world 6");
  1426 	    CASESDLK12TONAME(SDLK12_WORLD_7, "world 7");
  1427 	    CASESDLK12TONAME(SDLK12_WORLD_8, "world 8");
  1428 	    CASESDLK12TONAME(SDLK12_WORLD_9, "world 9");
  1429 	    CASESDLK12TONAME(SDLK12_WORLD_10, "world 10");
  1430 	    CASESDLK12TONAME(SDLK12_WORLD_11, "world 11");
  1431 	    CASESDLK12TONAME(SDLK12_WORLD_12, "world 12");
  1432 	    CASESDLK12TONAME(SDLK12_WORLD_13, "world 13");
  1433 	    CASESDLK12TONAME(SDLK12_WORLD_14, "world 14");
  1434 	    CASESDLK12TONAME(SDLK12_WORLD_15, "world 15");
  1435 	    CASESDLK12TONAME(SDLK12_WORLD_16, "world 16");
  1436 	    CASESDLK12TONAME(SDLK12_WORLD_17, "world 17");
  1437 	    CASESDLK12TONAME(SDLK12_WORLD_18, "world 18");
  1438 	    CASESDLK12TONAME(SDLK12_WORLD_19, "world 19");
  1439 	    CASESDLK12TONAME(SDLK12_WORLD_20, "world 20");
  1440 	    CASESDLK12TONAME(SDLK12_WORLD_21, "world 21");
  1441 	    CASESDLK12TONAME(SDLK12_WORLD_22, "world 22");
  1442 	    CASESDLK12TONAME(SDLK12_WORLD_23, "world 23");
  1443 	    CASESDLK12TONAME(SDLK12_WORLD_24, "world 24");
  1444 	    CASESDLK12TONAME(SDLK12_WORLD_25, "world 25");
  1445 	    CASESDLK12TONAME(SDLK12_WORLD_26, "world 26");
  1446 	    CASESDLK12TONAME(SDLK12_WORLD_27, "world 27");
  1447 	    CASESDLK12TONAME(SDLK12_WORLD_28, "world 28");
  1448 	    CASESDLK12TONAME(SDLK12_WORLD_29, "world 29");
  1449 	    CASESDLK12TONAME(SDLK12_WORLD_30, "world 30");
  1450 	    CASESDLK12TONAME(SDLK12_WORLD_31, "world 31");
  1451 	    CASESDLK12TONAME(SDLK12_WORLD_32, "world 32");
  1452 	    CASESDLK12TONAME(SDLK12_WORLD_33, "world 33");
  1453 	    CASESDLK12TONAME(SDLK12_WORLD_34, "world 34");
  1454 	    CASESDLK12TONAME(SDLK12_WORLD_35, "world 35");
  1455 	    CASESDLK12TONAME(SDLK12_WORLD_36, "world 36");
  1456 	    CASESDLK12TONAME(SDLK12_WORLD_37, "world 37");
  1457 	    CASESDLK12TONAME(SDLK12_WORLD_38, "world 38");
  1458 	    CASESDLK12TONAME(SDLK12_WORLD_39, "world 39");
  1459 	    CASESDLK12TONAME(SDLK12_WORLD_40, "world 40");
  1460 	    CASESDLK12TONAME(SDLK12_WORLD_41, "world 41");
  1461 	    CASESDLK12TONAME(SDLK12_WORLD_42, "world 42");
  1462 	    CASESDLK12TONAME(SDLK12_WORLD_43, "world 43");
  1463 	    CASESDLK12TONAME(SDLK12_WORLD_44, "world 44");
  1464 	    CASESDLK12TONAME(SDLK12_WORLD_45, "world 45");
  1465 	    CASESDLK12TONAME(SDLK12_WORLD_46, "world 46");
  1466 	    CASESDLK12TONAME(SDLK12_WORLD_47, "world 47");
  1467 	    CASESDLK12TONAME(SDLK12_WORLD_48, "world 48");
  1468 	    CASESDLK12TONAME(SDLK12_WORLD_49, "world 49");
  1469 	    CASESDLK12TONAME(SDLK12_WORLD_50, "world 50");
  1470 	    CASESDLK12TONAME(SDLK12_WORLD_51, "world 51");
  1471 	    CASESDLK12TONAME(SDLK12_WORLD_52, "world 52");
  1472 	    CASESDLK12TONAME(SDLK12_WORLD_53, "world 53");
  1473 	    CASESDLK12TONAME(SDLK12_WORLD_54, "world 54");
  1474 	    CASESDLK12TONAME(SDLK12_WORLD_55, "world 55");
  1475 	    CASESDLK12TONAME(SDLK12_WORLD_56, "world 56");
  1476 	    CASESDLK12TONAME(SDLK12_WORLD_57, "world 57");
  1477 	    CASESDLK12TONAME(SDLK12_WORLD_58, "world 58");
  1478 	    CASESDLK12TONAME(SDLK12_WORLD_59, "world 59");
  1479 	    CASESDLK12TONAME(SDLK12_WORLD_60, "world 60");
  1480 	    CASESDLK12TONAME(SDLK12_WORLD_61, "world 61");
  1481 	    CASESDLK12TONAME(SDLK12_WORLD_62, "world 62");
  1482 	    CASESDLK12TONAME(SDLK12_WORLD_63, "world 63");
  1483 	    CASESDLK12TONAME(SDLK12_WORLD_64, "world 64");
  1484 	    CASESDLK12TONAME(SDLK12_WORLD_65, "world 65");
  1485 	    CASESDLK12TONAME(SDLK12_WORLD_66, "world 66");
  1486 	    CASESDLK12TONAME(SDLK12_WORLD_67, "world 67");
  1487 	    CASESDLK12TONAME(SDLK12_WORLD_68, "world 68");
  1488 	    CASESDLK12TONAME(SDLK12_WORLD_69, "world 69");
  1489 	    CASESDLK12TONAME(SDLK12_WORLD_70, "world 70");
  1490 	    CASESDLK12TONAME(SDLK12_WORLD_71, "world 71");
  1491 	    CASESDLK12TONAME(SDLK12_WORLD_72, "world 72");
  1492 	    CASESDLK12TONAME(SDLK12_WORLD_73, "world 73");
  1493 	    CASESDLK12TONAME(SDLK12_WORLD_74, "world 74");
  1494 	    CASESDLK12TONAME(SDLK12_WORLD_75, "world 75");
  1495 	    CASESDLK12TONAME(SDLK12_WORLD_76, "world 76");
  1496 	    CASESDLK12TONAME(SDLK12_WORLD_77, "world 77");
  1497 	    CASESDLK12TONAME(SDLK12_WORLD_78, "world 78");
  1498 	    CASESDLK12TONAME(SDLK12_WORLD_79, "world 79");
  1499 	    CASESDLK12TONAME(SDLK12_WORLD_80, "world 80");
  1500 	    CASESDLK12TONAME(SDLK12_WORLD_81, "world 81");
  1501 	    CASESDLK12TONAME(SDLK12_WORLD_82, "world 82");
  1502 	    CASESDLK12TONAME(SDLK12_WORLD_83, "world 83");
  1503 	    CASESDLK12TONAME(SDLK12_WORLD_84, "world 84");
  1504 	    CASESDLK12TONAME(SDLK12_WORLD_85, "world 85");
  1505 	    CASESDLK12TONAME(SDLK12_WORLD_86, "world 86");
  1506 	    CASESDLK12TONAME(SDLK12_WORLD_87, "world 87");
  1507 	    CASESDLK12TONAME(SDLK12_WORLD_88, "world 88");
  1508 	    CASESDLK12TONAME(SDLK12_WORLD_89, "world 89");
  1509 	    CASESDLK12TONAME(SDLK12_WORLD_90, "world 90");
  1510 	    CASESDLK12TONAME(SDLK12_WORLD_91, "world 91");
  1511 	    CASESDLK12TONAME(SDLK12_WORLD_92, "world 92");
  1512 	    CASESDLK12TONAME(SDLK12_WORLD_93, "world 93");
  1513 	    CASESDLK12TONAME(SDLK12_WORLD_94, "world 94");
  1514 	    CASESDLK12TONAME(SDLK12_WORLD_95, "world 95");
  1515 
  1516 	    CASESDLK12TONAME(SDLK12_KP0, "[0]");
  1517 	    CASESDLK12TONAME(SDLK12_KP1, "[1]");
  1518 	    CASESDLK12TONAME(SDLK12_KP2, "[2]");
  1519 	    CASESDLK12TONAME(SDLK12_KP3, "[3]");
  1520 	    CASESDLK12TONAME(SDLK12_KP4, "[4]");
  1521 	    CASESDLK12TONAME(SDLK12_KP5, "[5]");
  1522 	    CASESDLK12TONAME(SDLK12_KP6, "[6]");
  1523 	    CASESDLK12TONAME(SDLK12_KP7, "[7]");
  1524 	    CASESDLK12TONAME(SDLK12_KP8, "[8]");
  1525 	    CASESDLK12TONAME(SDLK12_KP9, "[9]");
  1526 	    CASESDLK12TONAME(SDLK12_KP_PERIOD, "[.]");
  1527 	    CASESDLK12TONAME(SDLK12_KP_DIVIDE, "[/]");
  1528 	    CASESDLK12TONAME(SDLK12_KP_MULTIPLY, "[*]");
  1529 	    CASESDLK12TONAME(SDLK12_KP_MINUS, "[-]");
  1530 	    CASESDLK12TONAME(SDLK12_KP_PLUS, "[+]");
  1531 	    CASESDLK12TONAME(SDLK12_KP_ENTER, "enter");
  1532 	    CASESDLK12TONAME(SDLK12_KP_EQUALS, "equals");
  1533 
  1534 	    CASESDLK12TONAME(SDLK12_UP, "up");
  1535 	    CASESDLK12TONAME(SDLK12_DOWN, "down");
  1536 	    CASESDLK12TONAME(SDLK12_RIGHT, "right");
  1537 	    CASESDLK12TONAME(SDLK12_LEFT, "left");
  1538 	    CASESDLK12TONAME(SDLK12_INSERT, "insert");
  1539 	    CASESDLK12TONAME(SDLK12_HOME, "home");
  1540 	    CASESDLK12TONAME(SDLK12_END, "end");
  1541 	    CASESDLK12TONAME(SDLK12_PAGEUP, "page up");
  1542 	    CASESDLK12TONAME(SDLK12_PAGEDOWN, "page down");
  1543 
  1544 	    CASESDLK12TONAME(SDLK12_F1, "f1");
  1545 	    CASESDLK12TONAME(SDLK12_F2, "f2");
  1546 	    CASESDLK12TONAME(SDLK12_F3, "f3");
  1547 	    CASESDLK12TONAME(SDLK12_F4, "f4");
  1548 	    CASESDLK12TONAME(SDLK12_F5, "f5");
  1549 	    CASESDLK12TONAME(SDLK12_F6, "f6");
  1550 	    CASESDLK12TONAME(SDLK12_F7, "f7");
  1551 	    CASESDLK12TONAME(SDLK12_F8, "f8");
  1552 	    CASESDLK12TONAME(SDLK12_F9, "f9");
  1553 	    CASESDLK12TONAME(SDLK12_F10, "f10");
  1554 	    CASESDLK12TONAME(SDLK12_F11, "f11");
  1555 	    CASESDLK12TONAME(SDLK12_F12, "f12");
  1556 	    CASESDLK12TONAME(SDLK12_F13, "f13");
  1557 	    CASESDLK12TONAME(SDLK12_F14, "f14");
  1558 	    CASESDLK12TONAME(SDLK12_F15, "f15");
  1559 
  1560 	    CASESDLK12TONAME(SDLK12_NUMLOCK, "numlock");
  1561 	    CASESDLK12TONAME(SDLK12_CAPSLOCK, "caps lock");
  1562 	    CASESDLK12TONAME(SDLK12_SCROLLOCK, "scroll lock");
  1563 	    CASESDLK12TONAME(SDLK12_RSHIFT, "right shift");
  1564 	    CASESDLK12TONAME(SDLK12_LSHIFT, "left shift");
  1565 	    CASESDLK12TONAME(SDLK12_RCTRL, "right ctrl");
  1566 	    CASESDLK12TONAME(SDLK12_LCTRL, "left ctrl");
  1567 	    CASESDLK12TONAME(SDLK12_RALT, "right alt");
  1568 	    CASESDLK12TONAME(SDLK12_LALT, "left alt");
  1569 	    CASESDLK12TONAME(SDLK12_RMETA, "right meta");
  1570 	    CASESDLK12TONAME(SDLK12_LMETA, "left meta");
  1571 	    CASESDLK12TONAME(SDLK12_LSUPER, "left super");	/* "Windows" keys */
  1572 	    CASESDLK12TONAME(SDLK12_RSUPER, "right super");	
  1573 	    CASESDLK12TONAME(SDLK12_MODE, "alt gr");
  1574 	    CASESDLK12TONAME(SDLK12_COMPOSE, "compose");
  1575 
  1576 	    CASESDLK12TONAME(SDLK12_HELP, "help");
  1577 	    CASESDLK12TONAME(SDLK12_PRINT, "print screen");
  1578 	    CASESDLK12TONAME(SDLK12_SYSREQ, "sys req");
  1579 	    CASESDLK12TONAME(SDLK12_BREAK, "break");
  1580 	    CASESDLK12TONAME(SDLK12_MENU, "menu");
  1581 	    CASESDLK12TONAME(SDLK12_POWER, "power");
  1582 	    CASESDLK12TONAME(SDLK12_EURO, "euro");
  1583 	    CASESDLK12TONAME(SDLK12_UNDO, "undo");
  1584         #undef CASESDLK12TONAME
  1585         default: break;
  1586     }
  1587 
  1588     return (char *) "unknown key";
  1589 }
  1590 
  1591 static SDL12Key
  1592 Keysym20to12(const SDL_Keycode keysym20)
  1593 {
  1594     if ( ((int) keysym20) < 127 ) {  /* (most of) low-ASCII maps directly */
  1595         if (keysym20 == SDLK_PAUSE) {
  1596             return SDLK12_PAUSE;
  1597         } else if (keysym20 == SDLK_CLEAR) {
  1598             return SDLK12_CLEAR;
  1599         }
  1600         return (SDL12Key) keysym20;
  1601     }
  1602 
  1603     switch (keysym20) {
  1604         #define CASEKEYSYM20TO12(k20, k12) case SDLK_##k20: return SDLK12_##k12
  1605         CASEKEYSYM20TO12(KP_0, KP0);
  1606         CASEKEYSYM20TO12(KP_1, KP1);
  1607         CASEKEYSYM20TO12(KP_2, KP2);
  1608         CASEKEYSYM20TO12(KP_3, KP3);
  1609         CASEKEYSYM20TO12(KP_4, KP4);
  1610         CASEKEYSYM20TO12(KP_5, KP5);
  1611         CASEKEYSYM20TO12(KP_6, KP6);
  1612         CASEKEYSYM20TO12(KP_7, KP7);
  1613         CASEKEYSYM20TO12(KP_8, KP8);
  1614         CASEKEYSYM20TO12(KP_9, KP9);
  1615         CASEKEYSYM20TO12(NUMLOCKCLEAR, NUMLOCK);
  1616         CASEKEYSYM20TO12(SCROLLLOCK, SCROLLOCK);
  1617         CASEKEYSYM20TO12(RGUI, RMETA);
  1618         CASEKEYSYM20TO12(LGUI, LMETA);
  1619         CASEKEYSYM20TO12(PRINTSCREEN, PRINT);
  1620         #undef CASEKEYSYM20TO12
  1621 
  1622         #define CASEKEYSYM20TO12(k) case SDLK_##k: return SDLK12_##k
  1623         CASEKEYSYM20TO12(CLEAR);
  1624         CASEKEYSYM20TO12(PAUSE);
  1625         CASEKEYSYM20TO12(KP_PERIOD);
  1626         CASEKEYSYM20TO12(KP_DIVIDE);
  1627         CASEKEYSYM20TO12(KP_MULTIPLY);
  1628         CASEKEYSYM20TO12(KP_MINUS);
  1629         CASEKEYSYM20TO12(KP_PLUS);
  1630         CASEKEYSYM20TO12(KP_ENTER);
  1631         CASEKEYSYM20TO12(KP_EQUALS);
  1632         CASEKEYSYM20TO12(UP);
  1633         CASEKEYSYM20TO12(DOWN);
  1634         CASEKEYSYM20TO12(RIGHT);
  1635         CASEKEYSYM20TO12(LEFT);
  1636         CASEKEYSYM20TO12(INSERT);
  1637         CASEKEYSYM20TO12(HOME);
  1638         CASEKEYSYM20TO12(END);
  1639         CASEKEYSYM20TO12(PAGEUP);
  1640         CASEKEYSYM20TO12(PAGEDOWN);
  1641         CASEKEYSYM20TO12(F1);
  1642         CASEKEYSYM20TO12(F2);
  1643         CASEKEYSYM20TO12(F3);
  1644         CASEKEYSYM20TO12(F4);
  1645         CASEKEYSYM20TO12(F5);
  1646         CASEKEYSYM20TO12(F6);
  1647         CASEKEYSYM20TO12(F7);
  1648         CASEKEYSYM20TO12(F8);
  1649         CASEKEYSYM20TO12(F9);
  1650         CASEKEYSYM20TO12(F10);
  1651         CASEKEYSYM20TO12(F11);
  1652         CASEKEYSYM20TO12(F12);
  1653         CASEKEYSYM20TO12(F13);
  1654         CASEKEYSYM20TO12(F14);
  1655         CASEKEYSYM20TO12(F15);
  1656         CASEKEYSYM20TO12(CAPSLOCK);
  1657         CASEKEYSYM20TO12(RSHIFT);
  1658         CASEKEYSYM20TO12(LSHIFT);
  1659         CASEKEYSYM20TO12(RCTRL);
  1660         CASEKEYSYM20TO12(LCTRL);
  1661         CASEKEYSYM20TO12(RALT);
  1662         CASEKEYSYM20TO12(LALT);
  1663         CASEKEYSYM20TO12(MODE);
  1664         CASEKEYSYM20TO12(HELP);
  1665         CASEKEYSYM20TO12(SYSREQ);;
  1666         CASEKEYSYM20TO12(MENU);
  1667         CASEKEYSYM20TO12(POWER);
  1668         CASEKEYSYM20TO12(UNDO);
  1669         #undef CASEKEYSYM20TO12
  1670         default: break;
  1671     }
  1672 
  1673     FIXME("nothing maps to SDLK12_COMPOSE, SDLK12_BREAK, or SDLK12_EURO ...?");
  1674     FIXME("map some of the SDLK12_WORLD keys");
  1675     return SDLK12_UNKNOWN;
  1676 }
  1677 
  1678 static int
  1679 EventFilter20to12(void *data, SDL_Event *event20)
  1680 {
  1681     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1682     SDL12_Event event12;
  1683     int x, y;
  1684 
  1685     SDL_assert(data == NULL);  /* currently unused. */
  1686 
  1687     SDL20_zero(event12);
  1688 
  1689     switch (event20->type)
  1690     {
  1691         case SDL_QUIT:
  1692             event12.type = SDL12_QUIT;
  1693             break;
  1694 
  1695         case SDL_WINDOWEVENT:
  1696             switch (event20->window.event)
  1697             {
  1698                 case SDL_WINDOWEVENT_CLOSE:
  1699                     event12.type = SDL12_QUIT;
  1700                     break;
  1701 
  1702                 case SDL_WINDOWEVENT_SHOWN:
  1703                 case SDL_WINDOWEVENT_EXPOSED:
  1704                     event12.type = SDL12_VIDEOEXPOSE;
  1705                     break;
  1706 
  1707                 case SDL_WINDOWEVENT_RESIZED:
  1708                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1709                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1710                     event12.type = SDL12_VIDEORESIZE;
  1711                     event12.resize.w = event20->window.data1;
  1712                     event12.resize.h = event20->window.data2;
  1713                     break;
  1714 
  1715                 case SDL_WINDOWEVENT_MINIMIZED:
  1716                     event12.type = SDL12_ACTIVEEVENT;
  1717                     event12.active.gain = 0;
  1718                     event12.active.state = SDL12_APPACTIVE;
  1719                     break;
  1720 
  1721                 case SDL_WINDOWEVENT_RESTORED:
  1722                     event12.type = SDL12_ACTIVEEVENT;
  1723                     event12.active.gain = 1;
  1724                     event12.active.state = SDL12_APPACTIVE;
  1725                     break;
  1726 
  1727                 case SDL_WINDOWEVENT_ENTER:
  1728                     event12.type = SDL12_ACTIVEEVENT;
  1729                     event12.active.gain = 1;
  1730                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1731                     break;
  1732 
  1733                 case SDL_WINDOWEVENT_LEAVE:
  1734                     event12.type = SDL12_ACTIVEEVENT;
  1735                     event12.active.gain = 0;
  1736                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1737                     break;
  1738 
  1739                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1740                     event12.type = SDL12_ACTIVEEVENT;
  1741                     event12.active.gain = 1;
  1742                     event12.active.state = SDL12_APPINPUTFOCUS;
  1743                     break;
  1744 
  1745                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1746                     event12.type = SDL12_ACTIVEEVENT;
  1747                     event12.active.gain = 0;
  1748                     event12.active.state = SDL12_APPINPUTFOCUS;
  1749                     break;
  1750             }
  1751             break;
  1752 
  1753         // !!! FIXME: this is sort of a mess to convert.
  1754         case SDL_SYSWMEVENT: FIXME("write me"); return 0;
  1755 
  1756         case SDL_KEYUP:
  1757         case SDL_KEYDOWN:
  1758             if (event20->key.repeat) {
  1759                 return 0;  /* ignore 2.0-style key repeat events */
  1760             }
  1761             event12.key.keysym.sym = Keysym20to12(event20->key.keysym.sym);
  1762             if (event12.key.keysym.sym == SDLK12_UNKNOWN) {
  1763                 return 0;  /* drop it if we can't map it */
  1764             }
  1765             event12.type = (event20->type == SDL_KEYDOWN) ? SDL12_KEYDOWN : SDL12_KEYUP;
  1766             event12.key.which = 0;
  1767             event12.key.state = event20->key.state;
  1768             event12.key.keysym.scancode = (event20->key.keysym.scancode < 256) ? (Uint8) event20->key.keysym.scancode : 0;
  1769             event12.key.keysym.mod = event20->key.keysym.mod;  /* these match up between 1.2 and 2.0! */
  1770             event12.key.keysym.unicode = 0;  FIXME("unicode");
  1771             break;
  1772 
  1773         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  1774         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  1775 
  1776         case SDL_MOUSEMOTION:
  1777         	event12.type = SDL12_MOUSEMOTION;
  1778             event12.motion.which = (Uint8) event20->motion.which;
  1779             event12.motion.state = event20->motion.state;
  1780             event12.motion.x = (Uint16) event20->motion.x;
  1781             event12.motion.y = (Uint16) event20->motion.y;
  1782             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1783             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1784             break;
  1785 
  1786         case SDL_MOUSEBUTTONDOWN:
  1787         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1788             event12.button.which = (Uint8) event20->button.which;
  1789             event12.button.button = event20->button.button;
  1790             event12.button.state = event20->button.state;
  1791             event12.button.x = (Uint16) event20->button.x;
  1792             event12.button.y = (Uint16) event20->button.y;
  1793             break;
  1794 
  1795         case SDL_MOUSEBUTTONUP:
  1796         	event12.type = SDL12_MOUSEBUTTONUP;
  1797             event12.button.which = (Uint8) event20->button.which;
  1798             event12.button.button = event20->button.button;
  1799             event12.button.state = event20->button.state;
  1800             event12.button.x = (Uint16) event20->button.x;
  1801             event12.button.y = (Uint16) event20->button.y;
  1802             break;
  1803 
  1804         case SDL_MOUSEWHEEL:
  1805             if (event20->wheel.y == 0)
  1806                 break;  /* don't support horizontal wheels in 1.2. */
  1807 
  1808             event12.type = SDL12_MOUSEBUTTONDOWN;
  1809             event12.button.which = (Uint8) event20->wheel.which;
  1810             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1811             event12.button.state = SDL_GetMouseState(&x, &y);
  1812             event12.button.x = (Uint16) x;
  1813             event12.button.y = (Uint16) y;
  1814             PushEventIfNotFiltered(&event12);
  1815 
  1816             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1817             break;
  1818 
  1819         case SDL_JOYAXISMOTION:
  1820             event12.type = SDL12_JOYAXISMOTION;
  1821             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1822             event12.jaxis.axis = event20->jaxis.axis;
  1823             event12.jaxis.value = event20->jaxis.value;
  1824             break;
  1825 
  1826         case SDL_JOYBALLMOTION:
  1827             event12.type = SDL12_JOYBALLMOTION;
  1828             event12.jball.which = (Uint8) event20->jball.which;
  1829             event12.jball.ball = event20->jball.ball;
  1830             event12.jball.xrel = event20->jball.xrel;
  1831             event12.jball.yrel = event20->jball.yrel;
  1832             break;
  1833 
  1834         case SDL_JOYHATMOTION:
  1835             event12.type = SDL12_JOYHATMOTION;
  1836             event12.jhat.which = (Uint8) event20->jhat.which;
  1837             event12.jhat.hat = event20->jhat.hat;
  1838             event12.jhat.value = event20->jhat.value;
  1839             break;
  1840 
  1841         case SDL_JOYBUTTONDOWN:
  1842             event12.type = SDL12_JOYBUTTONDOWN;
  1843             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1844             event12.jbutton.button = event20->jbutton.button;
  1845             event12.jbutton.state = event20->jbutton.state;
  1846             break;
  1847 
  1848         case SDL_JOYBUTTONUP:
  1849             event12.type = SDL12_JOYBUTTONUP;
  1850             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1851             event12.jbutton.button = event20->jbutton.button;
  1852             event12.jbutton.state = event20->jbutton.state;
  1853             break;
  1854 
  1855         //case SDL_JOYDEVICEADDED:
  1856         //case SDL_JOYDEVICEREMOVED:
  1857 	    //case SDL_CONTROLLERAXISMOTION:
  1858 	    //case SDL_CONTROLLERBUTTONDOWN:
  1859 	    //case SDL_CONTROLLERBUTTONUP:
  1860 	    //case SDL_CONTROLLERDEVICEADDED:
  1861 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1862 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1863         //case SDL_FINGERDOWN:
  1864         //case SDL_FINGERUP:
  1865         //case SDL_FINGERMOTION:
  1866         //case SDL_DOLLARGESTURE:
  1867         //case SDL_DOLLARRECORD:
  1868         //case SDL_MULTIGESTURE:
  1869         //case SDL_CLIPBOARDUPDATE:
  1870         //case SDL_DROPFILE:
  1871 
  1872         default:
  1873             return 0;  /* drop everything else. */
  1874     }
  1875 
  1876     PushEventIfNotFiltered(&event12);
  1877 
  1878     return 0;  /* always drop it from the 2.0 event queue. */
  1879 }
  1880 
  1881 DECLSPEC void SDLCALL
  1882 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1883 {
  1884     /* We always have a filter installed, but will call the app's too. */
  1885     EventFilter12 = filter12;
  1886 }
  1887 
  1888 DECLSPEC SDL12_EventFilter SDLCALL
  1889 SDL_GetEventFilter(void)
  1890 {
  1891     return EventFilter12;
  1892 }
  1893 
  1894 
  1895 static SDL12_Rect *
  1896 Rect20to12(const SDL_Rect *rect20, SDL12_Rect *rect12)
  1897 {
  1898     rect12->x = (Sint16) rect20->x;
  1899     rect12->y = (Sint16) rect20->y;
  1900     rect12->w = (Uint16) rect20->w;
  1901     rect12->h = (Uint16) rect20->h;
  1902     return rect12;
  1903 }
  1904 
  1905 static SDL_Rect *
  1906 Rect12to20(const SDL12_Rect *rect12, SDL_Rect *rect20)
  1907 {
  1908     rect20->x = (int) rect12->x;
  1909     rect20->y = (int) rect12->y;
  1910     rect20->w = (int) rect12->w;
  1911     rect20->h = (int) rect12->h;
  1912     return rect20;
  1913 }
  1914 
  1915 static SDL12_Surface *
  1916 Surface20to12(SDL_Surface *surface20)
  1917 {
  1918     SDL12_Surface *surface12 = NULL;
  1919     SDL12_Palette *palette12 = NULL;
  1920     SDL12_PixelFormat *format12 = NULL;
  1921     Uint32 flags = 0;
  1922 
  1923     if (!surface20)
  1924         return NULL;
  1925 
  1926     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1927     if (!surface12)
  1928         goto failed;
  1929 
  1930     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1931     if (!palette12)
  1932         goto failed;
  1933 
  1934     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1935     if (!format12)
  1936         goto failed;
  1937 
  1938     SDL20_zerop(palette12);
  1939     palette12->ncolors = surface20->format->palette->ncolors;
  1940     palette12->colors = surface20->format->palette->colors;
  1941 
  1942     SDL20_zerop(format12);
  1943     format12->palette = palette12;
  1944     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1945     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1946     format12->Rloss = surface20->format->Rloss;
  1947     format12->Gloss = surface20->format->Gloss;
  1948     format12->Bloss = surface20->format->Bloss;
  1949     format12->Aloss = surface20->format->Aloss;
  1950     format12->Rshift = surface20->format->Rshift;
  1951     format12->Gshift = surface20->format->Gshift;
  1952     format12->Bshift = surface20->format->Bshift;
  1953     format12->Ashift = surface20->format->Ashift;
  1954     format12->Rmask = surface20->format->Rmask;
  1955     format12->Gmask = surface20->format->Gmask;
  1956     format12->Bmask = surface20->format->Bmask;
  1957     format12->Amask = surface20->format->Amask;
  1958     FIXME("format12->colorkey");
  1959     FIXME("format12->alpha");
  1960 
  1961     SDL20_zerop(surface12);
  1962     flags = surface20->flags;
  1963     #ifdef SDL_SIMD_ALIGNED
  1964     flags &= ~SDL_SIMD_ALIGNED;  /* we don't need to map this to 1.2 */
  1965     #endif
  1966     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1967     MAPSURFACEFLAGS(PREALLOC);
  1968     MAPSURFACEFLAGS(RLEACCEL);
  1969     /*MAPSURFACEFLAGS(DONTFREE);*/
  1970     #undef MAPSURFACEFLAGS
  1971     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1972 
  1973     surface12->format = format12;
  1974     surface12->w = surface20->w;
  1975     surface12->h = surface20->h;
  1976     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  1977     surface12->pixels = surface20->pixels;
  1978     surface12->offset = 0;
  1979     surface12->surface20 = surface20;
  1980     Rect20to12(&surface20->clip_rect, &surface12->clip_rect);
  1981     surface12->refcount = surface20->refcount;
  1982 
  1983     return surface12;
  1984 
  1985 failed:
  1986     SDL20_free(surface12);
  1987     SDL20_free(palette12);
  1988     SDL20_free(format12);
  1989     return NULL;
  1990 }
  1991 
  1992 DECLSPEC SDL12_Surface * SDLCALL
  1993 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1994 {
  1995     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1996     SDL12_Surface *surface12 = Surface20to12(surface20);
  1997     if (!surface12) {
  1998         SDL20_FreeSurface(surface20);
  1999         return NULL;
  2000     }
  2001 
  2002     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  2003     return surface12;
  2004 }
  2005 
  2006 DECLSPEC SDL12_Surface * SDLCALL
  2007 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  2008 {
  2009     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  2010     SDL12_Surface *surface12 = Surface20to12(surface20);
  2011     if (!surface12) {
  2012         SDL20_FreeSurface(surface20);
  2013         return NULL;
  2014     }
  2015 
  2016     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  2017     return surface12;
  2018 }
  2019 
  2020 DECLSPEC void SDLCALL
  2021 SDL_FreeSurface(SDL12_Surface *surface12)
  2022 {
  2023     if (surface12) {
  2024         SDL20_FreeSurface(surface12->surface20);
  2025         if (surface12->format) {
  2026             SDL20_free(surface12->format->palette);
  2027             SDL20_free(surface12->format);
  2028         }
  2029         SDL20_free(surface12);
  2030     }
  2031 }
  2032 
  2033 DECLSPEC void SDLCALL
  2034 SDL_GetClipRect(SDL12_Surface *surface12, SDL12_Rect *rect)
  2035 {
  2036     if (surface12 && rect) {
  2037         SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL12_Rect));
  2038     }
  2039 }
  2040 
  2041 DECLSPEC SDL_bool SDLCALL
  2042 SDL_SetClipRect(SDL12_Surface *surface12, const SDL12_Rect *rect12)
  2043 {
  2044     SDL_bool retval = SDL_FALSE;
  2045     if (surface12)
  2046     {
  2047         SDL_Rect rect20;
  2048         retval = SDL20_SetClipRect(surface12->surface20, rect12 ? Rect12to20(rect12, &rect20) : NULL);
  2049         SDL20_GetClipRect(surface12->surface20, &rect20);
  2050         Rect20to12(&rect20, &surface12->clip_rect);
  2051     }
  2052     return retval;
  2053 }
  2054 
  2055 DECLSPEC int SDLCALL
  2056 SDL_FillRect(SDL12_Surface *dst, SDL12_Rect *dstrect12, Uint32 color)
  2057 {
  2058     SDL_Rect dstrect20;
  2059     const int retval = SDL20_FillRect(dst->surface20, dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL, color);
  2060     if (retval != -1)
  2061     {
  2062         if (dstrect12) {  /* 1.2 stores the clip intersection in dstrect */
  2063             SDL_Rect intersected20;
  2064             SDL20_IntersectRect(&dstrect20, &dst->surface20->clip_rect, &intersected20);
  2065             Rect20to12(&intersected20, dstrect12);
  2066         }
  2067     }
  2068     return retval;
  2069 }
  2070 
  2071 
  2072 static SDL_PixelFormat *
  2073 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  2074 {
  2075     palette20->ncolors = format12->palette->ncolors;
  2076     palette20->colors = format12->palette->colors;
  2077     palette20->version = 1;
  2078     palette20->refcount = 1;
  2079     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  2080     format20->palette = palette20;
  2081     format20->BitsPerPixel = format12->BitsPerPixel;
  2082     format20->BytesPerPixel = format12->BytesPerPixel;
  2083     format20->Rmask = format12->Rmask;
  2084     format20->Gmask = format12->Gmask;
  2085     format20->Bmask = format12->Bmask;
  2086     format20->Amask = format12->Amask;
  2087     format20->Rloss = format12->Rloss;
  2088     format20->Gloss = format12->Gloss;
  2089     format20->Bloss = format12->Bloss;
  2090     format20->Aloss = format12->Aloss;
  2091     format20->Rshift = format12->Rshift;
  2092     format20->Gshift = format12->Gshift;
  2093     format20->Bshift = format12->Bshift;
  2094     format20->Ashift = format12->Ashift;
  2095     format20->refcount = 1;
  2096     format20->next = NULL;
  2097     return format20;
  2098 }
  2099 
  2100 DECLSPEC Uint32 SDLCALL
  2101 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  2102 {
  2103     /* This is probably way slower than apps expect. */
  2104     SDL_PixelFormat format20;
  2105     SDL_Palette palette20;
  2106     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  2107 }
  2108 
  2109 DECLSPEC Uint32 SDLCALL
  2110 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  2111 {
  2112     /* This is probably way slower than apps expect. */
  2113     SDL_PixelFormat format20;
  2114     SDL_Palette palette20;
  2115     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  2116 }
  2117 
  2118 DECLSPEC void SDLCALL
  2119 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  2120 {
  2121     /* This is probably way slower than apps expect. */
  2122     SDL_PixelFormat format20;
  2123     SDL_Palette palette20;
  2124     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  2125 }
  2126 
  2127 DECLSPEC void SDLCALL
  2128 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  2129 {
  2130     /* This is probably way slower than apps expect. */
  2131     SDL_PixelFormat format20;
  2132     SDL_Palette palette20;
  2133     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  2134 }
  2135 
  2136 DECLSPEC const SDL12_VideoInfo * SDLCALL
  2137 SDL_GetVideoInfo(void)
  2138 {
  2139     SDL_DisplayMode mode;
  2140 
  2141     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  2142 
  2143     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  2144         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  2145         VideoInfo12.current_w = mode.w;
  2146         VideoInfo12.current_h = mode.h;
  2147         FIXME("vidinfo details commented out");
  2148         //VideoInfo12.wm_available = 1;
  2149         //VideoInfo12.video_mem = 1024 * 256;
  2150     }
  2151     return &VideoInfo12;
  2152 }
  2153 
  2154 DECLSPEC int SDLCALL
  2155 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  2156 {
  2157     int i, nummodes, actual_bpp = 0;
  2158 
  2159     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  2160         return 0;
  2161     }
  2162 
  2163     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  2164         SDL_DisplayMode mode;
  2165         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  2166         return SDL_BITSPERPIXEL(mode.format);
  2167     }
  2168 
  2169     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  2170     for (i = 0; i < nummodes; ++i) {
  2171         SDL_DisplayMode mode;
  2172         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  2173         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  2174             if (!mode.format) {
  2175                 return bpp;
  2176             }
  2177             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  2178                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  2179             }
  2180         }
  2181     }
  2182     return actual_bpp;
  2183 }
  2184 
  2185 DECLSPEC SDL12_Rect ** SDLCALL
  2186 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  2187 {
  2188     Uint32 fmt;
  2189     int i;
  2190 
  2191     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  2192         return NULL;
  2193     }
  2194 
  2195     if ((!format12) && (!VideoInfo12.vfmt)) {
  2196         SDL20_SetError("No pixel format specified");
  2197         return NULL;
  2198     }
  2199 
  2200     if (!(flags & SDL12_FULLSCREEN)) {
  2201         return (SDL12_Rect **) (-1);  /* any resolution is fine. */
  2202     }
  2203 
  2204     if (format12) {
  2205         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  2206     } else {
  2207         fmt = VideoInfo12.vfmt->format;
  2208     }
  2209 
  2210     for (i = 0; i < VideoModesCount; i++) {
  2211         VideoModeList *modes = &VideoModes[i];
  2212         if (modes->format == fmt) {
  2213             return modes->modes12;
  2214         }
  2215     }
  2216 
  2217     SDL20_SetError("No modes support requested pixel format");
  2218     return NULL;
  2219 }
  2220 
  2221 DECLSPEC void SDLCALL
  2222 SDL_FreeCursor(SDL12_Cursor *cursor12)
  2223 {
  2224     if (cursor12) {
  2225         if (cursor12->wm_cursor)
  2226             SDL20_FreeCursor(cursor12->wm_cursor);
  2227         SDL20_free(cursor12->data);
  2228         SDL20_free(cursor12->mask);
  2229         SDL20_free(cursor12);
  2230     }
  2231 }
  2232 
  2233 DECLSPEC SDL12_Cursor * SDLCALL
  2234 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  2235 {
  2236     const size_t datasize = h * (w / 8);
  2237     SDL_Cursor *cursor20 = NULL;
  2238     SDL12_Cursor *retval = NULL;
  2239 
  2240     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  2241     if (!retval)
  2242         goto outofmem;
  2243 
  2244     SDL20_zerop(retval);
  2245 
  2246     retval->data = (Uint8 *) SDL20_malloc(datasize);
  2247     if (!retval->data)
  2248         goto outofmem;
  2249 
  2250     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  2251     if (!retval->mask)
  2252         goto outofmem;
  2253 
  2254     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  2255     if (!cursor20)
  2256         goto failed;
  2257 
  2258     retval->area.w = w;
  2259     retval->area.h = h;
  2260     retval->hot_x = hot_x;
  2261     retval->hot_y = hot_y;
  2262     retval->wm_cursor = cursor20;
  2263     /* we always leave retval->save as null pointers. */
  2264 
  2265     SDL20_memcpy(retval->data, data, datasize);
  2266     SDL20_memcpy(retval->mask, mask, datasize);
  2267 
  2268     return retval;
  2269 
  2270 outofmem:
  2271     SDL20_OutOfMemory();
  2272 
  2273 failed:
  2274     SDL_FreeCursor(retval);
  2275     return NULL;
  2276 }
  2277 
  2278 DECLSPEC void SDLCALL
  2279 SDL_SetCursor(SDL12_Cursor *cursor)
  2280 {
  2281     CurrentCursor12 = cursor;
  2282     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  2283 }
  2284 
  2285 DECLSPEC SDL12_Cursor * SDLCALL
  2286 SDL_GetCursor(void)
  2287 {
  2288     return CurrentCursor12;
  2289 }
  2290 
  2291 static void
  2292 GetEnvironmentWindowPosition(int *x, int *y)
  2293 {
  2294     int display = VideoDisplayIndex;
  2295     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  2296     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  2297     if (window) {
  2298         if (SDL20_strcmp(window, "center") == 0) {
  2299             center = window;
  2300         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  2301             return;
  2302         }
  2303     }
  2304 
  2305     if (center) {
  2306         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  2307         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  2308     }
  2309 }
  2310 
  2311 static void
  2312 SetupScreenSaver(const int flags12)
  2313 {
  2314     const char *env;
  2315     SDL_bool allow_screensaver;
  2316 
  2317     /* Allow environment override of screensaver disable */
  2318     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  2319     if (env) {
  2320         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  2321     } else if (flags12 & SDL12_FULLSCREEN) {
  2322         allow_screensaver = SDL_FALSE;
  2323     } else {
  2324         allow_screensaver = SDL_TRUE;
  2325     }
  2326     if (allow_screensaver) {
  2327         SDL20_EnableScreenSaver();
  2328     } else {
  2329         SDL20_DisableScreenSaver();
  2330     }
  2331 }
  2332 
  2333 
  2334 static SDL12_Surface *
  2335 EndVidModeCreate(void)
  2336 {
  2337     if (VideoTexture20) {
  2338         SDL20_DestroyTexture(VideoTexture20);
  2339         VideoTexture20 = NULL;
  2340     }
  2341     if (VideoRenderer20) {
  2342         SDL20_DestroyRenderer(VideoRenderer20);
  2343         VideoRenderer20 = NULL;
  2344     }
  2345     if (VideoGLContext20) {
  2346         SDL20_GL_MakeCurrent(NULL, NULL);
  2347         SDL20_GL_DeleteContext(VideoGLContext20);
  2348         VideoGLContext20 = NULL;
  2349     }
  2350     if (VideoWindow20) {
  2351         SDL20_DestroyWindow(VideoWindow20);
  2352         VideoWindow20 = NULL;
  2353     }
  2354     if (VideoSurface12) {
  2355         SDL20_free(VideoSurface12->pixels);
  2356         VideoSurface12->pixels = NULL;
  2357         SDL_FreeSurface(VideoSurface12);
  2358         VideoSurface12 = NULL;
  2359     }
  2360     if (VideoConvertSurface20) {
  2361         SDL20_FreeSurface(VideoConvertSurface20);
  2362         VideoConvertSurface20 = NULL;
  2363     }
  2364     return NULL;
  2365 }
  2366 
  2367 
  2368 static SDL12_Surface *
  2369 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  2370 {
  2371     Uint32 rmask, gmask, bmask, amask;
  2372     int bpp;
  2373     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  2374         return NULL;
  2375     }
  2376     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  2377 }
  2378 
  2379 static SDL_Surface *
  2380 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  2381 {
  2382     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  2383     if (surface20) {
  2384         surface20->flags |= SDL_PREALLOC;
  2385         surface20->pixels = NULL;
  2386         surface20->w = width;
  2387         surface20->h = height;
  2388         surface20->pitch = 0;
  2389         SDL20_SetClipRect(surface20, NULL);
  2390     }
  2391     return surface20;
  2392 }
  2393 
  2394 
  2395 DECLSPEC SDL12_Surface * SDLCALL
  2396 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  2397 {
  2398     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  2399     SDL_DisplayMode dmode;
  2400     Uint32 fullscreen_flags20 = 0;
  2401     Uint32 appfmt;
  2402 
  2403     /* SDL_SetVideoMode() implicitly inits if necessary. */
  2404     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  2405         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  2406             return NULL;
  2407         }
  2408     }
  2409 
  2410     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  2411         FIXME("No OPENGLBLIT support at the moment");
  2412         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  2413         return NULL;
  2414     }
  2415 
  2416     FIXME("handle SDL_ANYFORMAT");
  2417 
  2418     if ((width < 0) || (height < 0)) {
  2419         SDL20_SetError("Invalid width or height");
  2420         return NULL;
  2421     }
  2422 
  2423     FIXME("There's an environment variable to choose a display");
  2424     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  2425         return NULL;
  2426     }
  2427 
  2428     if (width == 0) {
  2429         width = dmode.w;
  2430     }
  2431 
  2432     if (height == 0) {
  2433         height = dmode.h;
  2434     }
  2435 
  2436     if (bpp == 0) {
  2437         bpp = SDL_BITSPERPIXEL(dmode.format);
  2438     }
  2439 
  2440     switch (bpp) {
  2441         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  2442         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  2443         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  2444         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  2445         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  2446     }
  2447 
  2448     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  2449 
  2450     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  2451     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  2452 
  2453     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  2454         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  2455     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  2456         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  2457     } else if (VideoGLContext20) {
  2458         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  2459         SDL20_GL_MakeCurrent(NULL, NULL);
  2460         SDL20_GL_DeleteContext(VideoGLContext20);
  2461         VideoGLContext20 = NULL;
  2462     }
  2463 
  2464     if (flags12 & SDL12_FULLSCREEN) {
  2465         // OpenGL tries to force the real resolution requested, but for
  2466         //  software rendering, we're just going to push it off onto the
  2467         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  2468         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  2469         if (flags12 & SDL12_OPENGL) {
  2470             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  2471         } else {
  2472             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  2473         }
  2474     }
  2475 
  2476     if (!VideoWindow20) {  /* create it */
  2477         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  2478         Uint32 flags20 = fullscreen_flags20;
  2479         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  2480         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  2481         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  2482 
  2483         /* most platforms didn't check these environment variables, but the major
  2484            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  2485         GetEnvironmentWindowPosition(&x, &y);
  2486 
  2487         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  2488         if (!VideoWindow20) {
  2489             return EndVidModeCreate();
  2490         }
  2491     } else {  /* resize it */
  2492         SDL20_SetWindowSize(VideoWindow20, width, height);
  2493         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  2494         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  2495         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  2496     }
  2497 
  2498     if (VideoSurface12) {
  2499         SDL20_free(VideoSurface12->pixels);
  2500     } else {
  2501         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  2502         if (!VideoSurface12) {
  2503             return EndVidModeCreate();
  2504         }
  2505     }
  2506 
  2507     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  2508     VideoSurface12->flags |= SDL12_PREALLOC;
  2509     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  2510     VideoSurface12->w = VideoSurface12->surface20->w = width;
  2511     VideoSurface12->h = VideoSurface12->surface20->h = height;
  2512     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  2513     SDL_SetClipRect(VideoSurface12, NULL);
  2514 
  2515     if (flags12 & SDL12_OPENGL) {
  2516         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  2517         SDL_assert(!VideoRenderer20);
  2518         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  2519         if (!VideoGLContext20) {
  2520             return EndVidModeCreate();
  2521         }
  2522 
  2523         VideoSurface12->flags |= SDL12_OPENGL;
  2524     } else {
  2525         /* always use a renderer for non-OpenGL windows. */
  2526         SDL_RendererInfo rinfo;
  2527         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  2528         if (!VideoRenderer20) {
  2529             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  2530         }
  2531         if (!VideoRenderer20) {
  2532             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_PRESENTVSYNC);
  2533         }
  2534         if (!VideoRenderer20) {
  2535             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  2536         }
  2537         if (!VideoRenderer20) {
  2538             return EndVidModeCreate();
  2539         }
  2540 
  2541         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  2542         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  2543         SDL20_RenderClear(VideoRenderer20);
  2544         SDL20_RenderPresent(VideoRenderer20);
  2545         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  2546 
  2547         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  2548             return EndVidModeCreate();
  2549         }
  2550 
  2551         if (VideoTexture20) {
  2552             SDL20_DestroyTexture(VideoTexture20);
  2553         }
  2554 
  2555         if (VideoConvertSurface20) {
  2556             SDL20_FreeSurface(VideoConvertSurface20);
  2557             VideoConvertSurface20 = NULL;
  2558         }
  2559 
  2560         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  2561         if (!VideoTexture20) {
  2562             return EndVidModeCreate();
  2563         }
  2564 
  2565         if (rinfo.texture_formats[0] != appfmt) {
  2566             /* need to convert between app's format and texture format */
  2567             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  2568             if (!VideoConvertSurface20) {
  2569                 return EndVidModeCreate();
  2570             }
  2571         }
  2572 
  2573         VideoSurface12->flags &= ~SDL12_OPENGL;
  2574         VideoSurface12->flags |= SDL12_DOUBLEBUF;
  2575         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  2576         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  2577         if (!VideoSurface12->pixels) {
  2578             SDL20_OutOfMemory();
  2579             return EndVidModeCreate();
  2580         }
  2581 
  2582         /* fill in the same default palette that SDL 1.2 does... */
  2583         if (VideoSurface12->format->BitsPerPixel == 8) {
  2584             int i;
  2585             SDL_Color *color = VideoSurface12->format->palette->colors;
  2586             for (i = 0; i < 256; i++, color++) {
  2587                 { const int x = i & 0xe0; color->r = x | x >> 3 | x >> 6; }
  2588                 { const int x = (i << 3) & 0xe0; color->g = x | x >> 3 | x >> 6; }
  2589                 { const int x = (i & 0x3) | ((i & 0x3) << 2); color->b = x | x << 4; }
  2590                 color->a = 255;
  2591             }
  2592         }
  2593     }
  2594 
  2595     FIXME("setup screen saver");
  2596 
  2597     return VideoSurface12;
  2598 }
  2599 
  2600 DECLSPEC SDL12_Surface * SDLCALL
  2601 SDL_GetVideoSurface(void)
  2602 {
  2603     return VideoSurface12;
  2604 }
  2605 
  2606 DECLSPEC int SDLCALL
  2607 SDL_UpperBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
  2608 {
  2609     SDL_Rect srcrect20, dstrect20;
  2610     const int retval = SDL20_UpperBlit(src->surface20,
  2611                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  2612                                        dst->surface20,
  2613                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  2614 
  2615     if (srcrect12) {
  2616         Rect20to12(&srcrect20, srcrect12);
  2617     }
  2618 
  2619     if (srcrect12) {
  2620         Rect20to12(&dstrect20, dstrect12);
  2621     }
  2622 
  2623     return retval;
  2624 }
  2625 
  2626 DECLSPEC int SDLCALL
  2627 SDL_LowerBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
  2628 {
  2629     SDL_Rect srcrect20, dstrect20;
  2630     const int retval = SDL20_LowerBlit(src->surface20,
  2631                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  2632                                        dst->surface20,
  2633                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  2634 
  2635     if (srcrect12) {
  2636         Rect20to12(&srcrect20, srcrect12);
  2637     }
  2638 
  2639     if (srcrect12) {
  2640         Rect20to12(&dstrect20, dstrect12);
  2641     }
  2642 
  2643     return retval;
  2644 }
  2645 
  2646 DECLSPEC int SDLCALL
  2647 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  2648 {
  2649     FIXME("write me");
  2650     return SDL20_Unsupported();
  2651 }
  2652 
  2653 DECLSPEC int SDLCALL
  2654 SDL_LockSurface(SDL12_Surface *surface12)
  2655 {
  2656     const int retval = SDL20_LockSurface(surface12->surface20);
  2657     surface12->pixels = surface12->surface20->pixels;
  2658     surface12->pitch = surface12->surface20->pitch;
  2659     return retval;
  2660 }
  2661 
  2662 DECLSPEC void SDLCALL
  2663 SDL_UnlockSurface(SDL12_Surface *surface12)
  2664 {
  2665     SDL20_UnlockSurface(surface12->surface20);
  2666     surface12->pixels = surface12->surface20->pixels;
  2667     surface12->pitch = surface12->surface20->pitch;
  2668 }
  2669 
  2670 DECLSPEC SDL12_Surface * SDLCALL
  2671 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
  2672 {
  2673     Uint32 flags20 = 0;
  2674     SDL_PixelFormat format20;
  2675     SDL_Palette palette20;
  2676     SDL_Surface *surface20;
  2677     SDL12_Surface *retval = NULL;
  2678 
  2679     if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
  2680     if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
  2681 
  2682     surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
  2683     if (surface20) {
  2684         retval = Surface20to12(surface20);
  2685         if (!retval) {
  2686             SDL20_FreeSurface(surface20);
  2687         }
  2688     }
  2689     return retval;
  2690 }
  2691 
  2692 DECLSPEC SDL12_Surface * SDLCALL
  2693 SDL_DisplayFormat(SDL12_Surface *surface12)
  2694 {
  2695     const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
  2696     return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
  2697 }
  2698 
  2699 DECLSPEC SDL12_Surface * SDLCALL
  2700 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  2701 {
  2702     FIXME("write me");
  2703     SDL20_Unsupported();
  2704     return NULL;
  2705 }
  2706 
  2707 static void
  2708 PresentScreen(void)
  2709 {
  2710     void *pixels = NULL;
  2711     int pitch = 0;
  2712 
  2713     SDL_assert(VideoSurface12 != NULL);
  2714 
  2715     if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
  2716         return;  /* oh well */
  2717     }
  2718 
  2719     FIXME("Maybe lock texture always, until present, if no conversion needed?");
  2720     VideoConvertSurface20->pixels = pixels;
  2721     VideoConvertSurface20->pitch = pitch;
  2722     SDL20_UpperBlit(VideoSurface12->surface20, NULL, VideoConvertSurface20, NULL);
  2723     VideoConvertSurface20->pixels = NULL;
  2724     VideoConvertSurface20->pitch = 0;
  2725 
  2726     SDL20_UnlockTexture(VideoTexture20);
  2727     SDL20_RenderCopy(VideoRenderer20, VideoTexture20, NULL, NULL);
  2728     SDL20_RenderPresent(VideoRenderer20);
  2729 }
  2730 
  2731 DECLSPEC void SDLCALL
  2732 SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
  2733 {
  2734     /* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
  2735     /* (UpdateRect, singular, does...) */
  2736     if (surface12->flags & SDL12_OPENGL) {
  2737         SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2738         return;
  2739     }
  2740 
  2741     /* everything else is marked SDL12_DOUBLEBUF and is a no-op here. */
  2742 }
  2743 
  2744 DECLSPEC void SDLCALL
  2745 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  2746 {
  2747     if (screen12) {
  2748         SDL12_Rect rect12;
  2749         rect12.x = (Sint16) x;
  2750         rect12.y = (Sint16) y;
  2751         rect12.w = (Uint16) (w ? w : screen12->w);
  2752         rect12.h = (Uint16) (h ? h : screen12->h);
  2753         SDL_UpdateRects(screen12, 1, &rect12);
  2754     }
  2755 }
  2756 
  2757 DECLSPEC int SDLCALL
  2758 SDL_Flip(SDL12_Surface *surface12)
  2759 {
  2760     if (surface12->flags & SDL12_OPENGL) {
  2761         return SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2762     }
  2763 
  2764     if (surface12 == VideoSurface12) {
  2765         PresentScreen();
  2766     }
  2767 
  2768     return 0;
  2769 }
  2770 
  2771 DECLSPEC void SDLCALL
  2772 SDL_WM_SetCaption(const char *title, const char *icon)
  2773 {
  2774     if (WindowTitle) {
  2775         SDL20_free(WindowTitle);
  2776     }
  2777     if (WindowIconTitle) {
  2778         SDL20_free(WindowIconTitle);
  2779     }
  2780     WindowTitle = title ? SDL_strdup(title) : NULL;
  2781     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  2782     if (VideoWindow20) {
  2783         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  2784     }
  2785 }
  2786 
  2787 DECLSPEC void SDLCALL
  2788 SDL_WM_GetCaption(const char **title, const char **icon)
  2789 {
  2790     if (title) {
  2791         *title = WindowTitle;
  2792     }
  2793     if (icon) {
  2794         *icon = WindowIconTitle;
  2795     }
  2796 }
  2797 
  2798 DECLSPEC void SDLCALL
  2799 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2800 {
  2801     FIXME("write me");
  2802     SDL20_Unsupported();
  2803 }
  2804 
  2805 DECLSPEC int SDLCALL
  2806 SDL_WM_IconifyWindow(void)
  2807 {
  2808     SDL20_MinimizeWindow(VideoWindow20);
  2809     return 0;
  2810 }
  2811 
  2812 DECLSPEC int SDLCALL
  2813 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  2814 {
  2815     FIXME("write me");
  2816     return SDL20_Unsupported();
  2817 }
  2818 
  2819 typedef enum
  2820 {
  2821     SDL12_GRAB_QUERY = -1,
  2822     SDL12_GRAB_OFF = 0,
  2823     SDL12_GRAB_ON = 1
  2824 } SDL12_GrabMode;
  2825 
  2826 DECLSPEC SDL12_GrabMode SDLCALL
  2827 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2828 {
  2829     if (mode != SDL12_GRAB_QUERY) {
  2830         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2831     }
  2832     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2833 }
  2834 
  2835 DECLSPEC void SDLCALL
  2836 SDL_WarpMouse(Uint16 x, Uint16 y)
  2837 {
  2838     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2839 }
  2840 
  2841 DECLSPEC Uint8 SDLCALL
  2842 SDL_GetAppState(void)
  2843 {
  2844     Uint8 state12 = 0;
  2845     Uint32 flags20 = 0;
  2846 
  2847     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2848     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2849         state12 |= SDL12_APPACTIVE;
  2850     }
  2851     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2852         state12 |= SDL12_APPINPUTFOCUS;
  2853     }
  2854     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2855         state12 |= SDL12_APPMOUSEFOCUS;
  2856     }
  2857     return state12;
  2858 }
  2859 
  2860 DECLSPEC int SDLCALL
  2861 SDL_SetColorKey(SDL12_Surface *surface12, Uint32 flag12, Uint32 key)
  2862 {
  2863     const SDL_bool addkey = (flag12 & SDL12_SRCCOLORKEY) ? SDL_TRUE : SDL_FALSE;
  2864     const int retval = SDL20_SetColorKey(surface12->surface20, addkey, key);
  2865     if (SDL20_GetColorKey(surface12->surface20, &surface12->format->colorkey) < 0) {
  2866         surface12->format->colorkey = 0;
  2867     }
  2868     return retval;
  2869 }
  2870 
  2871 DECLSPEC int SDLCALL
  2872 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2873                int firstcolor, int ncolors)
  2874 {
  2875     FIXME("write me");
  2876     return SDL20_Unsupported();
  2877 }
  2878 
  2879 DECLSPEC int SDLCALL
  2880 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2881               int ncolors)
  2882 {
  2883     FIXME("write me");
  2884     return SDL20_Unsupported();
  2885 }
  2886 
  2887 DECLSPEC int SDLCALL
  2888 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2889 {
  2890     FIXME("write me");
  2891     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  2892     return SDL20_Unsupported();
  2893 }
  2894 
  2895 DECLSPEC SDL12_Overlay * SDLCALL
  2896 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2897 {
  2898     FIXME("write me");
  2899     SDL20_Unsupported();
  2900     return NULL;
  2901 }
  2902 
  2903 DECLSPEC int SDLCALL
  2904 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  2905 {
  2906     FIXME("write me");
  2907     return SDL20_Unsupported();
  2908 }
  2909 
  2910 DECLSPEC void SDLCALL
  2911 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  2912 {
  2913     FIXME("write me");
  2914 }
  2915 
  2916 DECLSPEC int SDLCALL
  2917 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL12_Rect * dstrect12)
  2918 {
  2919     FIXME("write me");
  2920     return SDL20_Unsupported();
  2921 }
  2922 
  2923 DECLSPEC void SDLCALL
  2924 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  2925 {
  2926     FIXME("write me");
  2927 }
  2928 
  2929 DECLSPEC int SDLCALL
  2930 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2931 {
  2932     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2933         return SDL20_SetError("Unknown GL attribute");
  2934 
  2935     /* swap control was moved out of this API, everything else lines up. */
  2936     if (attr == SDL12_GL_SWAP_CONTROL)
  2937     {
  2938         SwapInterval = value;
  2939         FIXME("Actually set swap interval somewhere");
  2940         return 0;
  2941     }
  2942 
  2943     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2944 }
  2945 
  2946 DECLSPEC int SDLCALL
  2947 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2948 {
  2949     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2950         return SDL20_SetError("Unknown GL attribute");
  2951 
  2952     /* swap control was moved out of this API, everything else lines up. */
  2953     if (attr == SDL12_GL_SWAP_CONTROL)
  2954     {
  2955         *value = SDL20_GL_GetSwapInterval();
  2956         return 0;
  2957     }
  2958 
  2959     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2960 }
  2961 
  2962 
  2963 DECLSPEC void SDLCALL
  2964 SDL_GL_SwapBuffers(void)
  2965 {
  2966     if (VideoWindow20)
  2967         SDL20_GL_SwapWindow(VideoWindow20);
  2968 }
  2969 
  2970 DECLSPEC int SDLCALL
  2971 SDL_SetGamma(float red, float green, float blue)
  2972 {
  2973     Uint16 red_ramp[256];
  2974     Uint16 green_ramp[256];
  2975     Uint16 blue_ramp[256];
  2976 
  2977     SDL20_CalculateGammaRamp(red, red_ramp);
  2978     if (green == red) {
  2979         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2980     } else {
  2981         SDL20_CalculateGammaRamp(green, green_ramp);
  2982     }
  2983     if (blue == red) {
  2984         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2985     } else if (blue == green) {
  2986         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2987     } else {
  2988         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2989     }
  2990     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2991 }
  2992 
  2993 DECLSPEC int SDLCALL
  2994 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2995 {
  2996     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2997 }
  2998 
  2999 DECLSPEC int SDLCALL
  3000 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  3001 {
  3002     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  3003 }
  3004 
  3005 DECLSPEC int SDLCALL
  3006 SDL_EnableKeyRepeat(int delay, int interval)
  3007 {
  3008     FIXME("write me");
  3009     return 0;
  3010 }
  3011 
  3012 DECLSPEC void SDLCALL
  3013 SDL_GetKeyRepeat(int *delay, int *interval)
  3014 {
  3015     FIXME("write me");
  3016     if (delay) {
  3017         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  3018     }
  3019     if (interval) {
  3020         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  3021     }
  3022 }
  3023 
  3024 DECLSPEC int SDLCALL
  3025 SDL_EnableUNICODE(int enable)
  3026 {
  3027     FIXME("write me");
  3028     return SDL20_Unsupported();
  3029 }
  3030 
  3031 static Uint32
  3032 SetTimerOld_Callback(Uint32 interval, void* param)
  3033 {
  3034     return ((SDL12_TimerCallback)param)(interval);
  3035 }
  3036 
  3037 DECLSPEC int SDLCALL
  3038 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  3039 {
  3040     static SDL_TimerID compat_timer;
  3041 
  3042     if (compat_timer) {
  3043         SDL20_RemoveTimer(compat_timer);
  3044         compat_timer = 0;
  3045     }
  3046 
  3047     if (interval && callback) {
  3048         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  3049         if (!compat_timer) {
  3050             return -1;
  3051         }
  3052     }
  3053     return 0;
  3054 }
  3055 
  3056 DECLSPEC int SDLCALL
  3057 SDL_putenv(const char *_var)
  3058 {
  3059     char *ptr = NULL;
  3060     char *var = SDL20_strdup(_var);
  3061     if (var == NULL) {
  3062         return -1;  /* we don't set errno. */
  3063     }
  3064 
  3065     ptr = SDL20_strchr(var, '=');
  3066     if (ptr == NULL) {
  3067         SDL20_free(var);
  3068         return -1;
  3069     }
  3070 
  3071     *ptr = '\0';  /* split the string into name and value. */
  3072     SDL20_setenv(var, ptr + 1, 1);
  3073     SDL20_free(var);
  3074     return 0;
  3075 }
  3076 
  3077 
  3078 
  3079 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  3080 
  3081 typedef void *SDL12_CD;  /* close enough.  :) */
  3082 typedef int SDL12_CDstatus;  /* close enough.  :) */
  3083 
  3084 DECLSPEC int SDLCALL
  3085 SDL_CDNumDrives(void)
  3086 {
  3087     FIXME("should return -1 without SDL_INIT_CDROM");
  3088     return 0;
  3089 }
  3090 
  3091 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  3092 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  3093 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3094 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  3095 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  3096 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3097 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3098 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3099 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  3100 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  3101 
  3102 
  3103 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  3104 DECLSPEC SDL_Thread * SDLCALL
  3105 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  3106 {
  3107     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  3108 }
  3109 #else
  3110 DECLSPEC SDL_Thread * SDLCALL
  3111 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  3112 {
  3113     return SDL20_CreateThread(fn, NULL, data);
  3114 }
  3115 #endif
  3116 
  3117 DECLSPEC int SDLCALL
  3118 SDL_mutexP(SDL_mutex *mutex)
  3119 {
  3120     return SDL20_LockMutex(mutex);
  3121 }
  3122 
  3123 DECLSPEC int SDLCALL
  3124 SDL_mutexV(SDL_mutex *mutex)
  3125 {
  3126     return SDL20_UnlockMutex(mutex);
  3127 }
  3128 
  3129 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
  3130 {
  3131     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  3132     fprintf(stderr,
  3133         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  3134         "This program should be fixed. No thread was actually harmed.\n");
  3135 }
  3136 
  3137 /* This changed from an opaque pointer to an int in 2.0. */
  3138 typedef struct _SDL12_TimerID *SDL12_TimerID;
  3139 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  3140 
  3141 
  3142 DECLSPEC SDL12_TimerID SDLCALL
  3143 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  3144 {
  3145     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  3146 }
  3147 
  3148 DECLSPEC SDL_bool SDLCALL
  3149 SDL_RemoveTimer(SDL12_TimerID id)
  3150 {
  3151     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  3152 }
  3153 
  3154 
  3155 typedef struct SDL12_RWops {
  3156     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  3157     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  3158     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  3159     int (SDLCALL *close)(struct SDL12_RWops *context);
  3160     Uint32 type;
  3161     void *padding[8];
  3162     SDL_RWops *rwops20;
  3163 } SDL12_RWops;
  3164 
  3165 
  3166 DECLSPEC SDL12_RWops * SDLCALL
  3167 SDL_AllocRW(void)
  3168 {
  3169     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  3170     if (!rwops)
  3171         SDL20_OutOfMemory();
  3172     return rwops;
  3173 }
  3174 
  3175 DECLSPEC void SDLCALL
  3176 SDL_FreeRW(SDL12_RWops *rwops12)
  3177 {
  3178     SDL20_free(rwops12);
  3179 }
  3180 
  3181 static int SDLCALL
  3182 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  3183 {
  3184     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  3185 }
  3186 
  3187 static int SDLCALL
  3188 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  3189 {
  3190     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  3191 }
  3192 
  3193 static int SDLCALL
  3194 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  3195 {
  3196     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  3197 }
  3198 
  3199 static int SDLCALL
  3200 RWops20to12_close(struct SDL12_RWops *rwops12)
  3201 {
  3202     int rc = 0;
  3203     if (rwops12)
  3204     {
  3205         rc = rwops12->rwops20->close(rwops12->rwops20);
  3206         if (rc == 0)
  3207             SDL_FreeRW(rwops12);
  3208     }
  3209     return rc;
  3210 }
  3211 
  3212 static SDL12_RWops *
  3213 RWops20to12(SDL_RWops *rwops20)
  3214 {
  3215     SDL12_RWops *rwops12;
  3216 
  3217     if (!rwops20)
  3218         return NULL;
  3219 
  3220     rwops12 = SDL_AllocRW();
  3221     if (!rwops12)
  3222         return NULL;
  3223 
  3224     SDL20_zerop(rwops12);
  3225     rwops12->type = rwops20->type;
  3226     rwops12->rwops20 = rwops20;
  3227     rwops12->seek = RWops20to12_seek;
  3228     rwops12->read = RWops20to12_read;
  3229     rwops12->write = RWops20to12_write;
  3230     rwops12->close = RWops20to12_close;
  3231 
  3232     return rwops12;
  3233 }
  3234 
  3235 DECLSPEC SDL12_RWops * SDLCALL
  3236 SDL_RWFromFile(const char *file, const char *mode)
  3237 {
  3238     return RWops20to12(SDL20_RWFromFile(file, mode));
  3239 }
  3240 
  3241 DECLSPEC SDL12_RWops * SDLCALL
  3242 SDL_RWFromFP(FILE *io, int autoclose)
  3243 {
  3244     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  3245 }
  3246 
  3247 DECLSPEC SDL12_RWops * SDLCALL
  3248 SDL_RWFromMem(void *mem, int size)
  3249 {
  3250     return RWops20to12(SDL20_RWFromMem(mem, size));
  3251 }
  3252 
  3253 DECLSPEC SDL12_RWops * SDLCALL
  3254 SDL_RWFromConstMem(const void *mem, int size)
  3255 {
  3256     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  3257 }
  3258 
  3259 #define READ_AND_BYTESWAP(endian, bits) \
  3260     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  3261         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  3262         return SDL_Swap##endian##bits(val); \
  3263     }
  3264 
  3265 READ_AND_BYTESWAP(LE,16)
  3266 READ_AND_BYTESWAP(BE,16)
  3267 READ_AND_BYTESWAP(LE,32)
  3268 READ_AND_BYTESWAP(BE,32)
  3269 READ_AND_BYTESWAP(LE,64)
  3270 READ_AND_BYTESWAP(BE,64)
  3271 #undef READ_AND_BYTESWAP
  3272 
  3273 #define BYTESWAP_AND_WRITE(endian, bits) \
  3274     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  3275         val = SDL_Swap##endian##bits(val); \
  3276         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  3277     }
  3278 BYTESWAP_AND_WRITE(LE,16)
  3279 BYTESWAP_AND_WRITE(BE,16)
  3280 BYTESWAP_AND_WRITE(LE,32)
  3281 BYTESWAP_AND_WRITE(BE,32)
  3282 BYTESWAP_AND_WRITE(LE,64)
  3283 BYTESWAP_AND_WRITE(BE,64)
  3284 #undef BYTESWAP_AND_WRITE
  3285 
  3286 
  3287 static Sint64 SDLCALL
  3288 RWops12to20_size(struct SDL_RWops *rwops20)
  3289 {
  3290     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3291     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  3292     int pos;
  3293 
  3294     if (size != -1)
  3295         return size;
  3296 
  3297     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  3298     if (pos == -1)
  3299         return -1;
  3300 
  3301     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  3302     if (size == -1)
  3303         return -1;
  3304 
  3305     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  3306     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  3307     return size;
  3308 }
  3309 
  3310 static Sint64 SDLCALL
  3311 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  3312 {
  3313     FIXME("fail if (offset) is too big");
  3314     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3315     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  3316 }
  3317 
  3318 static size_t SDLCALL
  3319 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  3320 {
  3321     FIXME("fail if (size) or (maxnum) is too big");
  3322     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3323     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  3324 }
  3325 
  3326 static size_t SDLCALL
  3327 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  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->write(rwops12, ptr, (int) size, (int) num);
  3332 }
  3333 
  3334 static int SDLCALL
  3335 RWops12to20_close(struct SDL_RWops *rwops20)
  3336 {
  3337     int rc = 0;
  3338     if (rwops20)
  3339     {
  3340         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3341         rc = rwops12->close(rwops12);
  3342         if (rc == 0)
  3343             SDL20_FreeRW(rwops20);
  3344     }
  3345     return rc;
  3346 }
  3347 
  3348 static SDL_RWops *
  3349 RWops12to20(SDL12_RWops *rwops12)
  3350 {
  3351     SDL_RWops *rwops20;
  3352 
  3353     if (!rwops12)
  3354         return NULL;
  3355 
  3356     rwops20 = SDL20_AllocRW();
  3357     if (!rwops20)
  3358         return NULL;
  3359 
  3360     SDL20_zerop(rwops20);
  3361     rwops20->type = rwops12->type;
  3362     rwops20->hidden.unknown.data1 = rwops12;
  3363     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  3364     rwops20->size = RWops12to20_size;
  3365     rwops20->seek = RWops12to20_seek;
  3366     rwops20->read = RWops12to20_read;
  3367     rwops20->write = RWops12to20_write;
  3368     rwops20->close = RWops12to20_close;
  3369     return rwops20;
  3370 }
  3371 
  3372 DECLSPEC SDL12_Surface * SDLCALL
  3373 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  3374 {
  3375     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3376     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  3377     SDL12_Surface *surface12 = Surface20to12(surface20);
  3378     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3379         SDL20_FreeRW(rwops20);
  3380     if ((!surface12) && (surface20))
  3381         SDL20_FreeSurface(surface20);
  3382     return surface12;
  3383 }
  3384 
  3385 DECLSPEC int SDLCALL
  3386 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  3387 {
  3388     FIXME("wrap surface");
  3389     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3390     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  3391     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3392         SDL20_FreeRW(rwops20);
  3393     return retval;
  3394 }
  3395 
  3396 DECLSPEC SDL_AudioSpec * SDLCALL
  3397 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  3398                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  3399 {
  3400     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3401     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  3402     FIXME("deal with non-1.2 formats, like float32");
  3403     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3404         SDL20_FreeRW(rwops20);
  3405     return retval;
  3406 }
  3407 
  3408 /* vi: set ts=4 sw=4 expandtab: */