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