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