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