src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 14 Feb 2019 14:28:40 -0500
changeset 62 a26906f18e84
parent 61 832594ced260
child 64 9e17c11fc222
permissions -rw-r--r--
Support code for macOS binaries that statically linked against 1.2's SDLmain.
     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_ConvertSurface
    54 // !!! IMPLEMENT_ME SDL_CreateYUVOverlay
    55 
    56 // !!! IMPLEMENT_ME SDL_DisplayFormat
    57 // !!! IMPLEMENT_ME SDL_DisplayFormatAlpha
    58 // !!! IMPLEMENT_ME SDL_DisplayYUVOverlay
    59 // !!! IMPLEMENT_ME SDL_EnableKeyRepeat
    60 // !!! IMPLEMENT_ME SDL_EnableUNICODE
    61 // !!! IMPLEMENT_ME SDL_FreeYUVOverlay
    62 
    63 // !!! IMPLEMENT_ME SDL_GL_Lock
    64 // !!! IMPLEMENT_ME SDL_GL_Unlock
    65 // !!! IMPLEMENT_ME SDL_GL_UpdateRects
    66 
    67 // !!! IMPLEMENT_ME SDL_GetKeyName
    68 // !!! IMPLEMENT_ME SDL_GetKeyState
    69 // !!! IMPLEMENT_ME SDL_GetModState
    70 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    71 
    72 // !!! IMPLEMENT_ME SDL_GetVideoSurface
    73 // !!! IMPLEMENT_ME SDL_GetWMInfo
    74 
    75 // !!! IMPLEMENT_ME SDL_LockSurface
    76 // !!! IMPLEMENT_ME SDL_LockYUVOverlay
    77 // !!! IMPLEMENT_ME SDL_LowerBlit
    78 
    79 // !!! IMPLEMENT_ME SDL_SetAlpha
    80 // !!! IMPLEMENT_ME SDL_SetColorKey
    81 // !!! IMPLEMENT_ME SDL_SetColors
    82 
    83 // !!! IMPLEMENT_ME SDL_SetModState
    84 // !!! IMPLEMENT_ME SDL_SetPalette
    85 // !!! IMPLEMENT_ME SDL_SetVideoMode
    86 // !!! IMPLEMENT_ME SDL_SoftStretch
    87 // !!! IMPLEMENT_ME SDL_UnlockSurface
    88 // !!! IMPLEMENT_ME SDL_UnlockYUVOverlay
    89 // !!! IMPLEMENT_ME SDL_UpdateRects
    90 // !!! IMPLEMENT_ME SDL_UpperBlit
    91 
    92 // !!! FIXME: should SDL_VideoInit really be a passthrough?
    93 // !!! FIXME: should SDL_VideoQuit really be a passthrough?
    94 
    95 // !!! IMPLEMENT_ME SDL_WM_SetIcon
    96 // !!! IMPLEMENT_ME SDL_WM_ToggleFullScreen
    97 
    98 // !!! IMPLEMENT_ME X11_KeyToUnicode
    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_Palette
   146 {
   147     int       ncolors;
   148     SDL_Color *colors;
   149 } SDL12_Palette;
   150 
   151 typedef struct SDL12_PixelFormat
   152 {
   153     SDL12_Palette *palette;
   154     Uint8 BitsPerPixel;
   155     Uint8 BytesPerPixel;
   156     Uint8 Rloss;
   157     Uint8 Gloss;
   158     Uint8 Bloss;
   159     Uint8 Aloss;
   160     Uint8 Rshift;
   161     Uint8 Gshift;
   162     Uint8 Bshift;
   163     Uint8 Ashift;
   164     Uint32 Rmask;
   165     Uint32 Gmask;
   166     Uint32 Bmask;
   167     Uint32 Amask;
   168     Uint32 colorkey;
   169     Uint8 alpha;
   170 } SDL12_PixelFormat;
   171 
   172 typedef struct SDL12_Surface
   173 {
   174     Uint32 flags;
   175     SDL12_PixelFormat *format;
   176     int w;
   177     int h;
   178     Uint16 pitch;
   179     void *pixels;
   180     int offset;
   181     SDL_Surface *surface20; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here named "hwdata". */
   182     SDL_Rect clip_rect;
   183     Uint32 unused1;
   184     Uint32 locked;
   185     void *blitmap;
   186     unsigned int format_version;
   187     int refcount;
   188 } SDL12_Surface;
   189 
   190 typedef struct SDL12_Overlay
   191 {
   192     Uint32 format;
   193     int w;
   194     int h;
   195     int planes;
   196     Uint16 *pitches;
   197     Uint8 **pixels;
   198     void *hwfuncs;
   199     void *hwdata;
   200     Uint32 hw_overlay :1;
   201     Uint32 UnusedBits :31;
   202 } SDL12_Overlay;
   203 
   204 typedef struct
   205 {
   206     Uint32 hw_available :1;
   207     Uint32 wm_available :1;
   208     Uint32 UnusedBits1  :6;
   209     Uint32 UnusedBits2  :1;
   210     Uint32 blit_hw      :1;
   211     Uint32 blit_hw_CC   :1;
   212     Uint32 blit_hw_A    :1;
   213     Uint32 blit_sw      :1;
   214     Uint32 blit_sw_CC   :1;
   215     Uint32 blit_sw_A    :1;
   216     Uint32 blit_fill    :1;
   217     Uint32 UnusedBits3  :16;
   218     Uint32 video_mem;
   219     SDL_PixelFormat *vfmt;
   220     int current_w;
   221     int current_h;
   222 } SDL12_VideoInfo;
   223 
   224 
   225 #define SDL12_HWSURFACE 0x00000001
   226 #define SDL12_ASYNCBLIT 0x00000004
   227 #define SDL12_ANYFORMAT 0x10000000
   228 #define SDL12_HWPALETTE 0x20000000
   229 #define SDL12_DOUBLEBUF 0x40000000
   230 #define SDL12_FULLSCREEN 0x80000000
   231 #define SDL12_OPENGL 0x00000002
   232 #define SDL12_OPENGLBLIT 0x0000000A
   233 #define SDL12_RESIZABLE 0x00000010
   234 #define SDL12_NOFRAME 0x00000020
   235 #define SDL12_HWACCEL 0x00000100
   236 #define SDL12_SRCCOLORKEY 0x00001000
   237 #define SDL12_RLEACCELOK 0x00002000
   238 #define SDL12_RLEACCEL 0x00004000
   239 #define SDL12_SRCALPHA 0x00010000
   240 #define SDL12_PREALLOC 0x01000000
   241 
   242 typedef enum
   243 {
   244     SDL12_NOEVENT = 0,
   245     SDL12_ACTIVEEVENT,
   246     SDL12_KEYDOWN,
   247     SDL12_KEYUP,
   248     SDL12_MOUSEMOTION,
   249     SDL12_MOUSEBUTTONDOWN,
   250     SDL12_MOUSEBUTTONUP,
   251     SDL12_JOYAXISMOTION,
   252     SDL12_JOYBALLMOTION,
   253     SDL12_JOYHATMOTION,
   254     SDL12_JOYBUTTONDOWN,
   255     SDL12_JOYBUTTONUP,
   256     SDL12_QUIT,
   257     SDL12_SYSWMEVENT,
   258     SDL12_EVENT_RESERVEDA,
   259     SDL12_EVENT_RESERVEDB,
   260     SDL12_VIDEORESIZE,
   261     SDL12_VIDEOEXPOSE,
   262     SDL12_USEREVENT = 24,
   263     SDL12_NUMEVENTS = 32
   264 } SDL12_EventType;
   265 
   266 
   267 #define SDL12_APPMOUSEFOCUS (1<<0)
   268 #define SDL12_APPINPUTFOCUS (1<<1)
   269 #define SDL12_APPACTIVE     (1<<2)
   270 
   271 typedef struct
   272 {
   273     Uint8 type;
   274     Uint8 gain;
   275     Uint8 state;
   276 } SDL12_ActiveEvent;
   277 
   278 typedef struct
   279 {
   280     Uint8 type;
   281     Uint8 which;
   282     Uint8 state;
   283     //FIXME: SDL12_keysym keysym;
   284 } SDL12_KeyboardEvent;
   285 
   286 typedef struct
   287 {
   288     Uint8 type;
   289     Uint8 which;
   290     Uint8 state;
   291     Uint16 x, y;
   292     Sint16 xrel;
   293     Sint16 yrel;
   294 } SDL12_MouseMotionEvent;
   295 
   296 typedef struct
   297 {
   298     Uint8 type;
   299     Uint8 which;
   300     Uint8 button;
   301     Uint8 state;
   302     Uint16 x, y;
   303 } SDL12_MouseButtonEvent;
   304 
   305 typedef struct
   306 {
   307     Uint8 type;
   308     Uint8 which;
   309     Uint8 axis;
   310     Sint16 value;
   311 } SDL12_JoyAxisEvent;
   312 
   313 typedef struct
   314 {
   315     Uint8 type;
   316     Uint8 which;
   317     Uint8 ball;
   318     Sint16 xrel;
   319     Sint16 yrel;
   320 } SDL12_JoyBallEvent;
   321 
   322 typedef struct
   323 {
   324     Uint8 type;
   325     Uint8 which;
   326     Uint8 hat;
   327     Uint8 value;
   328 } SDL12_JoyHatEvent;
   329 
   330 typedef struct
   331 {
   332     Uint8 type;
   333     Uint8 which;
   334     Uint8 button;
   335     Uint8 state;
   336 } SDL12_JoyButtonEvent;
   337 
   338 typedef struct
   339 {
   340     Uint8 type;
   341     int w;
   342     int h;
   343 } SDL12_ResizeEvent;
   344 
   345 typedef struct
   346 {
   347     Uint8 type;
   348 } SDL12_ExposeEvent;
   349 
   350 typedef struct
   351 {
   352     Uint8 type;
   353 } SDL12_QuitEvent;
   354 
   355 typedef struct
   356 {
   357     Uint8 type;
   358     int code;
   359     void *data1;
   360     void *data2;
   361 } SDL12_UserEvent;
   362 
   363 typedef struct
   364 {
   365     Uint8 type;
   366     void *msg;
   367 } SDL12_SysWMEvent;
   368 
   369 typedef union
   370 {
   371     Uint8 type;
   372     SDL12_ActiveEvent active;
   373     SDL12_KeyboardEvent key;
   374     SDL12_MouseMotionEvent motion;
   375     SDL12_MouseButtonEvent button;
   376     SDL12_JoyAxisEvent jaxis;
   377     SDL12_JoyBallEvent jball;
   378     SDL12_JoyHatEvent jhat;
   379     SDL12_JoyButtonEvent jbutton;
   380     SDL12_ResizeEvent resize;
   381     SDL12_ExposeEvent expose;
   382     SDL12_QuitEvent quit;
   383     SDL12_UserEvent user;
   384     SDL12_SysWMEvent syswm;
   385 } SDL12_Event;
   386 
   387 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
   388 static int EventFilter20to12(void *data, SDL_Event *event20);
   389 
   390 typedef Uint32 (SDLCALL *SDL12_TimerCallback)(Uint32 interval);
   391 typedef SDL_TimerCallback SDL12_NewTimerCallback;
   392 
   393 typedef struct
   394 {
   395     SDL_Rect area;
   396     Sint16 hot_x;
   397     Sint16 hot_y;
   398     Uint8 *data;
   399     Uint8 *mask;
   400     Uint8 *save[2];
   401     SDL_Cursor *wm_cursor;  /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
   402 } SDL12_Cursor;
   403 
   404 typedef enum
   405 {
   406     SDL12_GL_RED_SIZE,
   407     SDL12_GL_GREEN_SIZE,
   408     SDL12_GL_BLUE_SIZE,
   409     SDL12_GL_ALPHA_SIZE,
   410     SDL12_GL_BUFFER_SIZE,
   411     SDL12_GL_DOUBLEBUFFER,
   412     SDL12_GL_DEPTH_SIZE,
   413     SDL12_GL_STENCIL_SIZE,
   414     SDL12_GL_ACCUM_RED_SIZE,
   415     SDL12_GL_ACCUM_GREEN_SIZE,
   416     SDL12_GL_ACCUM_BLUE_SIZE,
   417     SDL12_GL_ACCUM_ALPHA_SIZE,
   418     SDL12_GL_STEREO,
   419     SDL12_GL_MULTISAMPLEBUFFERS,
   420     SDL12_GL_MULTISAMPLESAMPLES,
   421     SDL12_GL_ACCELERATED_VISUAL,
   422     SDL12_GL_SWAP_CONTROL,
   423     SDL12_GL_MAX_ATTRIBUTE
   424 } SDL12_GLattr;
   425 
   426 
   427 typedef struct
   428 {
   429     Uint32 format;
   430     SDL_Rect *modeslist;
   431     SDL_Rect **modes;  /* ptrs to each item in modeslist, for SDL_ListModes() */
   432 } VideoModeList;
   433 
   434 // !!! FIXME: go through all of these.
   435 static VideoModeList *VideoModes = NULL;
   436 static int VideoModesCount = 0;
   437 static SDL12_VideoInfo VideoInfo12;
   438 static SDL_Window *VideoWindow20 = NULL;
   439 static SDL_Renderer *VideoRenderer20 = NULL;
   440 static SDL_Texture *VideoTexture20 = NULL;
   441 static SDL12_Surface *VideoSurface12 = NULL;
   442 static SDL_Surface *VideoConvertSurface20 = NULL;
   443 static SDL_GLContext *VideoGLContext20 = NULL;
   444 static char *WindowTitle = NULL;
   445 static char *WindowIconTitle = NULL;
   446 static SDL12_Surface *VideoIcon12;
   447 static int EnabledUnicode = 0;
   448 static int VideoDisplayIndex = 0;
   449 static int CDRomInit = 0;
   450 static SDL12_EventFilter EventFilter12 = NULL;
   451 static SDL12_Cursor *CurrentCursor12 = NULL;
   452 static Uint8 EventStates[SDL12_NUMEVENTS];
   453 static int SwapInterval = 0;
   454 
   455 // !!! FIXME: need a mutex for the event queue.
   456 #define SDL12_MAXEVENTS 128
   457 typedef struct EventQueueType
   458 {
   459     SDL12_Event event12;
   460     struct EventQueueType *next;
   461 } EventQueueType;
   462 
   463 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
   464 static EventQueueType *EventQueueHead = NULL;
   465 static EventQueueType *EventQueueTail = NULL;
   466 static EventQueueType *EventQueueAvailable = NULL;
   467 
   468 
   469 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   470 #if defined(_WINDOWS)
   471     #define WIN32_LEAN_AND_MEAN 1
   472     #include <windows.h>
   473     #define SDL20_LIBNAME "SDL2.dll"
   474     static HANDLE Loaded_SDL20 = NULL;
   475     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   476     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   477     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   478 #elif defined(unix) || defined(__APPLE__)
   479     #include <dlfcn.h>
   480     #ifdef __APPLE__
   481     #define SDL20_LIBNAME "libSDL2.dylib"
   482     #else
   483     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   484     #endif
   485     static void *Loaded_SDL20 = NULL;
   486     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL)) != NULL)
   487     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   488     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   489 #else
   490     #error Please define your platform.
   491 #endif
   492 
   493 static void *
   494 LoadSDL20Symbol(const char *fn, int *okay)
   495 {
   496     void *retval = NULL;
   497     if (*okay)  /* only bother trying if we haven't previously failed. */
   498     {
   499         retval = LookupSDL20Sym(fn);
   500 if (!retval) { fprintf(stderr, "WARNING: LOAD FAILED: %s\n", fn); }
   501 //        if (retval == NULL)
   502 //            *okay = 0;
   503     }
   504     return retval;
   505 }
   506 
   507 static void
   508 UnloadSDL20(void)
   509 {
   510     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   511     #include "SDL20_syms.h"
   512     CloseSDL20Library();
   513 }
   514 
   515 static int
   516 LoadSDL20(void)
   517 {
   518     int okay = 1;
   519     if (!Loaded_SDL20)
   520     {
   521         okay = LoadSDL20Library();
   522         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   523         #include "SDL20_syms.h"
   524         if (!okay)
   525             UnloadSDL20();
   526     }
   527     return okay;
   528 }
   529 
   530 DECLSPEC const SDL_version * SDLCALL
   531 SDL_Linked_Version(void)
   532 {
   533     static const SDL_version version = { 1, 2, SDL12_COMPAT_VERSION };
   534     return &version;
   535 }
   536 
   537 DECLSPEC int SDLCALL
   538 SDL_sscanf(const char *text, const char *fmt, ...)
   539 {
   540     int retval;
   541     va_list ap;
   542     va_start(ap, fmt);
   543     retval = (int) SDL20_sscanf(text, fmt, ap);
   544     va_end(ap);
   545     return retval;
   546 }
   547 
   548 DECLSPEC int SDLCALL
   549 SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
   550 {
   551     int retval;
   552     va_list ap;
   553     va_start(ap, fmt);
   554     retval = (int) SDL20_vsnprintf(text, maxlen, fmt, ap);
   555     va_end(ap);
   556     return retval;
   557 }
   558 
   559 DECLSPEC SDL_bool SDLCALL
   560 SDL_HasMMXExt(void)
   561 {
   562     /* this isn't accurate, but SDL2 doesn't have this for some reason.
   563         MMXExt is available in all SSE1 machines, except early Athlon chips,
   564         so we'll just say it's available if they have SSE1. Oh well. */
   565     return SDL20_HasSSE();
   566 }
   567 
   568 DECLSPEC SDL_bool SDLCALL
   569 SDL_Has3DNowExt(void)
   570 {
   571     FIXME("check this");
   572     return SDL20_HasSSE();
   573 }
   574 
   575 DECLSPEC int SDLCALL SDL_JoystickOpened(int device_index)
   576 {
   577     FIXME("write me");
   578     return 0;
   579 }
   580 
   581 static int
   582 GetVideoDisplay()
   583 {
   584     FIXME("cache this value during SDL_Init() so it doesn't change.");
   585     const char *variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
   586     if ( !variable ) {
   587         variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
   588     }
   589     if ( variable ) {
   590         return SDL20_atoi(variable);
   591     } else {
   592         return 0;
   593     }
   594 }
   595 
   596 /* This sets up VideoModes and VideoModesCount. You end up with arrays by pixel
   597     format, each with a value that 1.2's SDL_ListModes() can return. */
   598 static int
   599 Init12VidModes(void)
   600 {
   601     const int total = SDL20_GetNumDisplayModes(VideoDisplayIndex);
   602     VideoModeList *vmode = NULL;
   603     int num_modes = 0;
   604     void *ptr = NULL;
   605     int i, j;
   606 
   607     SDL_assert(VideoModes == NULL);
   608     SDL_assert(VideoModesCount == 0);
   609 
   610     for (i = 0; i < total; ++i) {
   611         SDL_DisplayMode mode;
   612 
   613         if (SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode) == -1) {
   614             continue;
   615         } else if (!mode.w || !mode.h) {
   616             SDL_assert(0 && "Can this actually happen?");
   617             continue;
   618         }
   619 
   620         if (!vmode || (mode.format != vmode->format)) {  // SDL20_GetDisplayMode() sorts on bpp first. We know when to change arrays.
   621             if (VideoModesCount > 0) {
   622                 VideoModes[VideoModesCount-1].modes[num_modes] = NULL;
   623             }
   624             ptr = (VideoModeList *) SDL20_realloc(VideoModes, sizeof (VideoModeList) * (VideoModesCount+1));
   625             if (!ptr) {
   626                 return SDL20_OutOfMemory();
   627             }
   628             VideoModes = (VideoModeList *) ptr;
   629             vmode = &VideoModes[VideoModesCount];
   630             vmode->format = mode.format;
   631             vmode->modeslist = NULL;
   632             vmode->modes = NULL;
   633             VideoModesCount++;
   634             num_modes = 0;
   635         }
   636 
   637         /* make sure we don't have this one already (with a different refresh rate, etc). */
   638         for (j = 0; j < num_modes; j++) {
   639             if ((vmode->modeslist[j].w == mode.w) && (vmode->modeslist[j].h == mode.h)) {
   640                 break;
   641             }
   642         }
   643 
   644         if (j < num_modes) {
   645             continue;  /* already have this one. */
   646         }
   647 
   648         ptr = SDL20_realloc(vmode->modes, sizeof (SDL_Rect *) * (num_modes + 2));
   649         if (ptr == NULL) {
   650             return SDL20_OutOfMemory();
   651         }
   652         vmode->modes = (SDL_Rect **) ptr;
   653 
   654         ptr = SDL20_realloc(vmode->modeslist, sizeof (SDL_Rect) * (num_modes + 1));
   655         if (ptr == NULL) {
   656             return SDL20_OutOfMemory();
   657         }
   658         vmode->modeslist = (SDL_Rect *) ptr;
   659 
   660         vmode->modeslist[num_modes].x = 0;
   661         vmode->modeslist[num_modes].y = 0;
   662         vmode->modeslist[num_modes].w = mode.w;
   663         vmode->modeslist[num_modes].h = mode.h;
   664 
   665         vmode->modes[num_modes] = &vmode->modeslist[num_modes];
   666 
   667         num_modes++;
   668     }
   669 
   670     if (VideoModesCount > 0) {
   671         VideoModes[VideoModesCount-1].modes[num_modes] = NULL;
   672     }
   673 
   674     return 0;
   675 }
   676 
   677 static int
   678 Init12Video(void)
   679 {
   680     int i;
   681 
   682     for (i = 0; i < SDL12_MAXEVENTS-1; i++)
   683         EventQueuePool[i].next = &EventQueuePool[i+1];
   684     EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
   685 
   686     EventQueueHead = EventQueueTail = NULL;
   687     EventQueueAvailable = EventQueuePool;
   688 
   689     SDL_memset(EventStates, SDL_ENABLE, sizeof (EventStates)); /* on by default */
   690     EventStates[SDL12_SYSWMEVENT] = SDL_IGNORE;  /* off by default. */
   691 
   692     SDL20_SetEventFilter(EventFilter20to12, NULL);
   693 
   694     VideoDisplayIndex = GetVideoDisplay();
   695     SwapInterval = 0;
   696 
   697     if (Init12VidModes() == -1) {
   698         return -1;
   699     }
   700 
   701     return 0;
   702 }
   703 
   704 
   705 DECLSPEC int SDLCALL
   706 SDL_InitSubSystem(Uint32 sdl12flags)
   707 {
   708     FIXME("there is never a parachute in SDL2, should we catch segfaults ourselves?");
   709 
   710     FIXME("support event thread where it makes sense to do so?");
   711 
   712 	if ( (sdl12flags & SDL12_INIT_EVENTTHREAD) == SDL12_INIT_EVENTTHREAD ) {
   713 		return SDL20_SetError("OS doesn't support threaded events");
   714 	}
   715 
   716     Uint32 sdl20flags = 0;
   717     int rc;
   718 
   719     if (!LoadSDL20())
   720         return -1;
   721 
   722 #ifdef __MACOSX__
   723     extern void sdl12_compat_macos_init(void);
   724     sdl12_compat_macos_init();
   725 #endif
   726 
   727     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   728     SETFLAG(TIMER);
   729     SETFLAG(AUDIO);
   730     SETFLAG(VIDEO);
   731     SETFLAG(JOYSTICK);
   732     SETFLAG(NOPARACHUTE);
   733     #undef SETFLAG
   734 
   735     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   736     if (sdl12flags & SDL12_INIT_CDROM)
   737         CDRomInit = 1;
   738 
   739     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   740 
   741     rc = SDL20_Init(sdl20flags);
   742     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO)) {
   743         if (Init12Video() == -1) {
   744             FIXME("should we deinit other subsystems?");
   745             return -1;
   746         }
   747     }
   748 
   749     return rc;
   750 }
   751 
   752 DECLSPEC int SDLCALL
   753 SDL_Init(Uint32 sdl12flags)
   754 {
   755     FIXME("what was different in 1.2?");
   756     return SDL_InitSubSystem(sdl12flags);   /* there's no difference betwee Init and InitSubSystem in SDL2. */
   757 }
   758 
   759 
   760 static void
   761 InitFlags12To20(const Uint32 flags12, Uint32 *_flags20, Uint32 *_extraflags)
   762 {
   763     Uint32 flags20 = 0;
   764     Uint32 extraflags = 0;
   765 
   766     #define SETFLAG(flag) if (flags12 & SDL12_INIT_##flag) flags20 |= SDL_INIT_##flag
   767     SETFLAG(TIMER);
   768     SETFLAG(AUDIO);
   769     SETFLAG(VIDEO);
   770     SETFLAG(JOYSTICK);
   771     SETFLAG(NOPARACHUTE);
   772     #undef SETFLAG
   773 
   774     if ((flags12 & SDL12_INIT_CDROM) && (CDRomInit)) {
   775         extraflags |= SDL12_INIT_CDROM;
   776     }
   777 
   778     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   779 
   780     *_flags20 = flags20;
   781     *_extraflags = extraflags;
   782 }
   783 
   784 static Uint32
   785 InitFlags20to12(const Uint32 flags20)
   786 {
   787     Uint32 flags12 = 0;
   788 
   789     #define SETFLAG(flag) if (flags20 & SDL_INIT_##flag) flags12 |= SDL12_INIT_##flag
   790     SETFLAG(TIMER);
   791     SETFLAG(AUDIO);
   792     SETFLAG(VIDEO);
   793     SETFLAG(JOYSTICK);
   794     SETFLAG(NOPARACHUTE);
   795     #undef SETFLAG
   796 
   797     return flags12;
   798 }
   799 
   800 
   801 DECLSPEC Uint32 SDLCALL
   802 SDL_WasInit(Uint32 sdl12flags)
   803 {
   804     Uint32 sdl20flags, extraflags;
   805     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
   806 
   807     return InitFlags20to12(SDL20_WasInit(sdl20flags)) | extraflags;
   808 }
   809 
   810 static void
   811 Quit12Video(void)
   812 {
   813     int i;
   814 
   815     for (i = 0; i < VideoModesCount; i++) {
   816         SDL20_free(VideoModes[i].modeslist);
   817         SDL20_free(VideoModes[i].modes);
   818     }
   819     SDL20_free(VideoModes);
   820 
   821     SDL20_FreeFormat(VideoInfo12.vfmt);
   822     SDL20_zero(VideoInfo12);
   823 
   824     EventFilter12 = NULL;
   825     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   826     CurrentCursor12 = NULL;
   827     VideoModes = NULL;
   828     VideoModesCount = 0;
   829 }
   830 
   831 DECLSPEC void SDLCALL
   832 SDL_QuitSubSystem(Uint32 sdl12flags)
   833 {
   834     Uint32 sdl20flags, extraflags;
   835     InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
   836 
   837     if (extraflags & SDL12_INIT_CDROM) {
   838         CDRomInit = 0;
   839     }
   840 
   841     FIXME("reset a bunch of other global variables too.");
   842     if (sdl12flags & SDL12_INIT_VIDEO) {
   843         Quit12Video();
   844     }
   845 
   846     FIXME("do something about SDL12_INIT_EVENTTHREAD");
   847     SDL20_QuitSubSystem(sdl20flags);
   848 
   849     if ((SDL20_WasInit(0) == 0) && (!CDRomInit)) {
   850         SDL20_Quit();
   851         UnloadSDL20();
   852     }
   853 }
   854 
   855 DECLSPEC void SDLCALL
   856 SDL_Quit(void)
   857 {
   858     SDL_QuitSubSystem(SDL_WasInit(0) | SDL12_INIT_CDROM);
   859 }
   860 
   861 DECLSPEC void SDLCALL
   862 SDL_SetError(const char *fmt, ...)
   863 {
   864     char ch;
   865     char *str = NULL;
   866     size_t len = 0;
   867     va_list ap;
   868     va_start(ap, fmt);
   869     len = SDL20_vsnprintf(&ch, 1, fmt, ap);
   870     va_end(ap);
   871 
   872     str = (char *) SDL20_malloc(len + 1);
   873     if (!str)
   874         SDL20_OutOfMemory();
   875     else
   876     {
   877         va_start(ap, fmt);
   878         SDL20_vsnprintf(str, len + 1, fmt, ap);
   879         va_end(ap);
   880         SDL20_SetError("%s", str);
   881         SDL20_free(str);
   882     }
   883 }
   884 
   885 DECLSPEC const char * SDLCALL
   886 SDL_GetError(void)
   887 {
   888     if (SDL20_GetError == NULL)
   889     {
   890         static const char noload_errstr[] = "The SDL 2.0 library that the 1.2 compatibility layer needs isn't loaded";
   891         return noload_errstr;
   892     }
   893     return SDL20_GetError();
   894 }
   895 
   896 
   897 static const char *
   898 GetDriverName(const char *name, char *namebuf, int maxlen)
   899 {
   900     if (name) {
   901         if (namebuf) {
   902             SDL20_strlcpy(namebuf, name, maxlen);
   903             return namebuf;
   904         } else {
   905             return name;
   906         }
   907     }
   908     return NULL;
   909 }
   910 
   911 DECLSPEC const char * SDLCALL
   912 SDL_AudioDriverName(char *namebuf, int maxlen)
   913 {
   914     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   915 }
   916 
   917 DECLSPEC const char * SDLCALL
   918 SDL_VideoDriverName(char *namebuf, int maxlen)
   919 {
   920     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   921 }
   922 
   923 DECLSPEC int SDLCALL
   924 SDL_PollEvent(SDL12_Event *event12)
   925 {
   926     EventQueueType *next;
   927 
   928     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   929 
   930     if (EventQueueHead == NULL)
   931         return 0;  /* no events at the moment. */
   932 
   933     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   934     next = EventQueueHead->next;
   935     EventQueueHead->next = EventQueueAvailable;
   936     EventQueueAvailable = EventQueueHead;
   937     EventQueueHead = next;
   938     return 1;
   939 }
   940 
   941 DECLSPEC int SDLCALL
   942 SDL_PushEvent(SDL12_Event *event12)
   943 {
   944     EventQueueType *item = EventQueueAvailable;
   945     if (item == NULL)
   946         return -1;  /* no space available at the moment. */
   947 
   948     EventQueueAvailable = item->next;
   949     if (EventQueueTail)
   950         EventQueueTail->next = item;
   951     else
   952         EventQueueHead = EventQueueTail = item;
   953     item->next = NULL;
   954 
   955     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   956     return 0;
   957 }
   958 
   959 DECLSPEC int SDLCALL
   960 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   961 {
   962     if (action == SDL_ADDEVENT)
   963     {
   964         int i;
   965         for (i = 0; i < numevents; i++)
   966         {
   967             if (SDL_PushEvent(&events12[i]) == -1)
   968                 break;  /* out of space for more events. */
   969         }
   970         return i;
   971     }
   972     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   973     {
   974         const SDL_bool isGet = (action == SDL_GETEVENT);
   975         EventQueueType *prev = NULL;
   976         EventQueueType *item = EventQueueHead;
   977         EventQueueType *next = NULL;
   978         int chosen = 0;
   979         while (chosen < numevents)
   980         {
   981             EventQueueType *nextPrev = item;
   982             if (!item)
   983                 break;  /* no more events at the moment. */
   984 
   985             next = item->next;  /* copy, since we might overwrite item->next */
   986 
   987             if (mask & (1<<item->event12.type))
   988             {
   989                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   990                 if (isGet)  /* remove from list? */
   991                 {
   992                     if (prev != NULL)
   993                         prev->next = next;
   994                     if (item == EventQueueHead)
   995                         EventQueueHead = next;
   996                     if (item == EventQueueTail)
   997                         EventQueueTail = prev;
   998 
   999                     /* put it back in the free pool. */
  1000                     item->next = EventQueueAvailable;
  1001                     EventQueueAvailable = item;
  1002                     nextPrev = prev;  /* previous item doesn't change. */
  1003                 }
  1004             }
  1005 
  1006             item = next;
  1007             prev = nextPrev;
  1008         }
  1009         return chosen;
  1010     }
  1011 
  1012     return 0;
  1013 }
  1014 
  1015 DECLSPEC int SDLCALL
  1016 SDL_WaitEvent(SDL12_Event *event12)
  1017 {
  1018     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1019     while (!SDL_PollEvent(event12))
  1020         SDL20_Delay(10);
  1021     return 1;
  1022 }
  1023 
  1024 static SDL_bool
  1025 PushEventIfNotFiltered(SDL12_Event *event12)
  1026 {
  1027     if (event12->type != SDL12_NOEVENT)
  1028     {
  1029         if (EventStates[event12->type] != SDL_IGNORE)
  1030         {
  1031             if ((!EventFilter12) || (EventFilter12(event12)))
  1032                 return (SDL_PushEvent(event12) == 0);
  1033         }
  1034     }
  1035     return SDL_FALSE;
  1036 }
  1037 
  1038 DECLSPEC Uint8 SDLCALL
  1039 SDL_EventState(Uint8 type, int state)
  1040 {
  1041     /* the values of "state" match between 1.2 and 2.0 */
  1042     const Uint8 retval = EventStates[type];
  1043     SDL12_Event e;
  1044 
  1045     if (state != SDL_QUERY)
  1046         EventStates[type] = state;
  1047     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1048         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1049 
  1050     return retval;
  1051 }
  1052 
  1053 DECLSPEC Uint8 SDLCALL
  1054 SDL_GetMouseState(int *x, int *y)
  1055 {
  1056     const Uint32 state20 = SDL20_GetMouseState(x, y);
  1057     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1058 
  1059     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1060     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  1061         retval |= (1<<5);
  1062     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  1063         retval |= (1<<6);
  1064 
  1065     return retval;
  1066 }
  1067 
  1068 static int
  1069 EventFilter20to12(void *data, SDL_Event *event20)
  1070 {
  1071     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1072     SDL12_Event event12;
  1073     int x, y;
  1074 
  1075     SDL_assert(data == NULL);  /* currently unused. */
  1076 
  1077     SDL20_zero(event12);
  1078 
  1079     switch (event20->type)
  1080     {
  1081         case SDL_QUIT:
  1082             event12.type = SDL12_QUIT;
  1083             break;
  1084 
  1085         case SDL_WINDOWEVENT:
  1086             switch (event20->window.event)
  1087             {
  1088                 case SDL_WINDOWEVENT_CLOSE:
  1089                     event12.type = SDL12_QUIT;
  1090                     break;
  1091 
  1092                 case SDL_WINDOWEVENT_SHOWN:
  1093                 case SDL_WINDOWEVENT_EXPOSED:
  1094                     event12.type = SDL12_VIDEOEXPOSE;
  1095                     break;
  1096 
  1097                 case SDL_WINDOWEVENT_RESIZED:
  1098                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1099                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1100                     event12.type = SDL12_VIDEORESIZE;
  1101                     event12.resize.w = event20->window.data1;
  1102                     event12.resize.h = event20->window.data2;
  1103                     break;
  1104 
  1105                 case SDL_WINDOWEVENT_MINIMIZED:
  1106                     event12.type = SDL12_ACTIVEEVENT;
  1107                     event12.active.gain = 0;
  1108                     event12.active.state = SDL12_APPACTIVE;
  1109                     break;
  1110 
  1111                 case SDL_WINDOWEVENT_RESTORED:
  1112                     event12.type = SDL12_ACTIVEEVENT;
  1113                     event12.active.gain = 1;
  1114                     event12.active.state = SDL12_APPACTIVE;
  1115                     break;
  1116 
  1117                 case SDL_WINDOWEVENT_ENTER:
  1118                     event12.type = SDL12_ACTIVEEVENT;
  1119                     event12.active.gain = 1;
  1120                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1121                     break;
  1122 
  1123                 case SDL_WINDOWEVENT_LEAVE:
  1124                     event12.type = SDL12_ACTIVEEVENT;
  1125                     event12.active.gain = 0;
  1126                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1127                     break;
  1128 
  1129                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1130                     event12.type = SDL12_ACTIVEEVENT;
  1131                     event12.active.gain = 1;
  1132                     event12.active.state = SDL12_APPINPUTFOCUS;
  1133                     break;
  1134 
  1135                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1136                     event12.type = SDL12_ACTIVEEVENT;
  1137                     event12.active.gain = 0;
  1138                     event12.active.state = SDL12_APPINPUTFOCUS;
  1139                     break;
  1140             }
  1141             break;
  1142 
  1143         // !!! FIXME: this is sort of a mess to convert.
  1144         //case SDL_SYSWMEVENT:
  1145 
  1146         case SDL_KEYDOWN: FIXME("write me"); return 0;
  1147         case SDL_KEYUP: FIXME("write me"); return 0;
  1148 
  1149         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  1150         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  1151 
  1152         case SDL_MOUSEMOTION:
  1153         	event12.type = SDL12_MOUSEMOTION;
  1154             event12.motion.which = (Uint8) event20->motion.which;
  1155             event12.motion.state = event20->motion.state;
  1156             event12.motion.x = (Uint16) event20->motion.x;
  1157             event12.motion.y = (Uint16) event20->motion.y;
  1158             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1159             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1160             break;
  1161 
  1162         case SDL_MOUSEBUTTONDOWN:
  1163         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1164             event12.button.which = (Uint8) event20->button.which;
  1165             event12.button.button = event20->button.button;
  1166             event12.button.state = event20->button.state;
  1167             event12.button.x = (Uint16) event20->button.x;
  1168             event12.button.y = (Uint16) event20->button.y;
  1169             break;
  1170 
  1171         case SDL_MOUSEBUTTONUP:
  1172         	event12.type = SDL12_MOUSEBUTTONUP;
  1173             event12.button.which = (Uint8) event20->button.which;
  1174             event12.button.button = event20->button.button;
  1175             event12.button.state = event20->button.state;
  1176             event12.button.x = (Uint16) event20->button.x;
  1177             event12.button.y = (Uint16) event20->button.y;
  1178             break;
  1179 
  1180         case SDL_MOUSEWHEEL:
  1181             if (event20->wheel.y == 0)
  1182                 break;  /* don't support horizontal wheels in 1.2. */
  1183 
  1184             event12.type = SDL12_MOUSEBUTTONDOWN;
  1185             event12.button.which = (Uint8) event20->wheel.which;
  1186             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1187             event12.button.state = SDL_GetMouseState(&x, &y);
  1188             event12.button.x = (Uint16) x;
  1189             event12.button.y = (Uint16) y;
  1190             PushEventIfNotFiltered(&event12);
  1191 
  1192             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1193             break;
  1194 
  1195         case SDL_JOYAXISMOTION:
  1196             event12.type = SDL12_JOYAXISMOTION;
  1197             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1198             event12.jaxis.axis = event20->jaxis.axis;
  1199             event12.jaxis.value = event20->jaxis.value;
  1200             break;
  1201 
  1202         case SDL_JOYBALLMOTION:
  1203             event12.type = SDL12_JOYBALLMOTION;
  1204             event12.jball.which = (Uint8) event20->jball.which;
  1205             event12.jball.ball = event20->jball.ball;
  1206             event12.jball.xrel = event20->jball.xrel;
  1207             event12.jball.yrel = event20->jball.yrel;
  1208             break;
  1209 
  1210         case SDL_JOYHATMOTION:
  1211             event12.type = SDL12_JOYHATMOTION;
  1212             event12.jhat.which = (Uint8) event20->jhat.which;
  1213             event12.jhat.hat = event20->jhat.hat;
  1214             event12.jhat.value = event20->jhat.value;
  1215             break;
  1216 
  1217         case SDL_JOYBUTTONDOWN:
  1218             event12.type = SDL12_JOYBUTTONDOWN;
  1219             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1220             event12.jbutton.button = event20->jbutton.button;
  1221             event12.jbutton.state = event20->jbutton.state;
  1222             break;
  1223 
  1224         case SDL_JOYBUTTONUP:
  1225             event12.type = SDL12_JOYBUTTONUP;
  1226             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1227             event12.jbutton.button = event20->jbutton.button;
  1228             event12.jbutton.state = event20->jbutton.state;
  1229             break;
  1230 
  1231         //case SDL_JOYDEVICEADDED:
  1232         //case SDL_JOYDEVICEREMOVED:
  1233 	    //case SDL_CONTROLLERAXISMOTION:
  1234 	    //case SDL_CONTROLLERBUTTONDOWN:
  1235 	    //case SDL_CONTROLLERBUTTONUP:
  1236 	    //case SDL_CONTROLLERDEVICEADDED:
  1237 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1238 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1239         //case SDL_FINGERDOWN:
  1240         //case SDL_FINGERUP:
  1241         //case SDL_FINGERMOTION:
  1242         //case SDL_DOLLARGESTURE:
  1243         //case SDL_DOLLARRECORD:
  1244         //case SDL_MULTIGESTURE:
  1245         //case SDL_CLIPBOARDUPDATE:
  1246         //case SDL_DROPFILE:
  1247 
  1248         default:
  1249             return 0;  /* drop everything else. */
  1250     }
  1251 
  1252     PushEventIfNotFiltered(&event12);
  1253 
  1254     return 0;  /* always drop it from the 2.0 event queue. */
  1255 }
  1256 
  1257 DECLSPEC void SDLCALL
  1258 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1259 {
  1260     /* We always have a filter installed, but will call the app's too. */
  1261     EventFilter12 = filter12;
  1262 }
  1263 
  1264 DECLSPEC SDL12_EventFilter SDLCALL
  1265 SDL_GetEventFilter(void)
  1266 {
  1267     return EventFilter12;
  1268 }
  1269 
  1270 
  1271 static SDL12_Surface *
  1272 Surface20to12(SDL_Surface *surface20)
  1273 {
  1274     SDL12_Surface *surface12 = NULL;
  1275     SDL12_Palette *palette12 = NULL;
  1276     SDL12_PixelFormat *format12 = NULL;
  1277     Uint32 flags = 0;
  1278 
  1279     if (!surface20)
  1280         return NULL;
  1281 
  1282     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1283     if (!surface12)
  1284         goto failed;
  1285 
  1286     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1287     if (!palette12)
  1288         goto failed;
  1289 
  1290     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1291     if (!format12)
  1292         goto failed;
  1293 
  1294     SDL20_zerop(palette12);
  1295     palette12->ncolors = surface20->format->palette->ncolors;
  1296     palette12->colors = surface20->format->palette->colors;
  1297 
  1298     SDL20_zerop(format12);
  1299     format12->palette = palette12;
  1300     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1301     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1302     format12->Rloss = surface20->format->Rloss;
  1303     format12->Gloss = surface20->format->Gloss;
  1304     format12->Bloss = surface20->format->Bloss;
  1305     format12->Aloss = surface20->format->Aloss;
  1306     format12->Rshift = surface20->format->Rshift;
  1307     format12->Gshift = surface20->format->Gshift;
  1308     format12->Bshift = surface20->format->Bshift;
  1309     format12->Ashift = surface20->format->Ashift;
  1310     format12->Rmask = surface20->format->Rmask;
  1311     format12->Gmask = surface20->format->Gmask;
  1312     format12->Bmask = surface20->format->Bmask;
  1313     format12->Amask = surface20->format->Amask;
  1314     FIXME("format12->colorkey");
  1315     FIXME("format12->alpha");
  1316 
  1317     SDL20_zerop(surface12);
  1318     flags = surface20->flags;
  1319     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1320     MAPSURFACEFLAGS(PREALLOC);
  1321     MAPSURFACEFLAGS(RLEACCEL);
  1322     /*MAPSURFACEFLAGS(DONTFREE);*/
  1323     #undef MAPSURFACEFLAGS
  1324     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1325 
  1326     surface12->format = format12;
  1327     surface12->w = surface20->w;
  1328     surface12->h = surface20->h;
  1329     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  1330     surface12->pixels = surface20->pixels;
  1331     surface12->offset = 0;
  1332     surface12->surface20 = surface20;
  1333     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
  1334     surface12->refcount = surface20->refcount;
  1335 
  1336     return surface12;
  1337 
  1338 failed:
  1339     SDL20_free(surface12);
  1340     SDL20_free(palette12);
  1341     SDL20_free(format12);
  1342     return NULL;
  1343 }
  1344 
  1345 DECLSPEC SDL12_Surface * SDLCALL
  1346 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1347 {
  1348     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1349     SDL12_Surface *surface12 = Surface20to12(surface20);
  1350     if (!surface12) {
  1351         SDL20_FreeSurface(surface20);
  1352         return NULL;
  1353     }
  1354 
  1355     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1356     return surface12;
  1357 }
  1358 
  1359 DECLSPEC SDL12_Surface * SDLCALL
  1360 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1361 {
  1362     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1363     SDL12_Surface *surface12 = Surface20to12(surface20);
  1364     if (!surface12) {
  1365         SDL20_FreeSurface(surface20);
  1366         return NULL;
  1367     }
  1368 
  1369     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1370     return surface12;
  1371 }
  1372 
  1373 DECLSPEC void SDLCALL
  1374 SDL_FreeSurface(SDL12_Surface *surface12)
  1375 {
  1376     if (surface12) {
  1377         SDL20_FreeSurface(surface12->surface20);
  1378         if (surface12->format) {
  1379             SDL20_free(surface12->format->palette);
  1380             SDL20_free(surface12->format);
  1381         }
  1382         SDL20_free(surface12);
  1383     }
  1384 }
  1385 
  1386 DECLSPEC void SDLCALL
  1387 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1388 {
  1389     if (surface12 && rect)
  1390 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1391 }
  1392 
  1393 DECLSPEC SDL_bool SDLCALL
  1394 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1395 {
  1396     SDL_bool retval = SDL_FALSE;
  1397     if (surface12)
  1398     {
  1399         retval = SDL20_SetClipRect(surface12->surface20, rect);
  1400         SDL20_GetClipRect(surface12->surface20, &surface12->clip_rect);
  1401     }
  1402     return retval;
  1403 }
  1404 
  1405 DECLSPEC int SDLCALL
  1406 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1407 {
  1408     const SDL_Rect orig_dstrect = *dstrect;
  1409     const int retval = SDL20_FillRect(dst->surface20, &orig_dstrect, color);
  1410     if (retval != -1)
  1411     {
  1412         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1413             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1414     }
  1415     return retval;
  1416 }
  1417 
  1418 
  1419 static SDL_PixelFormat *
  1420 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1421 {
  1422     palette20->ncolors = format12->palette->ncolors;
  1423     palette20->colors = format12->palette->colors;
  1424     palette20->version = 1;
  1425     palette20->refcount = 1;
  1426     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1427     format20->palette = palette20;
  1428     format20->BitsPerPixel = format12->BitsPerPixel;
  1429     format20->BytesPerPixel = format12->BytesPerPixel;
  1430     format20->Rmask = format12->Rmask;
  1431     format20->Gmask = format12->Gmask;
  1432     format20->Bmask = format12->Bmask;
  1433     format20->Amask = format12->Amask;
  1434     format20->Rloss = format12->Rloss;
  1435     format20->Gloss = format12->Gloss;
  1436     format20->Bloss = format12->Bloss;
  1437     format20->Aloss = format12->Aloss;
  1438     format20->Rshift = format12->Rshift;
  1439     format20->Gshift = format12->Gshift;
  1440     format20->Bshift = format12->Bshift;
  1441     format20->Ashift = format12->Ashift;
  1442     format20->refcount = 1;
  1443     format20->next = NULL;
  1444     return format20;
  1445 }
  1446 
  1447 DECLSPEC Uint32 SDLCALL
  1448 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1449 {
  1450     /* This is probably way slower than apps expect. */
  1451     SDL_PixelFormat format20;
  1452     SDL_Palette palette20;
  1453     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1454 }
  1455 
  1456 DECLSPEC Uint32 SDLCALL
  1457 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1458 {
  1459     /* This is probably way slower than apps expect. */
  1460     SDL_PixelFormat format20;
  1461     SDL_Palette palette20;
  1462     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1463 }
  1464 
  1465 DECLSPEC void SDLCALL
  1466 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1467 {
  1468     /* This is probably way slower than apps expect. */
  1469     SDL_PixelFormat format20;
  1470     SDL_Palette palette20;
  1471     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1472 }
  1473 
  1474 DECLSPEC void SDLCALL
  1475 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1476 {
  1477     /* This is probably way slower than apps expect. */
  1478     SDL_PixelFormat format20;
  1479     SDL_Palette palette20;
  1480     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1481 }
  1482 
  1483 DECLSPEC const SDL12_VideoInfo * SDLCALL
  1484 SDL_GetVideoInfo(void)
  1485 {
  1486     SDL_DisplayMode mode;
  1487 
  1488     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  1489 
  1490     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1491         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  1492         VideoInfo12.current_w = mode.w;
  1493         VideoInfo12.current_h = mode.h;
  1494         FIXME("vidinfo details commented out");
  1495         //VideoInfo12.wm_available = 1;
  1496         //VideoInfo12.video_mem = 1024 * 256;
  1497     }
  1498     return &VideoInfo12;
  1499 }
  1500 
  1501 DECLSPEC int SDLCALL
  1502 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1503 {
  1504     int i, nummodes, actual_bpp = 0;
  1505 
  1506     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1507         return 0;
  1508     }
  1509 
  1510     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1511         SDL_DisplayMode mode;
  1512         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1513         return SDL_BITSPERPIXEL(mode.format);
  1514     }
  1515 
  1516     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1517     for (i = 0; i < nummodes; ++i) {
  1518         SDL_DisplayMode mode;
  1519         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1520         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1521             if (!mode.format) {
  1522                 return bpp;
  1523             }
  1524             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1525                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1526             }
  1527         }
  1528     }
  1529     return actual_bpp;
  1530 }
  1531 
  1532 DECLSPEC SDL_Rect ** SDLCALL
  1533 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  1534 {
  1535     Uint32 fmt;
  1536     int i;
  1537 
  1538     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1539         return NULL;
  1540     }
  1541 
  1542     if ((!format12) && (!VideoInfo12.vfmt)) {
  1543         SDL20_SetError("No pixel format specified");
  1544         return NULL;
  1545     }
  1546 
  1547     if (!(flags & SDL12_FULLSCREEN)) {
  1548         return (SDL_Rect **) (-1);  /* any resolution is fine. */
  1549     }
  1550 
  1551     if (format12) {
  1552         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1553     } else {
  1554         fmt = VideoInfo12.vfmt->format;
  1555     }
  1556 
  1557     for (i = 0; i < VideoModesCount; i++) {
  1558         VideoModeList *modes = &VideoModes[i];
  1559         if (modes->format == fmt) {
  1560             return modes->modes;
  1561         }
  1562     }
  1563 
  1564     SDL20_SetError("No modes support requested pixel format");
  1565     return NULL;
  1566 }
  1567 
  1568 DECLSPEC void SDLCALL
  1569 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1570 {
  1571     if (cursor12) {
  1572         if (cursor12->wm_cursor)
  1573             SDL20_FreeCursor(cursor12->wm_cursor);
  1574         SDL20_free(cursor12->data);
  1575         SDL20_free(cursor12->mask);
  1576         SDL20_free(cursor12);
  1577     }
  1578 }
  1579 
  1580 DECLSPEC SDL12_Cursor * SDLCALL
  1581 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1582 {
  1583     const size_t datasize = h * (w / 8);
  1584     SDL_Cursor *cursor20 = NULL;
  1585     SDL12_Cursor *retval = NULL;
  1586 
  1587     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1588     if (!retval)
  1589         goto outofmem;
  1590 
  1591     SDL20_zerop(retval);
  1592 
  1593     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1594     if (!retval->data)
  1595         goto outofmem;
  1596 
  1597     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1598     if (!retval->mask)
  1599         goto outofmem;
  1600 
  1601     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1602     if (!cursor20)
  1603         goto failed;
  1604 
  1605     retval->area.w = w;
  1606     retval->area.h = h;
  1607     retval->hot_x = hot_x;
  1608     retval->hot_y = hot_y;
  1609     retval->wm_cursor = cursor20;
  1610     /* we always leave retval->save as null pointers. */
  1611 
  1612     SDL20_memcpy(retval->data, data, datasize);
  1613     SDL20_memcpy(retval->mask, mask, datasize);
  1614 
  1615     return retval;
  1616 
  1617 outofmem:
  1618     SDL20_OutOfMemory();
  1619 
  1620 failed:
  1621     SDL_FreeCursor(retval);
  1622     return NULL;
  1623 }
  1624 
  1625 DECLSPEC void SDLCALL
  1626 SDL_SetCursor(SDL12_Cursor *cursor)
  1627 {
  1628     CurrentCursor12 = cursor;
  1629     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1630 }
  1631 
  1632 DECLSPEC SDL12_Cursor * SDLCALL
  1633 SDL_GetCursor(void)
  1634 {
  1635     return CurrentCursor12;
  1636 }
  1637 
  1638 static void
  1639 GetEnvironmentWindowPosition(int *x, int *y)
  1640 {
  1641     int display = VideoDisplayIndex;
  1642     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  1643     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  1644     if (window) {
  1645         if (SDL20_strcmp(window, "center") == 0) {
  1646             center = window;
  1647         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  1648             return;
  1649         }
  1650     }
  1651 
  1652     if (center) {
  1653         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1654         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1655     }
  1656 }
  1657 
  1658 static void
  1659 SetupScreenSaver(const int flags12)
  1660 {
  1661     const char *env;
  1662     SDL_bool allow_screensaver;
  1663 
  1664     /* Allow environment override of screensaver disable */
  1665     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1666     if (env) {
  1667         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1668     } else if (flags12 & SDL12_FULLSCREEN) {
  1669         allow_screensaver = SDL_FALSE;
  1670     } else {
  1671         allow_screensaver = SDL_TRUE;
  1672     }
  1673     if (allow_screensaver) {
  1674         SDL20_EnableScreenSaver();
  1675     } else {
  1676         SDL20_DisableScreenSaver();
  1677     }
  1678 }
  1679 
  1680 
  1681 static SDL12_Surface *
  1682 EndVidModeCreate(void)
  1683 {
  1684     if (VideoTexture20) {
  1685         SDL20_DestroyTexture(VideoTexture20);
  1686         VideoTexture20 = NULL;
  1687     }
  1688     if (VideoRenderer20) {
  1689         SDL20_DestroyRenderer(VideoRenderer20);
  1690         VideoRenderer20 = NULL;
  1691     }
  1692     if (VideoGLContext20) {
  1693         SDL20_GL_MakeCurrent(NULL, NULL);
  1694         SDL20_GL_DeleteContext(VideoGLContext20);
  1695         VideoGLContext20 = NULL;
  1696     }
  1697     if (VideoWindow20) {
  1698         SDL20_DestroyWindow(VideoWindow20);
  1699         VideoWindow20 = NULL;
  1700     }
  1701     if (VideoSurface12) {
  1702         SDL20_free(VideoSurface12->pixels);
  1703         VideoSurface12->pixels = NULL;
  1704         SDL_FreeSurface(VideoSurface12);
  1705         VideoSurface12 = NULL;
  1706     }
  1707     if (VideoConvertSurface20) {
  1708         SDL20_FreeSurface(VideoConvertSurface20);
  1709         VideoConvertSurface20 = NULL;
  1710     }
  1711     return NULL;
  1712 }
  1713 
  1714 
  1715 static SDL12_Surface *
  1716 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  1717 {
  1718     Uint32 rmask, gmask, bmask, amask;
  1719     int bpp;
  1720     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  1721         return NULL;
  1722     }
  1723     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  1724 }
  1725 
  1726 static SDL_Surface *
  1727 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  1728 {
  1729     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  1730     if (surface20) {
  1731         surface20->flags |= SDL_PREALLOC;
  1732         surface20->pixels = NULL;
  1733         surface20->w = width;
  1734         surface20->h = height;
  1735         surface20->pitch = 0;
  1736         SDL20_SetClipRect(surface20, NULL);
  1737     }
  1738     return surface20;
  1739 }
  1740 
  1741 
  1742 DECLSPEC SDL12_Surface * SDLCALL
  1743 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1744 {
  1745     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  1746     SDL_DisplayMode dmode;
  1747     Uint32 fullscreen_flags20 = 0;
  1748     Uint32 appfmt;
  1749 
  1750     /* SDL_SetVideoMode() implicitly inits if necessary. */
  1751     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  1752         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  1753             return NULL;
  1754         }
  1755     }
  1756 
  1757     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  1758         FIXME("No OPENGLBLIT support at the moment");
  1759         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  1760         return NULL;
  1761     }
  1762 
  1763     FIXME("handle SDL_ANYFORMAT");
  1764 
  1765     if ((width < 0) || (height < 0)) {
  1766         SDL20_SetError("Invalid width or height");
  1767         return NULL;
  1768     }
  1769 
  1770     FIXME("There's an environment variable to choose a display");
  1771     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  1772         return NULL;
  1773     }
  1774 
  1775     if (width == 0) {
  1776         width = dmode.w;
  1777     }
  1778 
  1779     if (height == 0) {
  1780         height = dmode.h;
  1781     }
  1782 
  1783     if (bpp == 0) {
  1784         bpp = SDL_BITSPERPIXEL(dmode.format);
  1785     }
  1786 
  1787     switch (bpp) {
  1788         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  1789         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  1790         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  1791         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  1792         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  1793     }
  1794 
  1795     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  1796 
  1797     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  1798     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  1799 
  1800     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  1801         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  1802     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  1803         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  1804     } else if (VideoGLContext20) {
  1805         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  1806         SDL20_GL_MakeCurrent(NULL, NULL);
  1807         SDL20_GL_DeleteContext(VideoGLContext20);
  1808         VideoGLContext20 = NULL;
  1809     }
  1810 
  1811     if (flags12 & SDL12_FULLSCREEN) {
  1812         // OpenGL tries to force the real resolution requested, but for
  1813         //  software rendering, we're just going to push it off onto the
  1814         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  1815         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  1816         if (flags12 & SDL12_OPENGL) {
  1817             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  1818         } else {
  1819             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  1820         }
  1821     }
  1822 
  1823     if (!VideoWindow20) {  /* create it */
  1824         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  1825         Uint32 flags20 = fullscreen_flags20;
  1826         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  1827         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  1828         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  1829 
  1830         /* most platforms didn't check these environment variables, but the major
  1831            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  1832         GetEnvironmentWindowPosition(&x, &y);
  1833 
  1834         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  1835         if (!VideoWindow20) {
  1836             return EndVidModeCreate();
  1837         }
  1838     } else {  /* resize it */
  1839         SDL20_SetWindowSize(VideoWindow20, width, height);
  1840         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  1841         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  1842         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  1843     }
  1844 
  1845     if (VideoSurface12) {
  1846         SDL20_free(VideoSurface12->pixels);
  1847     } else {
  1848         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  1849         if (!VideoSurface12) {
  1850             return EndVidModeCreate();
  1851         }
  1852     }
  1853 
  1854     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  1855     VideoSurface12->flags |= SDL12_PREALLOC;
  1856     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  1857     VideoSurface12->w = VideoSurface12->surface20->w = width;
  1858     VideoSurface12->h = VideoSurface12->surface20->h = height;
  1859     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  1860     SDL_SetClipRect(VideoSurface12, NULL);
  1861 
  1862     if (flags12 & SDL12_OPENGL) {
  1863         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  1864         SDL_assert(!VideoRenderer20);
  1865         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  1866         if (!VideoGLContext20) {
  1867             return EndVidModeCreate();
  1868         }
  1869 
  1870         VideoSurface12->flags |= SDL12_OPENGL;
  1871     } else {
  1872         /* always use a renderer for non-OpenGL windows. */
  1873         SDL_RendererInfo rinfo;
  1874         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  1875         if (!VideoRenderer20) {
  1876             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  1877             if (!VideoRenderer20) {
  1878                 return EndVidModeCreate();
  1879             }
  1880         }
  1881 
  1882         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  1883         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  1884         SDL20_RenderClear(VideoRenderer20);
  1885         SDL20_RenderPresent(VideoRenderer20);
  1886         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  1887 
  1888         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  1889             return EndVidModeCreate();
  1890         }
  1891 
  1892         if (VideoTexture20) {
  1893             SDL20_DestroyTexture(VideoTexture20);
  1894         }
  1895 
  1896         if (VideoConvertSurface20) {
  1897             SDL20_FreeSurface(VideoConvertSurface20);
  1898             VideoConvertSurface20 = NULL;
  1899         }
  1900 
  1901         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  1902         if (!VideoTexture20) {
  1903             return EndVidModeCreate();
  1904         }
  1905 
  1906         if (rinfo.texture_formats[0] != appfmt) {
  1907             /* need to convert between app's format and texture format */
  1908             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  1909             if (!VideoConvertSurface20) {
  1910                 return EndVidModeCreate();
  1911             }
  1912         }
  1913 
  1914         VideoSurface12->flags &= ~SDL12_OPENGL;
  1915         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  1916         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  1917         if (!VideoSurface12->pixels) {
  1918             SDL20_OutOfMemory();
  1919             return EndVidModeCreate();
  1920         }
  1921     }
  1922 
  1923     FIXME("setup screen saver");
  1924 
  1925     return VideoSurface12;
  1926 }
  1927 
  1928 DECLSPEC SDL12_Surface * SDLCALL
  1929 SDL_GetVideoSurface(void)
  1930 {
  1931     return VideoSurface12;
  1932 }
  1933 
  1934 DECLSPEC int SDLCALL
  1935 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  1936 {
  1937     FIXME("write me");
  1938     return SDL20_Unsupported();
  1939 }
  1940 
  1941 DECLSPEC SDL12_Surface * SDLCALL
  1942 SDL_DisplayFormat(SDL12_Surface *surface12)
  1943 {
  1944     FIXME("write me");
  1945     SDL20_Unsupported();
  1946     return NULL;
  1947 }
  1948 
  1949 DECLSPEC SDL12_Surface * SDLCALL
  1950 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1951 {
  1952     FIXME("write me");
  1953     SDL20_Unsupported();
  1954     return NULL;
  1955 }
  1956 
  1957 DECLSPEC void SDLCALL
  1958 SDL_UpdateRects(SDL12_Surface * screen12, int numrects, SDL_Rect * rects)
  1959 {
  1960     FIXME("write me");
  1961     SDL20_Unsupported();
  1962 }
  1963 
  1964 DECLSPEC void SDLCALL
  1965 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1966 {
  1967     if (screen12) {
  1968         SDL_Rect rect;
  1969         rect.x = (int) x;
  1970         rect.y = (int) y;
  1971         rect.w = (int) (w ? w : screen12->w);
  1972         rect.h = (int) (h ? h : screen12->h);
  1973         SDL_UpdateRects(screen12, 1, &rect);
  1974     }
  1975 }
  1976 
  1977 DECLSPEC int SDLCALL
  1978 SDL_Flip(SDL12_Surface *screen12)
  1979 {
  1980     SDL_UpdateRect(screen12, 0, 0, 0, 0);
  1981     return 0;
  1982 }
  1983 
  1984 DECLSPEC void SDLCALL
  1985 SDL_WM_SetCaption(const char *title, const char *icon)
  1986 {
  1987     if (WindowTitle) {
  1988         SDL20_free(WindowTitle);
  1989     }
  1990     if (WindowIconTitle) {
  1991         SDL20_free(WindowIconTitle);
  1992     }
  1993     WindowTitle = title ? SDL_strdup(title) : NULL;
  1994     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  1995     if (VideoWindow20) {
  1996         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  1997     }
  1998 }
  1999 
  2000 DECLSPEC void SDLCALL
  2001 SDL_WM_GetCaption(const char **title, const char **icon)
  2002 {
  2003     if (title) {
  2004         *title = WindowTitle;
  2005     }
  2006     if (icon) {
  2007         *icon = WindowIconTitle;
  2008     }
  2009 }
  2010 
  2011 DECLSPEC void SDLCALL
  2012 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2013 {
  2014     FIXME("write me");
  2015     SDL20_Unsupported();
  2016 }
  2017 
  2018 DECLSPEC int SDLCALL
  2019 SDL_WM_IconifyWindow(void)
  2020 {
  2021     SDL20_MinimizeWindow(VideoWindow20);
  2022     return 0;
  2023 }
  2024 
  2025 DECLSPEC int SDLCALL
  2026 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  2027 {
  2028     FIXME("write me");
  2029     return SDL20_Unsupported();
  2030 }
  2031 
  2032 typedef enum
  2033 {
  2034     SDL12_GRAB_QUERY = -1,
  2035     SDL12_GRAB_OFF = 0,
  2036     SDL12_GRAB_ON = 1
  2037 } SDL12_GrabMode;
  2038 
  2039 DECLSPEC SDL12_GrabMode SDLCALL
  2040 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2041 {
  2042     if (mode != SDL12_GRAB_QUERY) {
  2043         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2044     }
  2045     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2046 }
  2047 
  2048 DECLSPEC void SDLCALL
  2049 SDL_WarpMouse(Uint16 x, Uint16 y)
  2050 {
  2051     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2052 }
  2053 
  2054 DECLSPEC Uint8 SDLCALL
  2055 SDL_GetAppState(void)
  2056 {
  2057     Uint8 state12 = 0;
  2058     Uint32 flags20 = 0;
  2059 
  2060     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2061     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2062         state12 |= SDL12_APPACTIVE;
  2063     }
  2064     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2065         state12 |= SDL12_APPINPUTFOCUS;
  2066     }
  2067     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2068         state12 |= SDL12_APPMOUSEFOCUS;
  2069     }
  2070     return state12;
  2071 }
  2072 
  2073 DECLSPEC int SDLCALL
  2074 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2075                int firstcolor, int ncolors)
  2076 {
  2077     FIXME("write me");
  2078     return SDL20_Unsupported();
  2079 }
  2080 
  2081 DECLSPEC int SDLCALL
  2082 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2083               int ncolors)
  2084 {
  2085     FIXME("write me");
  2086     return SDL20_Unsupported();
  2087 }
  2088 
  2089 DECLSPEC int SDLCALL
  2090 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2091 {
  2092     FIXME("write me");
  2093     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  2094     return SDL20_Unsupported();
  2095 }
  2096 
  2097 DECLSPEC SDL12_Overlay * SDLCALL
  2098 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2099 {
  2100     FIXME("write me");
  2101     SDL20_Unsupported();
  2102     return NULL;
  2103 }
  2104 
  2105 DECLSPEC int SDLCALL
  2106 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  2107 {
  2108     FIXME("write me");
  2109     return SDL20_Unsupported();
  2110 }
  2111 
  2112 DECLSPEC void SDLCALL
  2113 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  2114 {
  2115     FIXME("write me");
  2116 }
  2117 
  2118 DECLSPEC int SDLCALL
  2119 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL_Rect * dstrect)
  2120 {
  2121     FIXME("write me");
  2122     return SDL20_Unsupported();
  2123 }
  2124 
  2125 DECLSPEC void SDLCALL
  2126 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  2127 {
  2128     FIXME("write me");
  2129 }
  2130 
  2131 DECLSPEC int SDLCALL
  2132 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2133 {
  2134     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2135         return SDL20_SetError("Unknown GL attribute");
  2136 
  2137     /* swap control was moved out of this API, everything else lines up. */
  2138     if (attr == SDL12_GL_SWAP_CONTROL)
  2139     {
  2140         SwapInterval = value;
  2141         FIXME("Actually set swap interval somewhere");
  2142         return 0;
  2143     }
  2144 
  2145     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2146 }
  2147 
  2148 DECLSPEC int SDLCALL
  2149 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2150 {
  2151     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2152         return SDL20_SetError("Unknown GL attribute");
  2153 
  2154     /* swap control was moved out of this API, everything else lines up. */
  2155     if (attr == SDL12_GL_SWAP_CONTROL)
  2156     {
  2157         *value = SDL20_GL_GetSwapInterval();
  2158         return 0;
  2159     }
  2160 
  2161     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2162 }
  2163 
  2164 
  2165 DECLSPEC void SDLCALL
  2166 SDL_GL_SwapBuffers(void)
  2167 {
  2168     if (VideoWindow20)
  2169         SDL20_GL_SwapWindow(VideoWindow20);
  2170 }
  2171 
  2172 DECLSPEC int SDLCALL
  2173 SDL_SetGamma(float red, float green, float blue)
  2174 {
  2175     Uint16 red_ramp[256];
  2176     Uint16 green_ramp[256];
  2177     Uint16 blue_ramp[256];
  2178 
  2179     SDL20_CalculateGammaRamp(red, red_ramp);
  2180     if (green == red) {
  2181         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2182     } else {
  2183         SDL20_CalculateGammaRamp(green, green_ramp);
  2184     }
  2185     if (blue == red) {
  2186         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2187     } else if (blue == green) {
  2188         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2189     } else {
  2190         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2191     }
  2192     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2193 }
  2194 
  2195 DECLSPEC int SDLCALL
  2196 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2197 {
  2198     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2199 }
  2200 
  2201 DECLSPEC int SDLCALL
  2202 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2203 {
  2204     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2205 }
  2206 
  2207 DECLSPEC int SDLCALL
  2208 SDL_EnableKeyRepeat(int delay, int interval)
  2209 {
  2210     return 0;
  2211 }
  2212 
  2213 DECLSPEC void SDLCALL
  2214 SDL_GetKeyRepeat(int *delay, int *interval)
  2215 {
  2216     if (delay) {
  2217         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2218     }
  2219     if (interval) {
  2220         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2221     }
  2222 }
  2223 
  2224 DECLSPEC int SDLCALL
  2225 SDL_EnableUNICODE(int enable)
  2226 {
  2227     FIXME("write me");
  2228     return SDL20_Unsupported();
  2229 }
  2230 
  2231 static Uint32
  2232 SetTimerOld_Callback(Uint32 interval, void* param)
  2233 {
  2234     return ((SDL12_TimerCallback)param)(interval);
  2235 }
  2236 
  2237 DECLSPEC int SDLCALL
  2238 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2239 {
  2240     static SDL_TimerID compat_timer;
  2241 
  2242     if (compat_timer) {
  2243         SDL20_RemoveTimer(compat_timer);
  2244         compat_timer = 0;
  2245     }
  2246 
  2247     if (interval && callback) {
  2248         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2249         if (!compat_timer) {
  2250             return -1;
  2251         }
  2252     }
  2253     return 0;
  2254 }
  2255 
  2256 DECLSPEC int SDLCALL
  2257 SDL_putenv(const char *_var)
  2258 {
  2259     char *ptr = NULL;
  2260     char *var = SDL20_strdup(_var);
  2261     if (var == NULL) {
  2262         return -1;  /* we don't set errno. */
  2263     }
  2264 
  2265     ptr = SDL20_strchr(var, '=');
  2266     if (ptr == NULL) {
  2267         SDL20_free(var);
  2268         return -1;
  2269     }
  2270 
  2271     *ptr = '\0';  /* split the string into name and value. */
  2272     SDL20_setenv(var, ptr + 1, 1);
  2273     SDL20_free(var);
  2274     return 0;
  2275 }
  2276 
  2277 
  2278 
  2279 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2280 
  2281 typedef void *SDL12_CD;  /* close enough.  :) */
  2282 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2283 
  2284 DECLSPEC int SDLCALL
  2285 SDL_CDNumDrives(void)
  2286 {
  2287     FIXME("should return -1 without SDL_INIT_CDROM");
  2288     return 0;
  2289 }
  2290 
  2291 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2292 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2293 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2294 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2295 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2296 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2297 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2298 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2299 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2300 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  2301 
  2302 
  2303 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2304 DECLSPEC SDL_Thread * SDLCALL
  2305 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2306 {
  2307     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2308 }
  2309 #else
  2310 DECLSPEC SDL_Thread * SDLCALL
  2311 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2312 {
  2313     return SDL20_CreateThread(fn, NULL, data);
  2314 }
  2315 #endif
  2316 
  2317 DECLSPEC int SDLCALL
  2318 SDL_mutexP(SDL_mutex *mutex)
  2319 {
  2320     return SDL20_LockMutex(mutex);
  2321 }
  2322 
  2323 DECLSPEC int SDLCALL
  2324 SDL_mutexV(SDL_mutex *mutex)
  2325 {
  2326     return SDL20_UnlockMutex(mutex);
  2327 }
  2328 
  2329 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
  2330 {
  2331     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  2332     fprintf(stderr,
  2333         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  2334         "This program should be fixed. No thread was actually harmed.\n");
  2335 }
  2336 
  2337 /* This changed from an opaque pointer to an int in 2.0. */
  2338 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2339 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2340 
  2341 
  2342 DECLSPEC SDL12_TimerID SDLCALL
  2343 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2344 {
  2345     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2346 }
  2347 
  2348 DECLSPEC SDL_bool SDLCALL
  2349 SDL_RemoveTimer(SDL12_TimerID id)
  2350 {
  2351     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2352 }
  2353 
  2354 
  2355 typedef struct SDL12_RWops {
  2356     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2357     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2358     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2359     int (SDLCALL *close)(struct SDL12_RWops *context);
  2360     Uint32 type;
  2361     void *padding[8];
  2362     SDL_RWops *rwops20;
  2363 } SDL12_RWops;
  2364 
  2365 
  2366 DECLSPEC SDL12_RWops * SDLCALL
  2367 SDL_AllocRW(void)
  2368 {
  2369     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2370     if (!rwops)
  2371         SDL20_OutOfMemory();
  2372     return rwops;
  2373 }
  2374 
  2375 DECLSPEC void SDLCALL
  2376 SDL_FreeRW(SDL12_RWops *rwops12)
  2377 {
  2378     SDL20_free(rwops12);
  2379 }
  2380 
  2381 static int SDLCALL
  2382 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2383 {
  2384     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2385 }
  2386 
  2387 static int SDLCALL
  2388 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2389 {
  2390     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2391 }
  2392 
  2393 static int SDLCALL
  2394 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2395 {
  2396     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2397 }
  2398 
  2399 static int SDLCALL
  2400 RWops20to12_close(struct SDL12_RWops *rwops12)
  2401 {
  2402     int rc = 0;
  2403     if (rwops12)
  2404     {
  2405         rc = rwops12->rwops20->close(rwops12->rwops20);
  2406         if (rc == 0)
  2407             SDL_FreeRW(rwops12);
  2408     }
  2409     return rc;
  2410 }
  2411 
  2412 static SDL12_RWops *
  2413 RWops20to12(SDL_RWops *rwops20)
  2414 {
  2415     SDL12_RWops *rwops12;
  2416 
  2417     if (!rwops20)
  2418         return NULL;
  2419 
  2420     rwops12 = SDL_AllocRW();
  2421     if (!rwops12)
  2422         return NULL;
  2423 
  2424     SDL20_zerop(rwops12);
  2425     rwops12->type = rwops20->type;
  2426     rwops12->rwops20 = rwops20;
  2427     rwops12->seek = RWops20to12_seek;
  2428     rwops12->read = RWops20to12_read;
  2429     rwops12->write = RWops20to12_write;
  2430     rwops12->close = RWops20to12_close;
  2431 
  2432     return rwops12;
  2433 }
  2434 
  2435 DECLSPEC SDL12_RWops * SDLCALL
  2436 SDL_RWFromFile(const char *file, const char *mode)
  2437 {
  2438     return RWops20to12(SDL20_RWFromFile(file, mode));
  2439 }
  2440 
  2441 DECLSPEC SDL12_RWops * SDLCALL
  2442 SDL_RWFromFP(FILE *io, int autoclose)
  2443 {
  2444     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  2445 }
  2446 
  2447 DECLSPEC SDL12_RWops * SDLCALL
  2448 SDL_RWFromMem(void *mem, int size)
  2449 {
  2450     return RWops20to12(SDL20_RWFromMem(mem, size));
  2451 }
  2452 
  2453 DECLSPEC SDL12_RWops * SDLCALL
  2454 SDL_RWFromConstMem(const void *mem, int size)
  2455 {
  2456     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  2457 }
  2458 
  2459 #define READ_AND_BYTESWAP(endian, bits) \
  2460     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2461         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2462         return SDL_Swap##endian##bits(val); \
  2463     }
  2464 
  2465 READ_AND_BYTESWAP(LE,16)
  2466 READ_AND_BYTESWAP(BE,16)
  2467 READ_AND_BYTESWAP(LE,32)
  2468 READ_AND_BYTESWAP(BE,32)
  2469 READ_AND_BYTESWAP(LE,64)
  2470 READ_AND_BYTESWAP(BE,64)
  2471 #undef READ_AND_BYTESWAP
  2472 
  2473 #define BYTESWAP_AND_WRITE(endian, bits) \
  2474     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  2475         val = SDL_Swap##endian##bits(val); \
  2476         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2477     }
  2478 BYTESWAP_AND_WRITE(LE,16)
  2479 BYTESWAP_AND_WRITE(BE,16)
  2480 BYTESWAP_AND_WRITE(LE,32)
  2481 BYTESWAP_AND_WRITE(BE,32)
  2482 BYTESWAP_AND_WRITE(LE,64)
  2483 BYTESWAP_AND_WRITE(BE,64)
  2484 #undef BYTESWAP_AND_WRITE
  2485 
  2486 
  2487 static Sint64 SDLCALL
  2488 RWops12to20_size(struct SDL_RWops *rwops20)
  2489 {
  2490     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2491     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  2492     int pos;
  2493 
  2494     if (size != -1)
  2495         return size;
  2496 
  2497     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2498     if (pos == -1)
  2499         return -1;
  2500 
  2501     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  2502     if (size == -1)
  2503         return -1;
  2504 
  2505     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  2506     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  2507     return size;
  2508 }
  2509 
  2510 static Sint64 SDLCALL
  2511 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  2512 {
  2513     FIXME("fail if (offset) is too big");
  2514     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2515     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  2516 }
  2517 
  2518 static size_t SDLCALL
  2519 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  2520 {
  2521     FIXME("fail if (size) or (maxnum) is too big");
  2522     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2523     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  2524 }
  2525 
  2526 static size_t SDLCALL
  2527 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  2528 {
  2529     FIXME("fail if (size) or (maxnum) is too big");
  2530     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2531     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  2532 }
  2533 
  2534 static int SDLCALL
  2535 RWops12to20_close(struct SDL_RWops *rwops20)
  2536 {
  2537     int rc = 0;
  2538     if (rwops20)
  2539     {
  2540         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2541         rc = rwops12->close(rwops12);
  2542         if (rc == 0)
  2543             SDL20_FreeRW(rwops20);
  2544     }
  2545     return rc;
  2546 }
  2547 
  2548 static SDL_RWops *
  2549 RWops12to20(SDL12_RWops *rwops12)
  2550 {
  2551     SDL_RWops *rwops20;
  2552 
  2553     if (!rwops12)
  2554         return NULL;
  2555 
  2556     rwops20 = SDL20_AllocRW();
  2557     if (!rwops20)
  2558         return NULL;
  2559 
  2560     SDL20_zerop(rwops20);
  2561     rwops20->type = rwops12->type;
  2562     rwops20->hidden.unknown.data1 = rwops12;
  2563     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  2564     rwops20->size = RWops12to20_size;
  2565     rwops20->seek = RWops12to20_seek;
  2566     rwops20->read = RWops12to20_read;
  2567     rwops20->write = RWops12to20_write;
  2568     rwops20->close = RWops12to20_close;
  2569     return rwops20;
  2570 }
  2571 
  2572 DECLSPEC SDL12_Surface * SDLCALL
  2573 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  2574 {
  2575     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2576     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  2577     SDL12_Surface *surface12 = Surface20to12(surface20);
  2578     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2579         SDL20_FreeRW(rwops20);
  2580     if ((!surface12) && (surface20))
  2581         SDL20_FreeSurface(surface20);
  2582     return surface12;
  2583 }
  2584 
  2585 DECLSPEC int SDLCALL
  2586 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  2587 {
  2588     FIXME("wrap surface");
  2589     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2590     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  2591     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2592         SDL20_FreeRW(rwops20);
  2593     return retval;
  2594 }
  2595 
  2596 DECLSPEC SDL_AudioSpec * SDLCALL
  2597 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  2598                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  2599 {
  2600     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2601     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  2602     FIXME("deal with non-1.2 formats, like float32");
  2603     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2604         SDL20_FreeRW(rwops20);
  2605     return retval;
  2606 }
  2607 
  2608 /* vi: set ts=4 sw=4 expandtab: */