src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 19 Feb 2019 16:41:05 -0500
changeset 74 4e3e77f78520
parent 73 040f36454e95
child 75 00631178b6d5
permissions -rw-r--r--
Implemented SDL_SetColorKey.

Now testsprite renders perfectly!
     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     return 1;
   949 }
   950 
   951 DECLSPEC int SDLCALL
   952 SDL_PushEvent(SDL12_Event *event12)
   953 {
   954     EventQueueType *item = EventQueueAvailable;
   955     if (item == NULL)
   956         return -1;  /* no space available at the moment. */
   957 
   958     EventQueueAvailable = item->next;
   959     if (EventQueueTail)
   960         EventQueueTail->next = item;
   961     else
   962         EventQueueHead = EventQueueTail = item;
   963     item->next = NULL;
   964 
   965     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   966     return 0;
   967 }
   968 
   969 DECLSPEC int SDLCALL
   970 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   971 {
   972     if (action == SDL_ADDEVENT)
   973     {
   974         int i;
   975         for (i = 0; i < numevents; i++)
   976         {
   977             if (SDL_PushEvent(&events12[i]) == -1)
   978                 break;  /* out of space for more events. */
   979         }
   980         return i;
   981     }
   982     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   983     {
   984         const SDL_bool isGet = (action == SDL_GETEVENT);
   985         EventQueueType *prev = NULL;
   986         EventQueueType *item = EventQueueHead;
   987         EventQueueType *next = NULL;
   988         int chosen = 0;
   989         while (chosen < numevents)
   990         {
   991             EventQueueType *nextPrev = item;
   992             if (!item)
   993                 break;  /* no more events at the moment. */
   994 
   995             next = item->next;  /* copy, since we might overwrite item->next */
   996 
   997             if (mask & (1<<item->event12.type))
   998             {
   999                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
  1000                 if (isGet)  /* remove from list? */
  1001                 {
  1002                     if (prev != NULL)
  1003                         prev->next = next;
  1004                     if (item == EventQueueHead)
  1005                         EventQueueHead = next;
  1006                     if (item == EventQueueTail)
  1007                         EventQueueTail = prev;
  1008 
  1009                     /* put it back in the free pool. */
  1010                     item->next = EventQueueAvailable;
  1011                     EventQueueAvailable = item;
  1012                     nextPrev = prev;  /* previous item doesn't change. */
  1013                 }
  1014             }
  1015 
  1016             item = next;
  1017             prev = nextPrev;
  1018         }
  1019         return chosen;
  1020     }
  1021 
  1022     return 0;
  1023 }
  1024 
  1025 DECLSPEC int SDLCALL
  1026 SDL_WaitEvent(SDL12_Event *event12)
  1027 {
  1028     FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
  1029     while (!SDL_PollEvent(event12))
  1030         SDL20_Delay(10);
  1031     return 1;
  1032 }
  1033 
  1034 static SDL_bool
  1035 PushEventIfNotFiltered(SDL12_Event *event12)
  1036 {
  1037     if (event12->type != SDL12_NOEVENT)
  1038     {
  1039         if (EventStates[event12->type] != SDL_IGNORE)
  1040         {
  1041             if ((!EventFilter12) || (EventFilter12(event12)))
  1042                 return (SDL_PushEvent(event12) == 0);
  1043         }
  1044     }
  1045     return SDL_FALSE;
  1046 }
  1047 
  1048 DECLSPEC Uint8 SDLCALL
  1049 SDL_EventState(Uint8 type, int state)
  1050 {
  1051     /* the values of "state" match between 1.2 and 2.0 */
  1052     const Uint8 retval = EventStates[type];
  1053     SDL12_Event e;
  1054 
  1055     if (state != SDL_QUERY)
  1056         EventStates[type] = state;
  1057     if (state == SDL_IGNORE)  /* drop existing events of this type. */
  1058         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
  1059 
  1060     return retval;
  1061 }
  1062 
  1063 DECLSPEC Uint8 SDLCALL
  1064 SDL_GetMouseState(int *x, int *y)
  1065 {
  1066     const Uint32 state20 = SDL20_GetMouseState(x, y);
  1067     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  1068 
  1069     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  1070     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  1071         retval |= (1<<5);
  1072     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  1073         retval |= (1<<6);
  1074 
  1075     return retval;
  1076 }
  1077 
  1078 static int
  1079 EventFilter20to12(void *data, SDL_Event *event20)
  1080 {
  1081     //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
  1082     SDL12_Event event12;
  1083     int x, y;
  1084 
  1085     SDL_assert(data == NULL);  /* currently unused. */
  1086 
  1087     SDL20_zero(event12);
  1088 
  1089     switch (event20->type)
  1090     {
  1091         case SDL_QUIT:
  1092             event12.type = SDL12_QUIT;
  1093             break;
  1094 
  1095         case SDL_WINDOWEVENT:
  1096             switch (event20->window.event)
  1097             {
  1098                 case SDL_WINDOWEVENT_CLOSE:
  1099                     event12.type = SDL12_QUIT;
  1100                     break;
  1101 
  1102                 case SDL_WINDOWEVENT_SHOWN:
  1103                 case SDL_WINDOWEVENT_EXPOSED:
  1104                     event12.type = SDL12_VIDEOEXPOSE;
  1105                     break;
  1106 
  1107                 case SDL_WINDOWEVENT_RESIZED:
  1108                 case SDL_WINDOWEVENT_SIZE_CHANGED:
  1109                     FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
  1110                     event12.type = SDL12_VIDEORESIZE;
  1111                     event12.resize.w = event20->window.data1;
  1112                     event12.resize.h = event20->window.data2;
  1113                     break;
  1114 
  1115                 case SDL_WINDOWEVENT_MINIMIZED:
  1116                     event12.type = SDL12_ACTIVEEVENT;
  1117                     event12.active.gain = 0;
  1118                     event12.active.state = SDL12_APPACTIVE;
  1119                     break;
  1120 
  1121                 case SDL_WINDOWEVENT_RESTORED:
  1122                     event12.type = SDL12_ACTIVEEVENT;
  1123                     event12.active.gain = 1;
  1124                     event12.active.state = SDL12_APPACTIVE;
  1125                     break;
  1126 
  1127                 case SDL_WINDOWEVENT_ENTER:
  1128                     event12.type = SDL12_ACTIVEEVENT;
  1129                     event12.active.gain = 1;
  1130                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1131                     break;
  1132 
  1133                 case SDL_WINDOWEVENT_LEAVE:
  1134                     event12.type = SDL12_ACTIVEEVENT;
  1135                     event12.active.gain = 0;
  1136                     event12.active.state = SDL12_APPMOUSEFOCUS;
  1137                     break;
  1138 
  1139                 case SDL_WINDOWEVENT_FOCUS_GAINED:
  1140                     event12.type = SDL12_ACTIVEEVENT;
  1141                     event12.active.gain = 1;
  1142                     event12.active.state = SDL12_APPINPUTFOCUS;
  1143                     break;
  1144 
  1145                 case SDL_WINDOWEVENT_FOCUS_LOST:
  1146                     event12.type = SDL12_ACTIVEEVENT;
  1147                     event12.active.gain = 0;
  1148                     event12.active.state = SDL12_APPINPUTFOCUS;
  1149                     break;
  1150             }
  1151             break;
  1152 
  1153         // !!! FIXME: this is sort of a mess to convert.
  1154         //case SDL_SYSWMEVENT:
  1155 
  1156         case SDL_KEYDOWN: FIXME("write me"); return 0;
  1157         case SDL_KEYUP: FIXME("write me"); return 0;
  1158 
  1159         case SDL_TEXTEDITING: FIXME("write me"); return 0;
  1160         case SDL_TEXTINPUT: FIXME("write me"); return 0;
  1161 
  1162         case SDL_MOUSEMOTION:
  1163         	event12.type = SDL12_MOUSEMOTION;
  1164             event12.motion.which = (Uint8) event20->motion.which;
  1165             event12.motion.state = event20->motion.state;
  1166             event12.motion.x = (Uint16) event20->motion.x;
  1167             event12.motion.y = (Uint16) event20->motion.y;
  1168             event12.motion.xrel = (Sint16) event20->motion.xrel;
  1169             event12.motion.yrel = (Sint16) event20->motion.yrel;
  1170             break;
  1171 
  1172         case SDL_MOUSEBUTTONDOWN:
  1173         	event12.type = SDL12_MOUSEBUTTONDOWN;
  1174             event12.button.which = (Uint8) event20->button.which;
  1175             event12.button.button = event20->button.button;
  1176             event12.button.state = event20->button.state;
  1177             event12.button.x = (Uint16) event20->button.x;
  1178             event12.button.y = (Uint16) event20->button.y;
  1179             break;
  1180 
  1181         case SDL_MOUSEBUTTONUP:
  1182         	event12.type = SDL12_MOUSEBUTTONUP;
  1183             event12.button.which = (Uint8) event20->button.which;
  1184             event12.button.button = event20->button.button;
  1185             event12.button.state = event20->button.state;
  1186             event12.button.x = (Uint16) event20->button.x;
  1187             event12.button.y = (Uint16) event20->button.y;
  1188             break;
  1189 
  1190         case SDL_MOUSEWHEEL:
  1191             if (event20->wheel.y == 0)
  1192                 break;  /* don't support horizontal wheels in 1.2. */
  1193 
  1194             event12.type = SDL12_MOUSEBUTTONDOWN;
  1195             event12.button.which = (Uint8) event20->wheel.which;
  1196             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
  1197             event12.button.state = SDL_GetMouseState(&x, &y);
  1198             event12.button.x = (Uint16) x;
  1199             event12.button.y = (Uint16) y;
  1200             PushEventIfNotFiltered(&event12);
  1201 
  1202             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
  1203             break;
  1204 
  1205         case SDL_JOYAXISMOTION:
  1206             event12.type = SDL12_JOYAXISMOTION;
  1207             event12.jaxis.which = (Uint8) event20->jaxis.which;
  1208             event12.jaxis.axis = event20->jaxis.axis;
  1209             event12.jaxis.value = event20->jaxis.value;
  1210             break;
  1211 
  1212         case SDL_JOYBALLMOTION:
  1213             event12.type = SDL12_JOYBALLMOTION;
  1214             event12.jball.which = (Uint8) event20->jball.which;
  1215             event12.jball.ball = event20->jball.ball;
  1216             event12.jball.xrel = event20->jball.xrel;
  1217             event12.jball.yrel = event20->jball.yrel;
  1218             break;
  1219 
  1220         case SDL_JOYHATMOTION:
  1221             event12.type = SDL12_JOYHATMOTION;
  1222             event12.jhat.which = (Uint8) event20->jhat.which;
  1223             event12.jhat.hat = event20->jhat.hat;
  1224             event12.jhat.value = event20->jhat.value;
  1225             break;
  1226 
  1227         case SDL_JOYBUTTONDOWN:
  1228             event12.type = SDL12_JOYBUTTONDOWN;
  1229             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1230             event12.jbutton.button = event20->jbutton.button;
  1231             event12.jbutton.state = event20->jbutton.state;
  1232             break;
  1233 
  1234         case SDL_JOYBUTTONUP:
  1235             event12.type = SDL12_JOYBUTTONUP;
  1236             event12.jbutton.which = (Uint8) event20->jbutton.which;
  1237             event12.jbutton.button = event20->jbutton.button;
  1238             event12.jbutton.state = event20->jbutton.state;
  1239             break;
  1240 
  1241         //case SDL_JOYDEVICEADDED:
  1242         //case SDL_JOYDEVICEREMOVED:
  1243 	    //case SDL_CONTROLLERAXISMOTION:
  1244 	    //case SDL_CONTROLLERBUTTONDOWN:
  1245 	    //case SDL_CONTROLLERBUTTONUP:
  1246 	    //case SDL_CONTROLLERDEVICEADDED:
  1247 	    //case SDL_CONTROLLERDEVICEREMOVED:
  1248 	    //case SDL_CONTROLLERDEVICEREMAPPED:
  1249         //case SDL_FINGERDOWN:
  1250         //case SDL_FINGERUP:
  1251         //case SDL_FINGERMOTION:
  1252         //case SDL_DOLLARGESTURE:
  1253         //case SDL_DOLLARRECORD:
  1254         //case SDL_MULTIGESTURE:
  1255         //case SDL_CLIPBOARDUPDATE:
  1256         //case SDL_DROPFILE:
  1257 
  1258         default:
  1259             return 0;  /* drop everything else. */
  1260     }
  1261 
  1262     PushEventIfNotFiltered(&event12);
  1263 
  1264     return 0;  /* always drop it from the 2.0 event queue. */
  1265 }
  1266 
  1267 DECLSPEC void SDLCALL
  1268 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1269 {
  1270     /* We always have a filter installed, but will call the app's too. */
  1271     EventFilter12 = filter12;
  1272 }
  1273 
  1274 DECLSPEC SDL12_EventFilter SDLCALL
  1275 SDL_GetEventFilter(void)
  1276 {
  1277     return EventFilter12;
  1278 }
  1279 
  1280 
  1281 static SDL12_Rect *
  1282 Rect20to12(const SDL_Rect *rect20, SDL12_Rect *rect12)
  1283 {
  1284     rect12->x = (Sint16) rect20->x;
  1285     rect12->y = (Sint16) rect20->y;
  1286     rect12->w = (Uint16) rect20->w;
  1287     rect12->h = (Uint16) rect20->h;
  1288     return rect12;
  1289 }
  1290 
  1291 static SDL_Rect *
  1292 Rect12to20(const SDL12_Rect *rect12, SDL_Rect *rect20)
  1293 {
  1294     rect20->x = (int) rect12->x;
  1295     rect20->y = (int) rect12->y;
  1296     rect20->w = (int) rect12->w;
  1297     rect20->h = (int) rect12->h;
  1298     return rect20;
  1299 }
  1300 
  1301 static SDL12_Surface *
  1302 Surface20to12(SDL_Surface *surface20)
  1303 {
  1304     SDL12_Surface *surface12 = NULL;
  1305     SDL12_Palette *palette12 = NULL;
  1306     SDL12_PixelFormat *format12 = NULL;
  1307     Uint32 flags = 0;
  1308 
  1309     if (!surface20)
  1310         return NULL;
  1311 
  1312     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1313     if (!surface12)
  1314         goto failed;
  1315 
  1316     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1317     if (!palette12)
  1318         goto failed;
  1319 
  1320     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1321     if (!format12)
  1322         goto failed;
  1323 
  1324     SDL20_zerop(palette12);
  1325     palette12->ncolors = surface20->format->palette->ncolors;
  1326     palette12->colors = surface20->format->palette->colors;
  1327 
  1328     SDL20_zerop(format12);
  1329     format12->palette = palette12;
  1330     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1331     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1332     format12->Rloss = surface20->format->Rloss;
  1333     format12->Gloss = surface20->format->Gloss;
  1334     format12->Bloss = surface20->format->Bloss;
  1335     format12->Aloss = surface20->format->Aloss;
  1336     format12->Rshift = surface20->format->Rshift;
  1337     format12->Gshift = surface20->format->Gshift;
  1338     format12->Bshift = surface20->format->Bshift;
  1339     format12->Ashift = surface20->format->Ashift;
  1340     format12->Rmask = surface20->format->Rmask;
  1341     format12->Gmask = surface20->format->Gmask;
  1342     format12->Bmask = surface20->format->Bmask;
  1343     format12->Amask = surface20->format->Amask;
  1344     FIXME("format12->colorkey");
  1345     FIXME("format12->alpha");
  1346 
  1347     SDL20_zerop(surface12);
  1348     flags = surface20->flags;
  1349     #ifdef SDL_SIMD_ALIGNED
  1350     flags &= ~SDL_SIMD_ALIGNED;  /* we don't need to map this to 1.2 */
  1351     #endif
  1352     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1353     MAPSURFACEFLAGS(PREALLOC);
  1354     MAPSURFACEFLAGS(RLEACCEL);
  1355     /*MAPSURFACEFLAGS(DONTFREE);*/
  1356     #undef MAPSURFACEFLAGS
  1357     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1358 
  1359     surface12->format = format12;
  1360     surface12->w = surface20->w;
  1361     surface12->h = surface20->h;
  1362     surface12->pitch = (Uint16) surface20->pitch;  FIXME("make sure this fits in a Uint16");
  1363     surface12->pixels = surface20->pixels;
  1364     surface12->offset = 0;
  1365     surface12->surface20 = surface20;
  1366     Rect20to12(&surface20->clip_rect, &surface12->clip_rect);
  1367     surface12->refcount = surface20->refcount;
  1368 
  1369     return surface12;
  1370 
  1371 failed:
  1372     SDL20_free(surface12);
  1373     SDL20_free(palette12);
  1374     SDL20_free(format12);
  1375     return NULL;
  1376 }
  1377 
  1378 DECLSPEC SDL12_Surface * SDLCALL
  1379 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1380 {
  1381     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1382     SDL12_Surface *surface12 = Surface20to12(surface20);
  1383     if (!surface12) {
  1384         SDL20_FreeSurface(surface20);
  1385         return NULL;
  1386     }
  1387 
  1388     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1389     return surface12;
  1390 }
  1391 
  1392 DECLSPEC SDL12_Surface * SDLCALL
  1393 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1394 {
  1395     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1396     SDL12_Surface *surface12 = Surface20to12(surface20);
  1397     if (!surface12) {
  1398         SDL20_FreeSurface(surface20);
  1399         return NULL;
  1400     }
  1401 
  1402     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1403     return surface12;
  1404 }
  1405 
  1406 DECLSPEC void SDLCALL
  1407 SDL_FreeSurface(SDL12_Surface *surface12)
  1408 {
  1409     if (surface12) {
  1410         SDL20_FreeSurface(surface12->surface20);
  1411         if (surface12->format) {
  1412             SDL20_free(surface12->format->palette);
  1413             SDL20_free(surface12->format);
  1414         }
  1415         SDL20_free(surface12);
  1416     }
  1417 }
  1418 
  1419 DECLSPEC void SDLCALL
  1420 SDL_GetClipRect(SDL12_Surface *surface12, SDL12_Rect *rect)
  1421 {
  1422     if (surface12 && rect) {
  1423         SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL12_Rect));
  1424     }
  1425 }
  1426 
  1427 DECLSPEC SDL_bool SDLCALL
  1428 SDL_SetClipRect(SDL12_Surface *surface12, const SDL12_Rect *rect12)
  1429 {
  1430     SDL_bool retval = SDL_FALSE;
  1431     if (surface12)
  1432     {
  1433         SDL_Rect rect20;
  1434         retval = SDL20_SetClipRect(surface12->surface20, rect12 ? Rect12to20(rect12, &rect20) : NULL);
  1435         SDL20_GetClipRect(surface12->surface20, &rect20);
  1436         Rect20to12(&rect20, &surface12->clip_rect);
  1437     }
  1438     return retval;
  1439 }
  1440 
  1441 DECLSPEC int SDLCALL
  1442 SDL_FillRect(SDL12_Surface *dst, SDL12_Rect *dstrect12, Uint32 color)
  1443 {
  1444     SDL_Rect dstrect20;
  1445     const int retval = SDL20_FillRect(dst->surface20, dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL, color);
  1446     if (retval != -1)
  1447     {
  1448         if (dstrect12) {  /* 1.2 stores the clip intersection in dstrect */
  1449             SDL_Rect intersected20;
  1450             SDL20_IntersectRect(&dstrect20, &dst->surface20->clip_rect, &intersected20);
  1451             Rect20to12(&intersected20, dstrect12);
  1452         }
  1453     }
  1454     return retval;
  1455 }
  1456 
  1457 
  1458 static SDL_PixelFormat *
  1459 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1460 {
  1461     palette20->ncolors = format12->palette->ncolors;
  1462     palette20->colors = format12->palette->colors;
  1463     palette20->version = 1;
  1464     palette20->refcount = 1;
  1465     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1466     format20->palette = palette20;
  1467     format20->BitsPerPixel = format12->BitsPerPixel;
  1468     format20->BytesPerPixel = format12->BytesPerPixel;
  1469     format20->Rmask = format12->Rmask;
  1470     format20->Gmask = format12->Gmask;
  1471     format20->Bmask = format12->Bmask;
  1472     format20->Amask = format12->Amask;
  1473     format20->Rloss = format12->Rloss;
  1474     format20->Gloss = format12->Gloss;
  1475     format20->Bloss = format12->Bloss;
  1476     format20->Aloss = format12->Aloss;
  1477     format20->Rshift = format12->Rshift;
  1478     format20->Gshift = format12->Gshift;
  1479     format20->Bshift = format12->Bshift;
  1480     format20->Ashift = format12->Ashift;
  1481     format20->refcount = 1;
  1482     format20->next = NULL;
  1483     return format20;
  1484 }
  1485 
  1486 DECLSPEC Uint32 SDLCALL
  1487 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1488 {
  1489     /* This is probably way slower than apps expect. */
  1490     SDL_PixelFormat format20;
  1491     SDL_Palette palette20;
  1492     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1493 }
  1494 
  1495 DECLSPEC Uint32 SDLCALL
  1496 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1497 {
  1498     /* This is probably way slower than apps expect. */
  1499     SDL_PixelFormat format20;
  1500     SDL_Palette palette20;
  1501     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1502 }
  1503 
  1504 DECLSPEC void SDLCALL
  1505 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1506 {
  1507     /* This is probably way slower than apps expect. */
  1508     SDL_PixelFormat format20;
  1509     SDL_Palette palette20;
  1510     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1511 }
  1512 
  1513 DECLSPEC void SDLCALL
  1514 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1515 {
  1516     /* This is probably way slower than apps expect. */
  1517     SDL_PixelFormat format20;
  1518     SDL_Palette palette20;
  1519     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1520 }
  1521 
  1522 DECLSPEC const SDL12_VideoInfo * SDLCALL
  1523 SDL_GetVideoInfo(void)
  1524 {
  1525     SDL_DisplayMode mode;
  1526 
  1527     FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
  1528 
  1529     if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1530         VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
  1531         VideoInfo12.current_w = mode.w;
  1532         VideoInfo12.current_h = mode.h;
  1533         FIXME("vidinfo details commented out");
  1534         //VideoInfo12.wm_available = 1;
  1535         //VideoInfo12.video_mem = 1024 * 256;
  1536     }
  1537     return &VideoInfo12;
  1538 }
  1539 
  1540 DECLSPEC int SDLCALL
  1541 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1542 {
  1543     int i, nummodes, actual_bpp = 0;
  1544 
  1545     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1546         return 0;
  1547     }
  1548 
  1549     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1550         SDL_DisplayMode mode;
  1551         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1552         return SDL_BITSPERPIXEL(mode.format);
  1553     }
  1554 
  1555     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1556     for (i = 0; i < nummodes; ++i) {
  1557         SDL_DisplayMode mode;
  1558         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1559         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1560             if (!mode.format) {
  1561                 return bpp;
  1562             }
  1563             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1564                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1565             }
  1566         }
  1567     }
  1568     return actual_bpp;
  1569 }
  1570 
  1571 DECLSPEC SDL12_Rect ** SDLCALL
  1572 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
  1573 {
  1574     Uint32 fmt;
  1575     int i;
  1576 
  1577     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1578         return NULL;
  1579     }
  1580 
  1581     if ((!format12) && (!VideoInfo12.vfmt)) {
  1582         SDL20_SetError("No pixel format specified");
  1583         return NULL;
  1584     }
  1585 
  1586     if (!(flags & SDL12_FULLSCREEN)) {
  1587         return (SDL12_Rect **) (-1);  /* any resolution is fine. */
  1588     }
  1589 
  1590     if (format12) {
  1591         fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1592     } else {
  1593         fmt = VideoInfo12.vfmt->format;
  1594     }
  1595 
  1596     for (i = 0; i < VideoModesCount; i++) {
  1597         VideoModeList *modes = &VideoModes[i];
  1598         if (modes->format == fmt) {
  1599             return modes->modes12;
  1600         }
  1601     }
  1602 
  1603     SDL20_SetError("No modes support requested pixel format");
  1604     return NULL;
  1605 }
  1606 
  1607 DECLSPEC void SDLCALL
  1608 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1609 {
  1610     if (cursor12) {
  1611         if (cursor12->wm_cursor)
  1612             SDL20_FreeCursor(cursor12->wm_cursor);
  1613         SDL20_free(cursor12->data);
  1614         SDL20_free(cursor12->mask);
  1615         SDL20_free(cursor12);
  1616     }
  1617 }
  1618 
  1619 DECLSPEC SDL12_Cursor * SDLCALL
  1620 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1621 {
  1622     const size_t datasize = h * (w / 8);
  1623     SDL_Cursor *cursor20 = NULL;
  1624     SDL12_Cursor *retval = NULL;
  1625 
  1626     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1627     if (!retval)
  1628         goto outofmem;
  1629 
  1630     SDL20_zerop(retval);
  1631 
  1632     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1633     if (!retval->data)
  1634         goto outofmem;
  1635 
  1636     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1637     if (!retval->mask)
  1638         goto outofmem;
  1639 
  1640     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1641     if (!cursor20)
  1642         goto failed;
  1643 
  1644     retval->area.w = w;
  1645     retval->area.h = h;
  1646     retval->hot_x = hot_x;
  1647     retval->hot_y = hot_y;
  1648     retval->wm_cursor = cursor20;
  1649     /* we always leave retval->save as null pointers. */
  1650 
  1651     SDL20_memcpy(retval->data, data, datasize);
  1652     SDL20_memcpy(retval->mask, mask, datasize);
  1653 
  1654     return retval;
  1655 
  1656 outofmem:
  1657     SDL20_OutOfMemory();
  1658 
  1659 failed:
  1660     SDL_FreeCursor(retval);
  1661     return NULL;
  1662 }
  1663 
  1664 DECLSPEC void SDLCALL
  1665 SDL_SetCursor(SDL12_Cursor *cursor)
  1666 {
  1667     CurrentCursor12 = cursor;
  1668     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1669 }
  1670 
  1671 DECLSPEC SDL12_Cursor * SDLCALL
  1672 SDL_GetCursor(void)
  1673 {
  1674     return CurrentCursor12;
  1675 }
  1676 
  1677 static void
  1678 GetEnvironmentWindowPosition(int *x, int *y)
  1679 {
  1680     int display = VideoDisplayIndex;
  1681     const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
  1682     const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
  1683     if (window) {
  1684         if (SDL20_strcmp(window, "center") == 0) {
  1685             center = window;
  1686         } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
  1687             return;
  1688         }
  1689     }
  1690 
  1691     if (center) {
  1692         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1693         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1694     }
  1695 }
  1696 
  1697 static void
  1698 SetupScreenSaver(const int flags12)
  1699 {
  1700     const char *env;
  1701     SDL_bool allow_screensaver;
  1702 
  1703     /* Allow environment override of screensaver disable */
  1704     env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1705     if (env) {
  1706         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1707     } else if (flags12 & SDL12_FULLSCREEN) {
  1708         allow_screensaver = SDL_FALSE;
  1709     } else {
  1710         allow_screensaver = SDL_TRUE;
  1711     }
  1712     if (allow_screensaver) {
  1713         SDL20_EnableScreenSaver();
  1714     } else {
  1715         SDL20_DisableScreenSaver();
  1716     }
  1717 }
  1718 
  1719 
  1720 static SDL12_Surface *
  1721 EndVidModeCreate(void)
  1722 {
  1723     if (VideoTexture20) {
  1724         SDL20_DestroyTexture(VideoTexture20);
  1725         VideoTexture20 = NULL;
  1726     }
  1727     if (VideoRenderer20) {
  1728         SDL20_DestroyRenderer(VideoRenderer20);
  1729         VideoRenderer20 = NULL;
  1730     }
  1731     if (VideoGLContext20) {
  1732         SDL20_GL_MakeCurrent(NULL, NULL);
  1733         SDL20_GL_DeleteContext(VideoGLContext20);
  1734         VideoGLContext20 = NULL;
  1735     }
  1736     if (VideoWindow20) {
  1737         SDL20_DestroyWindow(VideoWindow20);
  1738         VideoWindow20 = NULL;
  1739     }
  1740     if (VideoSurface12) {
  1741         SDL20_free(VideoSurface12->pixels);
  1742         VideoSurface12->pixels = NULL;
  1743         SDL_FreeSurface(VideoSurface12);
  1744         VideoSurface12 = NULL;
  1745     }
  1746     if (VideoConvertSurface20) {
  1747         SDL20_FreeSurface(VideoConvertSurface20);
  1748         VideoConvertSurface20 = NULL;
  1749     }
  1750     return NULL;
  1751 }
  1752 
  1753 
  1754 static SDL12_Surface *
  1755 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
  1756 {
  1757     Uint32 rmask, gmask, bmask, amask;
  1758     int bpp;
  1759     if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
  1760         return NULL;
  1761     }
  1762     return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
  1763 }
  1764 
  1765 static SDL_Surface *
  1766 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
  1767 {
  1768     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
  1769     if (surface20) {
  1770         surface20->flags |= SDL_PREALLOC;
  1771         surface20->pixels = NULL;
  1772         surface20->w = width;
  1773         surface20->h = height;
  1774         surface20->pitch = 0;
  1775         SDL20_SetClipRect(surface20, NULL);
  1776     }
  1777     return surface20;
  1778 }
  1779 
  1780 
  1781 DECLSPEC SDL12_Surface * SDLCALL
  1782 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1783 {
  1784     FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
  1785     SDL_DisplayMode dmode;
  1786     Uint32 fullscreen_flags20 = 0;
  1787     Uint32 appfmt;
  1788 
  1789     /* SDL_SetVideoMode() implicitly inits if necessary. */
  1790     if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
  1791         if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
  1792             return NULL;
  1793         }
  1794     }
  1795 
  1796     if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
  1797         FIXME("No OPENGLBLIT support at the moment");
  1798         SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
  1799         return NULL;
  1800     }
  1801 
  1802     FIXME("handle SDL_ANYFORMAT");
  1803 
  1804     if ((width < 0) || (height < 0)) {
  1805         SDL20_SetError("Invalid width or height");
  1806         return NULL;
  1807     }
  1808 
  1809     FIXME("There's an environment variable to choose a display");
  1810     if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
  1811         return NULL;
  1812     }
  1813 
  1814     if (width == 0) {
  1815         width = dmode.w;
  1816     }
  1817 
  1818     if (height == 0) {
  1819         height = dmode.h;
  1820     }
  1821 
  1822     if (bpp == 0) {
  1823         bpp = SDL_BITSPERPIXEL(dmode.format);
  1824     }
  1825 
  1826     switch (bpp) {
  1827         case  8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
  1828         case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
  1829         case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
  1830         case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
  1831         default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
  1832     }
  1833 
  1834     SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
  1835 
  1836     FIXME("don't do anything if the window's dimensions, etc haven't changed.");
  1837     FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
  1838 
  1839     if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
  1840         EndVidModeCreate();  /* rebuild the window if moving to/from a GL context */
  1841     } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
  1842         EndVidModeCreate();  /* rebuild the window if changing pixel format */
  1843     } else if (VideoGLContext20) {
  1844         /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
  1845         SDL20_GL_MakeCurrent(NULL, NULL);
  1846         SDL20_GL_DeleteContext(VideoGLContext20);
  1847         VideoGLContext20 = NULL;
  1848     }
  1849 
  1850     if (flags12 & SDL12_FULLSCREEN) {
  1851         // OpenGL tries to force the real resolution requested, but for
  1852         //  software rendering, we're just going to push it off onto the
  1853         //  GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
  1854         FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
  1855         if (flags12 & SDL12_OPENGL) {
  1856             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
  1857         } else {
  1858             fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
  1859         }
  1860     }
  1861 
  1862     if (!VideoWindow20) {  /* create it */
  1863         int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
  1864         Uint32 flags20 = fullscreen_flags20;
  1865         if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
  1866         if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
  1867         if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
  1868 
  1869         /* most platforms didn't check these environment variables, but the major
  1870            ones did (x11, windib, quartz), so we'll just offer it everywhere. */
  1871         GetEnvironmentWindowPosition(&x, &y);
  1872 
  1873         VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
  1874         if (!VideoWindow20) {
  1875             return EndVidModeCreate();
  1876         }
  1877     } else {  /* resize it */
  1878         SDL20_SetWindowSize(VideoWindow20, width, height);
  1879         SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
  1880         SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
  1881         SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
  1882     }
  1883 
  1884     if (VideoSurface12) {
  1885         SDL20_free(VideoSurface12->pixels);
  1886     } else {
  1887         VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
  1888         if (!VideoSurface12) {
  1889             return EndVidModeCreate();
  1890         }
  1891     }
  1892 
  1893     VideoSurface12->surface20->flags |= SDL_PREALLOC;
  1894     VideoSurface12->flags |= SDL12_PREALLOC;
  1895     VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
  1896     VideoSurface12->w = VideoSurface12->surface20->w = width;
  1897     VideoSurface12->h = VideoSurface12->surface20->h = height;
  1898     VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
  1899     SDL_SetClipRect(VideoSurface12, NULL);
  1900 
  1901     if (flags12 & SDL12_OPENGL) {
  1902         SDL_assert(!VideoTexture20);  /* either a new window or we destroyed all this */
  1903         SDL_assert(!VideoRenderer20);
  1904         VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
  1905         if (!VideoGLContext20) {
  1906             return EndVidModeCreate();
  1907         }
  1908 
  1909         VideoSurface12->flags |= SDL12_OPENGL;
  1910     } else {
  1911         /* always use a renderer for non-OpenGL windows. */
  1912         SDL_RendererInfo rinfo;
  1913         SDL_assert(!VideoGLContext20);  /* either a new window or we destroyed all this */
  1914         if (!VideoRenderer20) {
  1915             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
  1916         }
  1917         if (!VideoRenderer20) {
  1918             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_PRESENTVSYNC);
  1919         }
  1920         if (!VideoRenderer20) {
  1921             VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
  1922         }
  1923         if (!VideoRenderer20) {
  1924             return EndVidModeCreate();
  1925         }
  1926 
  1927         SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
  1928         SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
  1929         SDL20_RenderClear(VideoRenderer20);
  1930         SDL20_RenderPresent(VideoRenderer20);
  1931         SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
  1932 
  1933         if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
  1934             return EndVidModeCreate();
  1935         }
  1936 
  1937         if (VideoTexture20) {
  1938             SDL20_DestroyTexture(VideoTexture20);
  1939         }
  1940 
  1941         if (VideoConvertSurface20) {
  1942             SDL20_FreeSurface(VideoConvertSurface20);
  1943             VideoConvertSurface20 = NULL;
  1944         }
  1945 
  1946         VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
  1947         if (!VideoTexture20) {
  1948             return EndVidModeCreate();
  1949         }
  1950 
  1951         if (rinfo.texture_formats[0] != appfmt) {
  1952             /* need to convert between app's format and texture format */
  1953             VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
  1954             if (!VideoConvertSurface20) {
  1955                 return EndVidModeCreate();
  1956             }
  1957         }
  1958 
  1959         VideoSurface12->flags &= ~SDL12_OPENGL;
  1960         VideoSurface12->flags |= SDL12_DOUBLEBUF;
  1961         VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
  1962         VideoSurface12->pixels = VideoSurface12->surface20->pixels;
  1963         if (!VideoSurface12->pixels) {
  1964             SDL20_OutOfMemory();
  1965             return EndVidModeCreate();
  1966         }
  1967 
  1968         /* fill in the same default palette that SDL 1.2 does... */
  1969         if (VideoSurface12->format->BitsPerPixel == 8) {
  1970             int i;
  1971             SDL_Color *color = VideoSurface12->format->palette->colors;
  1972             for (i = 0; i < 256; i++, color++) {
  1973                 { const int x = i & 0xe0; color->r = x | x >> 3 | x >> 6; }
  1974                 { const int x = (i << 3) & 0xe0; color->g = x | x >> 3 | x >> 6; }
  1975                 { const int x = (i & 0x3) | ((i & 0x3) << 2); color->b = x | x << 4; }
  1976                 color->a = 255;
  1977             }
  1978         }
  1979     }
  1980 
  1981     FIXME("setup screen saver");
  1982 
  1983     return VideoSurface12;
  1984 }
  1985 
  1986 DECLSPEC SDL12_Surface * SDLCALL
  1987 SDL_GetVideoSurface(void)
  1988 {
  1989     return VideoSurface12;
  1990 }
  1991 
  1992 DECLSPEC int SDLCALL
  1993 SDL_UpperBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
  1994 {
  1995     SDL_Rect srcrect20, dstrect20;
  1996     const int retval = SDL20_UpperBlit(src->surface20,
  1997                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  1998                                        dst->surface20,
  1999                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  2000 
  2001     if (srcrect12) {
  2002         Rect20to12(&srcrect20, srcrect12);
  2003     }
  2004 
  2005     if (srcrect12) {
  2006         Rect20to12(&dstrect20, dstrect12);
  2007     }
  2008 
  2009     return retval;
  2010 }
  2011 
  2012 DECLSPEC int SDLCALL
  2013 SDL_LowerBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
  2014 {
  2015     SDL_Rect srcrect20, dstrect20;
  2016     const int retval = SDL20_LowerBlit(src->surface20,
  2017                                        srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
  2018                                        dst->surface20,
  2019                                        dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
  2020 
  2021     if (srcrect12) {
  2022         Rect20to12(&srcrect20, srcrect12);
  2023     }
  2024 
  2025     if (srcrect12) {
  2026         Rect20to12(&dstrect20, dstrect12);
  2027     }
  2028 
  2029     return retval;
  2030 }
  2031 
  2032 DECLSPEC int SDLCALL
  2033 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
  2034 {
  2035     FIXME("write me");
  2036     return SDL20_Unsupported();
  2037 }
  2038 
  2039 DECLSPEC SDL12_Surface * SDLCALL
  2040 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
  2041 {
  2042     Uint32 flags20 = 0;
  2043     SDL_PixelFormat format20;
  2044     SDL_Palette palette20;
  2045     SDL_Surface *surface20;
  2046     SDL12_Surface *retval = NULL;
  2047 
  2048     if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
  2049     if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
  2050 
  2051     surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
  2052     if (surface20) {
  2053         retval = Surface20to12(surface20);
  2054         if (!retval) {
  2055             SDL20_FreeSurface(surface20);
  2056         }
  2057     }
  2058     return retval;
  2059 }
  2060 
  2061 DECLSPEC SDL12_Surface * SDLCALL
  2062 SDL_DisplayFormat(SDL12_Surface *surface12)
  2063 {
  2064     const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
  2065     return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
  2066 }
  2067 
  2068 DECLSPEC SDL12_Surface * SDLCALL
  2069 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  2070 {
  2071     FIXME("write me");
  2072     SDL20_Unsupported();
  2073     return NULL;
  2074 }
  2075 
  2076 static void
  2077 PresentScreen(void)
  2078 {
  2079     void *pixels = NULL;
  2080     int pitch = 0;
  2081 
  2082     SDL_assert(VideoSurface12 != NULL);
  2083 
  2084     if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
  2085         return;  /* oh well */
  2086     }
  2087 
  2088     FIXME("Maybe lock texture always, until present, if no conversion needed?");
  2089     VideoConvertSurface20->pixels = pixels;
  2090     VideoConvertSurface20->pitch = pitch;
  2091     SDL20_UpperBlit(VideoSurface12->surface20, NULL, VideoConvertSurface20, NULL);
  2092     VideoConvertSurface20->pixels = NULL;
  2093     VideoConvertSurface20->pitch = 0;
  2094 
  2095     SDL20_UnlockTexture(VideoTexture20);
  2096     SDL20_RenderCopy(VideoRenderer20, VideoTexture20, NULL, NULL);
  2097     SDL20_RenderPresent(VideoRenderer20);
  2098 }
  2099 
  2100 DECLSPEC void SDLCALL
  2101 SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
  2102 {
  2103     /* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
  2104     /* (UpdateRect, singular, does...) */
  2105     if (surface12->flags & SDL12_OPENGL) {
  2106         SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2107         return;
  2108     }
  2109 
  2110     /* everything else is marked SDL12_DOUBLEBUF and is a no-op here. */
  2111 }
  2112 
  2113 DECLSPEC void SDLCALL
  2114 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  2115 {
  2116     if (screen12) {
  2117         SDL12_Rect rect12;
  2118         rect12.x = (Sint16) x;
  2119         rect12.y = (Sint16) y;
  2120         rect12.w = (Uint16) (w ? w : screen12->w);
  2121         rect12.h = (Uint16) (h ? h : screen12->h);
  2122         SDL_UpdateRects(screen12, 1, &rect12);
  2123     }
  2124 }
  2125 
  2126 DECLSPEC int SDLCALL
  2127 SDL_Flip(SDL12_Surface *surface12)
  2128 {
  2129     if (surface12->flags & SDL12_OPENGL) {
  2130         return SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
  2131     }
  2132 
  2133     if (surface12 == VideoSurface12) {
  2134         PresentScreen();
  2135     }
  2136 
  2137     return 0;
  2138 }
  2139 
  2140 DECLSPEC void SDLCALL
  2141 SDL_WM_SetCaption(const char *title, const char *icon)
  2142 {
  2143     if (WindowTitle) {
  2144         SDL20_free(WindowTitle);
  2145     }
  2146     if (WindowIconTitle) {
  2147         SDL20_free(WindowIconTitle);
  2148     }
  2149     WindowTitle = title ? SDL_strdup(title) : NULL;
  2150     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  2151     if (VideoWindow20) {
  2152         SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  2153     }
  2154 }
  2155 
  2156 DECLSPEC void SDLCALL
  2157 SDL_WM_GetCaption(const char **title, const char **icon)
  2158 {
  2159     if (title) {
  2160         *title = WindowTitle;
  2161     }
  2162     if (icon) {
  2163         *icon = WindowIconTitle;
  2164     }
  2165 }
  2166 
  2167 DECLSPEC void SDLCALL
  2168 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  2169 {
  2170     FIXME("write me");
  2171     SDL20_Unsupported();
  2172 }
  2173 
  2174 DECLSPEC int SDLCALL
  2175 SDL_WM_IconifyWindow(void)
  2176 {
  2177     SDL20_MinimizeWindow(VideoWindow20);
  2178     return 0;
  2179 }
  2180 
  2181 DECLSPEC int SDLCALL
  2182 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
  2183 {
  2184     FIXME("write me");
  2185     return SDL20_Unsupported();
  2186 }
  2187 
  2188 typedef enum
  2189 {
  2190     SDL12_GRAB_QUERY = -1,
  2191     SDL12_GRAB_OFF = 0,
  2192     SDL12_GRAB_ON = 1
  2193 } SDL12_GrabMode;
  2194 
  2195 DECLSPEC SDL12_GrabMode SDLCALL
  2196 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2197 {
  2198     if (mode != SDL12_GRAB_QUERY) {
  2199         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2200     }
  2201     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2202 }
  2203 
  2204 DECLSPEC void SDLCALL
  2205 SDL_WarpMouse(Uint16 x, Uint16 y)
  2206 {
  2207     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2208 }
  2209 
  2210 DECLSPEC Uint8 SDLCALL
  2211 SDL_GetAppState(void)
  2212 {
  2213     Uint8 state12 = 0;
  2214     Uint32 flags20 = 0;
  2215 
  2216     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2217     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2218         state12 |= SDL12_APPACTIVE;
  2219     }
  2220     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2221         state12 |= SDL12_APPINPUTFOCUS;
  2222     }
  2223     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2224         state12 |= SDL12_APPMOUSEFOCUS;
  2225     }
  2226     return state12;
  2227 }
  2228 
  2229 DECLSPEC int SDLCALL
  2230 SDL_SetColorKey(SDL12_Surface *surface12, Uint32 flag12, Uint32 key)
  2231 {
  2232     const SDL_bool addkey = (flag12 & SDL12_SRCCOLORKEY) ? SDL_TRUE : SDL_FALSE;
  2233     const int retval = SDL20_SetColorKey(surface12->surface20, addkey, key);
  2234     if (SDL20_GetColorKey(surface12->surface20, &surface12->format->colorkey) < 0) {
  2235         surface12->format->colorkey = 0;
  2236     }
  2237     return retval;
  2238 }
  2239 
  2240 DECLSPEC int SDLCALL
  2241 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
  2242                int firstcolor, int ncolors)
  2243 {
  2244     FIXME("write me");
  2245     return SDL20_Unsupported();
  2246 }
  2247 
  2248 DECLSPEC int SDLCALL
  2249 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
  2250               int ncolors)
  2251 {
  2252     FIXME("write me");
  2253     return SDL20_Unsupported();
  2254 }
  2255 
  2256 DECLSPEC int SDLCALL
  2257 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2258 {
  2259     FIXME("write me");
  2260     //return SDL20_GetWindowWMInfo(VideoWindow20, info);
  2261     return SDL20_Unsupported();
  2262 }
  2263 
  2264 DECLSPEC SDL12_Overlay * SDLCALL
  2265 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
  2266 {
  2267     FIXME("write me");
  2268     SDL20_Unsupported();
  2269     return NULL;
  2270 }
  2271 
  2272 DECLSPEC int SDLCALL
  2273 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
  2274 {
  2275     FIXME("write me");
  2276     return SDL20_Unsupported();
  2277 }
  2278 
  2279 DECLSPEC void SDLCALL
  2280 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
  2281 {
  2282     FIXME("write me");
  2283 }
  2284 
  2285 DECLSPEC int SDLCALL
  2286 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL12_Rect * dstrect12)
  2287 {
  2288     FIXME("write me");
  2289     return SDL20_Unsupported();
  2290 }
  2291 
  2292 DECLSPEC void SDLCALL
  2293 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
  2294 {
  2295     FIXME("write me");
  2296 }
  2297 
  2298 DECLSPEC int SDLCALL
  2299 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2300 {
  2301     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2302         return SDL20_SetError("Unknown GL attribute");
  2303 
  2304     /* swap control was moved out of this API, everything else lines up. */
  2305     if (attr == SDL12_GL_SWAP_CONTROL)
  2306     {
  2307         SwapInterval = value;
  2308         FIXME("Actually set swap interval somewhere");
  2309         return 0;
  2310     }
  2311 
  2312     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2313 }
  2314 
  2315 DECLSPEC int SDLCALL
  2316 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2317 {
  2318     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2319         return SDL20_SetError("Unknown GL attribute");
  2320 
  2321     /* swap control was moved out of this API, everything else lines up. */
  2322     if (attr == SDL12_GL_SWAP_CONTROL)
  2323     {
  2324         *value = SDL20_GL_GetSwapInterval();
  2325         return 0;
  2326     }
  2327 
  2328     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2329 }
  2330 
  2331 
  2332 DECLSPEC void SDLCALL
  2333 SDL_GL_SwapBuffers(void)
  2334 {
  2335     if (VideoWindow20)
  2336         SDL20_GL_SwapWindow(VideoWindow20);
  2337 }
  2338 
  2339 DECLSPEC int SDLCALL
  2340 SDL_SetGamma(float red, float green, float blue)
  2341 {
  2342     Uint16 red_ramp[256];
  2343     Uint16 green_ramp[256];
  2344     Uint16 blue_ramp[256];
  2345 
  2346     SDL20_CalculateGammaRamp(red, red_ramp);
  2347     if (green == red) {
  2348         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2349     } else {
  2350         SDL20_CalculateGammaRamp(green, green_ramp);
  2351     }
  2352     if (blue == red) {
  2353         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2354     } else if (blue == green) {
  2355         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2356     } else {
  2357         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2358     }
  2359     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2360 }
  2361 
  2362 DECLSPEC int SDLCALL
  2363 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2364 {
  2365     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2366 }
  2367 
  2368 DECLSPEC int SDLCALL
  2369 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2370 {
  2371     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2372 }
  2373 
  2374 DECLSPEC int SDLCALL
  2375 SDL_EnableKeyRepeat(int delay, int interval)
  2376 {
  2377     return 0;
  2378 }
  2379 
  2380 DECLSPEC void SDLCALL
  2381 SDL_GetKeyRepeat(int *delay, int *interval)
  2382 {
  2383     if (delay) {
  2384         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2385     }
  2386     if (interval) {
  2387         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2388     }
  2389 }
  2390 
  2391 DECLSPEC int SDLCALL
  2392 SDL_EnableUNICODE(int enable)
  2393 {
  2394     FIXME("write me");
  2395     return SDL20_Unsupported();
  2396 }
  2397 
  2398 static Uint32
  2399 SetTimerOld_Callback(Uint32 interval, void* param)
  2400 {
  2401     return ((SDL12_TimerCallback)param)(interval);
  2402 }
  2403 
  2404 DECLSPEC int SDLCALL
  2405 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2406 {
  2407     static SDL_TimerID compat_timer;
  2408 
  2409     if (compat_timer) {
  2410         SDL20_RemoveTimer(compat_timer);
  2411         compat_timer = 0;
  2412     }
  2413 
  2414     if (interval && callback) {
  2415         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2416         if (!compat_timer) {
  2417             return -1;
  2418         }
  2419     }
  2420     return 0;
  2421 }
  2422 
  2423 DECLSPEC int SDLCALL
  2424 SDL_putenv(const char *_var)
  2425 {
  2426     char *ptr = NULL;
  2427     char *var = SDL20_strdup(_var);
  2428     if (var == NULL) {
  2429         return -1;  /* we don't set errno. */
  2430     }
  2431 
  2432     ptr = SDL20_strchr(var, '=');
  2433     if (ptr == NULL) {
  2434         SDL20_free(var);
  2435         return -1;
  2436     }
  2437 
  2438     *ptr = '\0';  /* split the string into name and value. */
  2439     SDL20_setenv(var, ptr + 1, 1);
  2440     SDL20_free(var);
  2441     return 0;
  2442 }
  2443 
  2444 
  2445 
  2446 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2447 
  2448 typedef void *SDL12_CD;  /* close enough.  :) */
  2449 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2450 
  2451 DECLSPEC int SDLCALL
  2452 SDL_CDNumDrives(void)
  2453 {
  2454     FIXME("should return -1 without SDL_INIT_CDROM");
  2455     return 0;
  2456 }
  2457 
  2458 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2459 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2460 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2461 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2462 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2463 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2464 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2465 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2466 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2467 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
  2468 
  2469 
  2470 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2471 DECLSPEC SDL_Thread * SDLCALL
  2472 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2473 {
  2474     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2475 }
  2476 #else
  2477 DECLSPEC SDL_Thread * SDLCALL
  2478 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2479 {
  2480     return SDL20_CreateThread(fn, NULL, data);
  2481 }
  2482 #endif
  2483 
  2484 DECLSPEC int SDLCALL
  2485 SDL_mutexP(SDL_mutex *mutex)
  2486 {
  2487     return SDL20_LockMutex(mutex);
  2488 }
  2489 
  2490 DECLSPEC int SDLCALL
  2491 SDL_mutexV(SDL_mutex *mutex)
  2492 {
  2493     return SDL20_UnlockMutex(mutex);
  2494 }
  2495 
  2496 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
  2497 {
  2498     FIXME("Removed from 2.0; do nothing. We can't even report failure.");
  2499     fprintf(stderr,
  2500         "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
  2501         "This program should be fixed. No thread was actually harmed.\n");
  2502 }
  2503 
  2504 /* This changed from an opaque pointer to an int in 2.0. */
  2505 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2506 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2507 
  2508 
  2509 DECLSPEC SDL12_TimerID SDLCALL
  2510 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2511 {
  2512     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2513 }
  2514 
  2515 DECLSPEC SDL_bool SDLCALL
  2516 SDL_RemoveTimer(SDL12_TimerID id)
  2517 {
  2518     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  2519 }
  2520 
  2521 
  2522 typedef struct SDL12_RWops {
  2523     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  2524     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  2525     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  2526     int (SDLCALL *close)(struct SDL12_RWops *context);
  2527     Uint32 type;
  2528     void *padding[8];
  2529     SDL_RWops *rwops20;
  2530 } SDL12_RWops;
  2531 
  2532 
  2533 DECLSPEC SDL12_RWops * SDLCALL
  2534 SDL_AllocRW(void)
  2535 {
  2536     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  2537     if (!rwops)
  2538         SDL20_OutOfMemory();
  2539     return rwops;
  2540 }
  2541 
  2542 DECLSPEC void SDLCALL
  2543 SDL_FreeRW(SDL12_RWops *rwops12)
  2544 {
  2545     SDL20_free(rwops12);
  2546 }
  2547 
  2548 static int SDLCALL
  2549 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  2550 {
  2551     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  2552 }
  2553 
  2554 static int SDLCALL
  2555 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  2556 {
  2557     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  2558 }
  2559 
  2560 static int SDLCALL
  2561 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  2562 {
  2563     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  2564 }
  2565 
  2566 static int SDLCALL
  2567 RWops20to12_close(struct SDL12_RWops *rwops12)
  2568 {
  2569     int rc = 0;
  2570     if (rwops12)
  2571     {
  2572         rc = rwops12->rwops20->close(rwops12->rwops20);
  2573         if (rc == 0)
  2574             SDL_FreeRW(rwops12);
  2575     }
  2576     return rc;
  2577 }
  2578 
  2579 static SDL12_RWops *
  2580 RWops20to12(SDL_RWops *rwops20)
  2581 {
  2582     SDL12_RWops *rwops12;
  2583 
  2584     if (!rwops20)
  2585         return NULL;
  2586 
  2587     rwops12 = SDL_AllocRW();
  2588     if (!rwops12)
  2589         return NULL;
  2590 
  2591     SDL20_zerop(rwops12);
  2592     rwops12->type = rwops20->type;
  2593     rwops12->rwops20 = rwops20;
  2594     rwops12->seek = RWops20to12_seek;
  2595     rwops12->read = RWops20to12_read;
  2596     rwops12->write = RWops20to12_write;
  2597     rwops12->close = RWops20to12_close;
  2598 
  2599     return rwops12;
  2600 }
  2601 
  2602 DECLSPEC SDL12_RWops * SDLCALL
  2603 SDL_RWFromFile(const char *file, const char *mode)
  2604 {
  2605     return RWops20to12(SDL20_RWFromFile(file, mode));
  2606 }
  2607 
  2608 DECLSPEC SDL12_RWops * SDLCALL
  2609 SDL_RWFromFP(FILE *io, int autoclose)
  2610 {
  2611     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  2612 }
  2613 
  2614 DECLSPEC SDL12_RWops * SDLCALL
  2615 SDL_RWFromMem(void *mem, int size)
  2616 {
  2617     return RWops20to12(SDL20_RWFromMem(mem, size));
  2618 }
  2619 
  2620 DECLSPEC SDL12_RWops * SDLCALL
  2621 SDL_RWFromConstMem(const void *mem, int size)
  2622 {
  2623     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  2624 }
  2625 
  2626 #define READ_AND_BYTESWAP(endian, bits) \
  2627     DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  2628         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  2629         return SDL_Swap##endian##bits(val); \
  2630     }
  2631 
  2632 READ_AND_BYTESWAP(LE,16)
  2633 READ_AND_BYTESWAP(BE,16)
  2634 READ_AND_BYTESWAP(LE,32)
  2635 READ_AND_BYTESWAP(BE,32)
  2636 READ_AND_BYTESWAP(LE,64)
  2637 READ_AND_BYTESWAP(BE,64)
  2638 #undef READ_AND_BYTESWAP
  2639 
  2640 #define BYTESWAP_AND_WRITE(endian, bits) \
  2641     DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  2642         val = SDL_Swap##endian##bits(val); \
  2643         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  2644     }
  2645 BYTESWAP_AND_WRITE(LE,16)
  2646 BYTESWAP_AND_WRITE(BE,16)
  2647 BYTESWAP_AND_WRITE(LE,32)
  2648 BYTESWAP_AND_WRITE(BE,32)
  2649 BYTESWAP_AND_WRITE(LE,64)
  2650 BYTESWAP_AND_WRITE(BE,64)
  2651 #undef BYTESWAP_AND_WRITE
  2652 
  2653 
  2654 static Sint64 SDLCALL
  2655 RWops12to20_size(struct SDL_RWops *rwops20)
  2656 {
  2657     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2658     int size = (int) ((size_t) rwops20->hidden.unknown.data2);
  2659     int pos;
  2660 
  2661     if (size != -1)
  2662         return size;
  2663 
  2664     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  2665     if (pos == -1)
  2666         return -1;
  2667 
  2668     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  2669     if (size == -1)
  2670         return -1;
  2671 
  2672     rwops12->seek(rwops12, pos, SEEK_SET);  FIXME("...and if this fails?");
  2673     rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
  2674     return size;
  2675 }
  2676 
  2677 static Sint64 SDLCALL
  2678 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  2679 {
  2680     FIXME("fail if (offset) is too big");
  2681     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2682     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  2683 }
  2684 
  2685 static size_t SDLCALL
  2686 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  2687 {
  2688     FIXME("fail if (size) or (maxnum) is too big");
  2689     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2690     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  2691 }
  2692 
  2693 static size_t SDLCALL
  2694 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  2695 {
  2696     FIXME("fail if (size) or (maxnum) is too big");
  2697     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2698     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  2699 }
  2700 
  2701 static int SDLCALL
  2702 RWops12to20_close(struct SDL_RWops *rwops20)
  2703 {
  2704     int rc = 0;
  2705     if (rwops20)
  2706     {
  2707         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  2708         rc = rwops12->close(rwops12);
  2709         if (rc == 0)
  2710             SDL20_FreeRW(rwops20);
  2711     }
  2712     return rc;
  2713 }
  2714 
  2715 static SDL_RWops *
  2716 RWops12to20(SDL12_RWops *rwops12)
  2717 {
  2718     SDL_RWops *rwops20;
  2719 
  2720     if (!rwops12)
  2721         return NULL;
  2722 
  2723     rwops20 = SDL20_AllocRW();
  2724     if (!rwops20)
  2725         return NULL;
  2726 
  2727     SDL20_zerop(rwops20);
  2728     rwops20->type = rwops12->type;
  2729     rwops20->hidden.unknown.data1 = rwops12;
  2730     rwops20->hidden.unknown.data2 = (void *) ((size_t) -1);  /* cached size of stream */
  2731     rwops20->size = RWops12to20_size;
  2732     rwops20->seek = RWops12to20_seek;
  2733     rwops20->read = RWops12to20_read;
  2734     rwops20->write = RWops12to20_write;
  2735     rwops20->close = RWops12to20_close;
  2736     return rwops20;
  2737 }
  2738 
  2739 DECLSPEC SDL12_Surface * SDLCALL
  2740 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  2741 {
  2742     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2743     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  2744     SDL12_Surface *surface12 = Surface20to12(surface20);
  2745     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2746         SDL20_FreeRW(rwops20);
  2747     if ((!surface12) && (surface20))
  2748         SDL20_FreeSurface(surface20);
  2749     return surface12;
  2750 }
  2751 
  2752 DECLSPEC int SDLCALL
  2753 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  2754 {
  2755     FIXME("wrap surface");
  2756     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2757     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  2758     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2759         SDL20_FreeRW(rwops20);
  2760     return retval;
  2761 }
  2762 
  2763 DECLSPEC SDL_AudioSpec * SDLCALL
  2764 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  2765                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  2766 {
  2767     SDL_RWops *rwops20 = RWops12to20(rwops12);
  2768     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  2769     FIXME("deal with non-1.2 formats, like float32");
  2770     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  2771         SDL20_FreeRW(rwops20);
  2772     return retval;
  2773 }
  2774 
  2775 /* vi: set ts=4 sw=4 expandtab: */