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