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