src/SDL12_compat.c
author Ryan C. Gordon <icculus@icculus.org>
Sat, 13 Apr 2013 23:38:00 -0400
changeset 34 946cbc18ba19
parent 33 4e9cde983cdc
child 35 365748d8ff6c
permissions -rw-r--r--
More work on pushing this through compiler/linker.

Disabled a lot of the original compat code until I can go through it by hand.
There's a lot of bitrot in there, not to mention things that didn't plan to
tapdance like this in the first place.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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 #include "SDL20_include_wrapper.h"
    25 
    26 #if !SDL_VERSION_ATLEAST(2,0,0)
    27 #error You need to compile against SDL 2.0 headers.
    28 #endif
    29 
    30 /*
    31  * We report the library version as 1.2.$(SDL12_COMPAT_VERSION). This number
    32  *  should be way ahead of what SDL-1.2 Classic would report, so apps can
    33  *  decide if they're running under the compat layer, if they really care.
    34  */
    35 #define SDL12_COMPAT_VERSION 50
    36 
    37 #include <stdarg.h>
    38 
    39 //#include "video/SDL_sysvideo.h"
    40 //#include "video/SDL_pixels_c.h"
    41 //#include "render/SDL_yuv_sw_c.h"
    42 
    43 // !!! IMPLEMENT_ME SDL_ConvertSurface
    44 // !!! IMPLEMENT_ME SDL_GetKeyName
    45 // !!! IMPLEMENT_ME SDL_GetKeyState
    46 // !!! IMPLEMENT_ME SDL_GetModState
    47 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
    48 // !!! IMPLEMENT_ME SDL_LockSurface
    49 // !!! IMPLEMENT_ME SDL_LowerBlit
    50 // !!! IMPLEMENT_ME SDL_SetColorKey
    51 // !!! IMPLEMENT_ME SDL_SetModState
    52 // !!! IMPLEMENT_ME SDL_SoftStretch
    53 // !!! IMPLEMENT_ME SDL_UnlockSurface
    54 // !!! IMPLEMENT_ME SDL_UpperBlit
    55 // !!! IMPLEMENT_ME X11_KeyToUnicode
    56 
    57 
    58 #define SDL20_SYM(rc,fn,params,args,ret) \
    59     typedef rc (*SDL20_##fn##_t) params; \
    60     static SDL20_##fn##_t SDL20_##fn = NULL;
    61 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
    62     SDL20_SYM(rc,fn,params,args,ret)
    63 #include "SDL20_syms.h"
    64 #undef SDL20_SYM_PASSTHROUGH
    65 #undef SDL20_SYM
    66 
    67 typedef int (*SDL20_SetError_t)(const char *fmt, ...);
    68 static SDL20_SetError_t SDL20_SetError = NULL;
    69 
    70 /* Things that _should_ be binary compatible pass right through... */
    71 #define SDL20_SYM(rc,fn,params,args,ret)
    72 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
    73     rc SDL_##fn params { ret SDL20_##fn args; }
    74 #include "SDL20_syms.h"
    75 #undef SDL20_SYM_PASSTHROUGH
    76 #undef SDL20_SYM
    77 
    78 
    79 /* these are macros (etc) in the SDL headers, so make our own. */
    80 #define SDL20_OutOfMemory() SDL20_Error(SDL_ENOMEM)
    81 #define SDL20_Unsupported() SDL20_Error(SDL_UNSUPPORTED)
    82 #define SDL20_InvalidParamError(param) SDL20_SetError("Parameter '%s' is invalid", (param))
    83 #define SDL20_zero(x) SDL20_memset(&(x), 0, sizeof((x)))
    84 #define SDL20_zerop(x) SDL20_memset((x), 0, sizeof(*(x)))
    85 #define SDL_ReportAssertion SDL20_ReportAssertion
    86 
    87 #define SDL12_DEFAULT_REPEAT_DELAY 500
    88 #define SDL12_DEFAULT_REPEAT_INTERVAL 30
    89 
    90 #define SDL12_INIT_TIMER       0x00000001
    91 #define SDL12_INIT_AUDIO       0x00000010
    92 #define SDL12_INIT_VIDEO       0x00000020
    93 #define SDL12_INIT_CDROM       0x00000100
    94 #define SDL12_INIT_JOYSTICK    0x00000200
    95 #define SDL12_INIT_NOPARACHUTE 0x00100000
    96 #define SDL12_INIT_EVENTTHREAD 0x01000000
    97 #define SDL12_INIT_EVERYTHING  0x0000FFFF
    98 
    99 typedef struct SDL12_Palette
   100 {
   101     int       ncolors;
   102     SDL_Color *colors;
   103 } SDL12_Palette;
   104 
   105 typedef struct SDL12_PixelFormat
   106 {
   107     SDL12_Palette *palette;
   108     Uint8 BitsPerPixel;
   109     Uint8 BytesPerPixel;
   110     Uint8 Rloss;
   111     Uint8 Gloss;
   112     Uint8 Bloss;
   113     Uint8 Aloss;
   114     Uint8 Rshift;
   115     Uint8 Gshift;
   116     Uint8 Bshift;
   117     Uint8 Ashift;
   118     Uint32 Rmask;
   119     Uint32 Gmask;
   120     Uint32 Bmask;
   121     Uint32 Amask;
   122     Uint32 colorkey;
   123     Uint8 alpha;
   124 } SDL12_PixelFormat;
   125 
   126 typedef struct SDL12_Surface
   127 {
   128     Uint32 flags;
   129     SDL12_PixelFormat *format;
   130     int w;
   131     int h;
   132     Uint16 pitch;
   133     void *pixels;
   134     int offset;
   135     SDL_Surface *surface20; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here named "hwdata". */
   136     SDL_Rect clip_rect;
   137     Uint32 unused1;
   138     Uint32 locked;
   139     void *blitmap;
   140     unsigned int format_version;
   141     int refcount;
   142 } SDL12_Surface;
   143 
   144 typedef struct
   145 {
   146     Uint32 hw_available :1;
   147     Uint32 wm_available :1;
   148     Uint32 UnusedBits1  :6;
   149     Uint32 UnusedBits2  :1;
   150     Uint32 blit_hw      :1;
   151     Uint32 blit_hw_CC   :1;
   152     Uint32 blit_hw_A    :1;
   153     Uint32 blit_sw      :1;
   154     Uint32 blit_sw_CC   :1;
   155     Uint32 blit_sw_A    :1;
   156     Uint32 blit_fill    :1;
   157     Uint32 UnusedBits3  :16;
   158     Uint32 video_mem;
   159     SDL_PixelFormat *vfmt;
   160     int current_w;
   161     int current_h;
   162 } SDL12_VideoInfo;
   163 
   164 
   165 #define SDL12_HWSURFACE 0x00000001
   166 #define SDL12_ASYNCBLIT 0x00000004
   167 #define SDL12_ANYFORMAT 0x10000000
   168 #define SDL12_HWPALETTE 0x20000000
   169 #define SDL12_DOUBLEBUF 0x40000000
   170 #define SDL12_FULLSCREEN 0x80000000
   171 #define SDL12_OPENGL 0x00000002
   172 #define SDL12_OPENGLBLIT 0x0000000A
   173 #define SDL12_RESIZABLE 0x00000010
   174 #define SDL12_NOFRAME 0x00000020
   175 #define SDL12_HWACCEL 0x00000100
   176 #define SDL12_SRCCOLORKEY 0x00001000
   177 #define SDL12_RLEACCELOK 0x00002000
   178 #define SDL12_RLEACCEL 0x00004000
   179 #define SDL12_SRCALPHA 0x00010000
   180 #define SDL12_PREALLOC 0x01000000
   181 
   182 typedef enum
   183 {
   184     SDL12_NOEVENT = 0,
   185     SDL12_ACTIVEEVENT,
   186     SDL12_KEYDOWN,
   187     SDL12_KEYUP,
   188     SDL12_MOUSEMOTION,
   189     SDL12_MOUSEBUTTONDOWN,
   190     SDL12_MOUSEBUTTONUP,
   191     SDL12_JOYAXISMOTION,
   192     SDL12_JOYBALLMOTION,
   193     SDL12_JOYHATMOTION,
   194     SDL12_JOYBUTTONDOWN,
   195     SDL12_JOYBUTTONUP,
   196     SDL12_QUIT,
   197     SDL12_SYSWMEVENT,
   198     SDL12_EVENT_RESERVEDA,
   199     SDL12_EVENT_RESERVEDB,
   200     SDL12_VIDEORESIZE,
   201     SDL12_VIDEOEXPOSE,
   202     SDL12_USEREVENT = 24,
   203     SDL12_NUMEVENTS = 32
   204 } SDL12_EventType;
   205 
   206 
   207 #define SDL12_APPMOUSEFOCUS (1<<0)
   208 #define SDL12_APPINPUTFOCUS (1<<1)
   209 #define SDL12_APPACTIVE     (1<<2)
   210 
   211 typedef struct
   212 {
   213     Uint8 type;
   214     Uint8 gain;
   215     Uint8 state;
   216 } SDL12_ActiveEvent;
   217 
   218 typedef struct
   219 {
   220     Uint8 type;
   221     Uint8 which;
   222     Uint8 state;
   223     //FIXME: SDL12_keysym keysym;
   224 } SDL12_KeyboardEvent;
   225 
   226 typedef struct
   227 {
   228     Uint8 type;
   229     Uint8 which;
   230     Uint8 state;
   231     Uint16 x, y;
   232     Sint16 xrel;
   233     Sint16 yrel;
   234 } SDL12_MouseMotionEvent;
   235 
   236 typedef struct
   237 {
   238     Uint8 type;
   239     Uint8 which;
   240     Uint8 button;
   241     Uint8 state;
   242     Uint16 x, y;
   243 } SDL12_MouseButtonEvent;
   244 
   245 typedef struct
   246 {
   247     Uint8 type;
   248     Uint8 which;
   249     Uint8 axis;
   250     Sint16 value;
   251 } SDL12_JoyAxisEvent;
   252 
   253 typedef struct
   254 {
   255     Uint8 type;
   256     Uint8 which;
   257     Uint8 ball;
   258     Sint16 xrel;
   259     Sint16 yrel;
   260 } SDL12_JoyBallEvent;
   261 
   262 typedef struct
   263 {
   264     Uint8 type;
   265     Uint8 which;
   266     Uint8 hat;
   267     Uint8 value;
   268 } SDL12_JoyHatEvent;
   269 
   270 typedef struct
   271 {
   272     Uint8 type;
   273     Uint8 which;
   274     Uint8 button;
   275     Uint8 state;
   276 } SDL12_JoyButtonEvent;
   277 
   278 typedef struct
   279 {
   280     Uint8 type;
   281     int w;
   282     int h;
   283 } SDL12_ResizeEvent;
   284 
   285 typedef struct
   286 {
   287     Uint8 type;
   288 } SDL12_ExposeEvent;
   289 
   290 typedef struct
   291 {
   292     Uint8 type;
   293 } SDL12_QuitEvent;
   294 
   295 typedef struct
   296 {
   297     Uint8 type;
   298     int code;
   299     void *data1;
   300     void *data2;
   301 } SDL12_UserEvent;
   302 
   303 typedef struct
   304 {
   305     Uint8 type;
   306     void *msg;
   307 } SDL12_SysWMEvent;
   308 
   309 typedef union
   310 {
   311     Uint8 type;
   312     SDL12_ActiveEvent active;
   313     SDL12_KeyboardEvent key;
   314     SDL12_MouseMotionEvent motion;
   315     SDL12_MouseButtonEvent button;
   316     SDL12_JoyAxisEvent jaxis;
   317     SDL12_JoyBallEvent jball;
   318     SDL12_JoyHatEvent jhat;
   319     SDL12_JoyButtonEvent jbutton;
   320     SDL12_ResizeEvent resize;
   321     SDL12_ExposeEvent expose;
   322     SDL12_QuitEvent quit;
   323     SDL12_UserEvent user;
   324     SDL12_SysWMEvent syswm;
   325 } SDL12_Event;
   326 
   327 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
   328 static int EventFilter20to12(void *data, SDL_Event *event20);
   329 
   330 typedef Uint32 (SDLCALL *SDL12_TimerCallback)(Uint32 interval);
   331 typedef SDL_TimerCallback SDL12_NewTimerCallback;
   332 
   333 typedef struct
   334 {
   335     SDL_Rect area;
   336     Sint16 hot_x;
   337     Sint16 hot_y;
   338     Uint8 *data;
   339     Uint8 *mask;
   340     Uint8 *save[2];
   341     SDL_Cursor *wm_cursor;  /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
   342 } SDL12_Cursor;
   343 
   344 typedef enum
   345 {
   346     SDL12_GL_RED_SIZE,
   347     SDL12_GL_GREEN_SIZE,
   348     SDL12_GL_BLUE_SIZE,
   349     SDL12_GL_ALPHA_SIZE,
   350     SDL12_GL_BUFFER_SIZE,
   351     SDL12_GL_DOUBLEBUFFER,
   352     SDL12_GL_DEPTH_SIZE,
   353     SDL12_GL_STENCIL_SIZE,
   354     SDL12_GL_ACCUM_RED_SIZE,
   355     SDL12_GL_ACCUM_GREEN_SIZE,
   356     SDL12_GL_ACCUM_BLUE_SIZE,
   357     SDL12_GL_ACCUM_ALPHA_SIZE,
   358     SDL12_GL_STEREO,
   359     SDL12_GL_MULTISAMPLEBUFFERS,
   360     SDL12_GL_MULTISAMPLESAMPLES,
   361     SDL12_GL_ACCELERATED_VISUAL,
   362     SDL12_GL_SWAP_CONTROL,
   363     SDL12_GL_MAX_ATTRIBUTE
   364 } SDL12_GLattr;
   365 
   366 static SDL12_VideoInfo VideoInfo;
   367 static SDL_Window *VideoWindow20 = NULL;
   368 static SDL12_Surface *WindowSurface = NULL;
   369 static SDL12_Surface *VideoSurface = NULL;
   370 static SDL12_Surface *ShadowSurface = NULL;
   371 static SDL12_Surface *PublicSurface = NULL;
   372 static SDL_GLContext *VideoContext = NULL;
   373 static Uint32 VideoFlags = 0;
   374 static SDL_Rect VideoViewport;
   375 static char *WindowTitle = NULL;
   376 static char *WindowIconTitle = NULL;
   377 static SDL_Surface *VideoIcon;
   378 static int EnabledUnicode = 0;
   379 static int VideoDisplayIndex = 0;
   380 static int CDRomInit = 0;
   381 static SDL12_EventFilter EventFilter12 = NULL;
   382 static SDL12_Cursor *CurrentCursor = NULL;
   383 static Uint8 EventStates[SDL12_NUMEVENTS];
   384 static int SwapInterval = 0;
   385 
   386 // !!! FIXME: need a mutex for the event queue.
   387 #define SDL12_MAXEVENTS 128
   388 typedef struct EventQueueType
   389 {
   390     SDL12_Event event12;
   391     struct EventQueueType *next;
   392 } EventQueueType;
   393 
   394 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
   395 static EventQueueType *EventQueueHead = NULL;
   396 static EventQueueType *EventQueueTail = NULL;
   397 static EventQueueType *EventQueueAvailable = NULL;
   398 
   399 const SDL_version *
   400 SDL_Linked_Version(void)
   401 {
   402     static const SDL_version version = { 1, 2, SDL12_COMPAT_VERSION };
   403     return &version;
   404 }
   405 
   406 /* Obviously we can't use SDL_LoadObject() to load SDL2.  :)  */
   407 #if defined(_WINDOWS)
   408     #define WIN32_LEAN_AND_MEAN 1
   409     #include <windows.h>
   410     #define SDL20_LIBNAME "SDL2.dll"
   411     static HANDLE Loaded_SDL20 = NULL;
   412     #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
   413     #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
   414     #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   415 #elif defined(unix) || defined(__APPLE__)
   416     #include <dlfcn.h>
   417     #ifdef __APPLE__
   418     #define SDL20_LIBNAME "libSDL2.dylib"
   419     #else
   420     #define SDL20_LIBNAME "libSDL2-2.0.so.0"
   421     #endif
   422     static void *Loaded_SDL20 = NULL;
   423     #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL)) != NULL)
   424     #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
   425     #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
   426 #else
   427     #error Please define your platform.
   428 #endif
   429 
   430 static void *
   431 LoadSDL20Symbol(const char *fn, int *okay)
   432 {
   433     void *retval = NULL;
   434     if (*okay)  /* only bother trying if we haven't previously failed. */
   435     {
   436         retval = LookupSDL20Sym(fn);
   437         if (retval == NULL)
   438             *okay = 0;
   439     }
   440     return retval;
   441 }
   442 
   443 static void
   444 UnloadSDL20(void)
   445 {
   446     #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
   447     #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_SYM(rc,fn,params,args,ret)
   448     #include "SDL20_syms.h"
   449     #undef SDL20_SYM_PASSTHROUGH
   450     #undef SDL20_SYM
   451     SDL20_SetError = NULL;
   452     CloseSDL20Library();
   453 }
   454 
   455 static int
   456 LoadSDL20(void)
   457 {
   458     int okay = 1;
   459     if (!Loaded_SDL20)
   460     {
   461         okay = LoadSDL20Library();
   462         #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
   463         #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) SDL20_SYM(rc,fn,params,args,ret)
   464         #include "SDL20_syms.h"
   465         #undef SDL20_SYM_PASSTHROUGH
   466         #undef SDL20_SYM
   467         SDL20_SetError = (SDL20_SetError_t) LoadSDL20Symbol("SDL_SetError", &okay);
   468         if (!okay)
   469             UnloadSDL20();
   470     }
   471     return okay;
   472 }
   473 
   474 
   475 static int
   476 GetVideoDisplay()
   477 {
   478     // !!! FIXME: cache this value during SDL_Init() so it doesn't change.
   479     const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
   480     if ( !variable ) {
   481         variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
   482     }
   483     if ( variable ) {
   484         return SDL20_atoi(variable);
   485     } else {
   486         return 0;
   487     }
   488 }
   489 
   490 static int
   491 DoSDLInit(const int justsubs, Uint32 sdl12flags)
   492 {
   493     Uint32 sdl20flags = 0;
   494     int rc;
   495 
   496     if (!LoadSDL20())
   497         return -1;
   498 
   499     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   500     SETFLAG(TIMER);
   501     SETFLAG(AUDIO);
   502     SETFLAG(VIDEO);
   503     SETFLAG(JOYSTICK);
   504     SETFLAG(NOPARACHUTE);
   505     #undef SETFLAG
   506 
   507     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   508     if (sdl12flags & SDL12_INIT_CDROM)
   509         CDRomInit = 1;
   510 
   511     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   512 
   513     rc = justsubs ? SDL20_InitSubSystem(sdl20flags) : SDL20_Init(sdl20flags);
   514     if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO))
   515     {
   516         int i;
   517         for (i = 0; i < SDL12_MAXEVENTS-1; i++)
   518             EventQueuePool[i].next = &EventQueuePool[i+1];
   519         EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
   520         EventQueueHead = EventQueueTail = NULL;
   521         EventQueueAvailable = EventQueuePool;
   522         SDL_memset(EventStates, SDL_ENABLE, sizeof (EventStates)); /* on by default */
   523         EventStates[SDL12_SYSWMEVENT] = SDL_IGNORE;  /* off by default. */
   524         SDL20_SetEventFilter(EventFilter20to12, NULL);
   525         VideoDisplayIndex = GetVideoDisplay();
   526         SwapInterval = 0;
   527     }
   528 
   529     return rc;
   530 }
   531 
   532 int
   533 SDL_InitSubSystem(Uint32 sdl12flags)
   534 {
   535     return DoSDLInit(1, sdl12flags);
   536 }
   537 
   538 int
   539 SDL_Init(Uint32 sdl12flags)
   540 {
   541     return DoSDLInit(0, sdl12flags);
   542 }
   543 
   544 Uint32
   545 SDL_WasInit(Uint32 sdl12flags)
   546 {
   547     // !!! FIXME: this is cut and pasted several places.
   548     Uint32 sdl20flags = 0;
   549     Uint32 extraflags = 0;
   550 
   551     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   552     SETFLAG(TIMER);
   553     SETFLAG(AUDIO);
   554     SETFLAG(VIDEO);
   555     SETFLAG(JOYSTICK);
   556     SETFLAG(NOPARACHUTE);
   557     #undef SETFLAG
   558 
   559     if ((sdl12flags & SDL12_INIT_CDROM) && (CDRomInit))
   560         extraflags |= SDL12_INIT_CDROM;
   561 
   562     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   563 
   564     // !!! FIXME: convert back to 1.2
   565     return SDL20_WasInit(sdl20flags) | extraflags;
   566 }
   567 
   568 void
   569 SDL_QuitSubSystem(Uint32 sdl12flags)
   570 {
   571     Uint32 sdl20flags = 0;
   572 
   573     #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
   574     SETFLAG(TIMER);
   575     SETFLAG(AUDIO);
   576     SETFLAG(VIDEO);
   577     SETFLAG(JOYSTICK);
   578     SETFLAG(NOPARACHUTE);
   579     // There's no CDROM in 2.0, but we'll just pretend it succeeded.
   580     #undef SETFLAG
   581 
   582     if (sdl12flags & SDL12_INIT_CDROM)
   583         CDRomInit = 0;
   584 
   585     // !!! FIXME: reset a bunch of other global variables too.
   586     if (sdl12flags & SDL12_INIT_VIDEO) {
   587         EventFilter12 = NULL;
   588         EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   589         CurrentCursor = NULL;
   590         SDL20_FreeFormat(VideoInfo.vfmt);
   591         SDL20_zero(VideoInfo);
   592     }
   593 
   594     // !!! FIXME: do something about SDL12_INIT_EVENTTHREAD
   595     SDL20_QuitSubSystem(sdl20flags);
   596 
   597     // !!! FIXME: UnloadSDL20() ?
   598 }
   599 
   600 void
   601 SDL_Quit(void)
   602 {
   603     // !!! FIXME: reset a bunch of other global variables too.
   604     EventFilter12 = NULL;
   605     EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
   606     CurrentCursor = NULL;
   607     SDL20_FreeFormat(VideoInfo.vfmt);
   608     SDL20_zero(VideoInfo);
   609     CDRomInit = 0;
   610     SDL20_Quit();
   611     UnloadSDL20();
   612 }
   613 
   614 void
   615 SDL_SetError(const char *fmt, ...)
   616 {
   617     char ch;
   618     char *str = NULL;
   619     size_t len = 0;
   620     va_list ap;
   621     va_start(ap, fmt);
   622     len = SDL20_vsnprintf(&ch, 1, fmt, ap);
   623     va_end(ap);
   624 
   625     str = (char *) SDL20_malloc(len + 1);
   626     if (!str)
   627         SDL20_OutOfMemory();
   628     else
   629     {
   630         va_start(ap, fmt);
   631         SDL20_vsnprintf(str, len + 1, fmt, ap);
   632         va_end(ap);
   633         SDL20_SetError("%s", str);
   634         SDL20_free(str);
   635     }
   636 }
   637 
   638 const char *
   639 SDL_GetError(void)
   640 {
   641     if (!Loaded_SDL20)
   642     {
   643         static const char noload_errstr[] = "Failed to load SDL 2.0 shared library";
   644         return noload_errstr;
   645     }
   646     return SDL20_GetError();
   647 }
   648 
   649 
   650 static const char *
   651 GetDriverName(const char *name, char *namebuf, int maxlen)
   652 {
   653     if (name) {
   654         if (namebuf) {
   655             SDL20_strlcpy(namebuf, name, maxlen);
   656             return namebuf;
   657         } else {
   658             return name;
   659         }
   660     }
   661     return NULL;
   662 }
   663 
   664 const char *
   665 SDL_AudioDriverName(char *namebuf, int maxlen)
   666 {
   667     return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
   668 }
   669 
   670 const char *
   671 SDL_VideoDriverName(char *namebuf, int maxlen)
   672 {
   673     return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
   674 }
   675 
   676 int
   677 SDL_PollEvent(SDL12_Event *event12)
   678 {
   679     EventQueueType *next;
   680 
   681     SDL20_PumpEvents();  /* this will run our filter and build our 1.2 queue. */
   682 
   683     if (EventQueueHead == NULL)
   684         return 0;  /* no events at the moment. */
   685 
   686     SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
   687     next = EventQueueHead->next;
   688     EventQueueHead->next = EventQueueAvailable;
   689     EventQueueAvailable = EventQueueHead;
   690     EventQueueHead = next;
   691     return 1;
   692 }
   693 
   694 int
   695 SDL_PushEvent(SDL12_Event *event12)
   696 {
   697     EventQueueType *item = EventQueueAvailable;
   698     if (item == NULL)
   699         return -1;  /* no space available at the moment. */
   700 
   701     EventQueueAvailable = item->next;
   702     if (EventQueueTail)
   703         EventQueueTail->next = item;
   704     else
   705         EventQueueHead = EventQueueTail = item;
   706     item->next = NULL;
   707 
   708     SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
   709     return 0;
   710 }
   711 
   712 int
   713 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
   714 {
   715     if (action == SDL_ADDEVENT)
   716     {
   717         int i;
   718         for (i = 0; i < numevents; i++)
   719         {
   720             if (SDL_PushEvent(&events12[i]) == -1)
   721                 break;  /* out of space for more events. */
   722         }
   723         return i;
   724     }
   725     else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
   726     {
   727         const SDL_bool isGet = (action == SDL_GETEVENT);
   728         EventQueueType *prev = NULL;
   729         EventQueueType *item = EventQueueHead;
   730         EventQueueType *next = NULL;
   731         int chosen = 0;
   732         while (chosen < numevents)
   733         {
   734             EventQueueType *nextPrev = item;
   735             if (!item)
   736                 break;  /* no more events at the moment. */
   737 
   738             next = item->next;  /* copy, since we might overwrite item->next */
   739 
   740             if (mask & (1<<item->event12.type))
   741             {
   742                 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
   743                 if (isGet)  /* remove from list? */
   744                 {
   745                     if (prev != NULL)
   746                         prev->next = next;
   747                     if (item == EventQueueHead)
   748                         EventQueueHead = next;
   749                     if (item == EventQueueTail)
   750                         EventQueueTail = prev;
   751 
   752                     /* put it back in the free pool. */
   753                     item->next = EventQueueAvailable;
   754                     EventQueueAvailable = item;
   755                     nextPrev = prev;  /* previous item doesn't change. */
   756                 }
   757             }
   758 
   759             item = next;
   760             prev = nextPrev;
   761         }
   762         return chosen;
   763     }
   764 
   765     return 0;
   766 }
   767 
   768 int
   769 SDL_WaitEvent(SDL12_Event *event12)
   770 {
   771     /* In 1.2, this only fails (-1) if you haven't SDL_Init()'d. */
   772     while (!SDL_PollEvent(event12))
   773         SDL_Delay(10);
   774     return 1;
   775 }
   776 
   777 static SDL_bool
   778 PushEventIfNotFiltered(SDL12_Event *event12)
   779 {
   780     if (event12->type != SDL12_NOEVENT)
   781     {
   782         if (EventStates[event12->type] != SDL_IGNORE)
   783         {
   784             if ((!EventFilter12) || (EventFilter12(event12)))
   785                 return (SDL_PushEvent(event12) == 0);
   786         }
   787     }
   788     return SDL_FALSE;
   789 }
   790 
   791 Uint8 SDL_GetMouseState(int *x, int *y);
   792 
   793 
   794 Uint8
   795 SDL_EventState(Uint8 type, int state)
   796 {
   797     /* the values of "state" match between 1.2 and 2.0 */
   798     const Uint8 retval = EventStates[type];
   799     SDL12_Event e;
   800 
   801     if (state != SDL_QUERY)
   802         EventStates[type] = state;
   803     if (state == SDL_IGNORE)  /* drop existing events of this type. */
   804         while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
   805 
   806     return retval;
   807 }
   808 
   809 static int
   810 EventFilter20to12(void *data, SDL_Event *event20)
   811 {
   812     const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
   813     SDL12_Event event12;
   814     int x, y;
   815 
   816     SDL_assert(data == NULL);  /* currently unused. */
   817 
   818     SDL20_zero(event12);
   819 
   820     switch (event20->type)
   821     {
   822         case SDL_QUIT:
   823             event12.type = SDL12_QUIT;
   824             break;
   825 
   826         case SDL_WINDOWEVENT:
   827             switch (event20->window.event)
   828             {
   829                 case SDL_WINDOWEVENT_CLOSE:
   830                     event12.type = SDL12_QUIT;
   831                     break;
   832 
   833                 case SDL_WINDOWEVENT_SHOWN:
   834                 case SDL_WINDOWEVENT_EXPOSED:
   835                     event12.type = SDL12_VIDEOEXPOSE;
   836                     break;
   837 
   838                 case SDL_WINDOWEVENT_RESIZED:
   839                 case SDL_WINDOWEVENT_SIZE_CHANGED:  // !!! FIXME: what's the difference between RESIZED and SIZE_CHANGED?
   840                     event12.type = SDL12_VIDEORESIZE;
   841                     event12.resize.w = event20->window.data1;
   842                     event12.resize.h = event20->window.data2;
   843                     break;
   844 
   845                 case SDL_WINDOWEVENT_MINIMIZED:
   846                     event12.type = SDL12_ACTIVEEVENT;
   847                     event12.active.gain = 0;
   848                     event12.active.state = SDL12_APPACTIVE;
   849                     break;
   850 
   851                 case SDL_WINDOWEVENT_RESTORED:
   852                     event12.type = SDL12_ACTIVEEVENT;
   853                     event12.active.gain = 1;
   854                     event12.active.state = SDL12_APPACTIVE;
   855                     break;
   856 
   857                 case SDL_WINDOWEVENT_ENTER:
   858                     event12.type = SDL12_ACTIVEEVENT;
   859                     event12.active.gain = 1;
   860                     event12.active.state = SDL12_APPMOUSEFOCUS;
   861                     break;
   862 
   863                 case SDL_WINDOWEVENT_LEAVE:
   864                     event12.type = SDL12_ACTIVEEVENT;
   865                     event12.active.gain = 0;
   866                     event12.active.state = SDL12_APPMOUSEFOCUS;
   867                     break;
   868 
   869                 case SDL_WINDOWEVENT_FOCUS_GAINED:
   870                     event12.type = SDL12_ACTIVEEVENT;
   871                     event12.active.gain = 1;
   872                     event12.active.state = SDL12_APPINPUTFOCUS;
   873                     break;
   874 
   875                 case SDL_WINDOWEVENT_FOCUS_LOST:
   876                     event12.type = SDL12_ACTIVEEVENT;
   877                     event12.active.gain = 0;
   878                     event12.active.state = SDL12_APPINPUTFOCUS;
   879                     break;
   880             }
   881             break;
   882 
   883         // !!! FIXME: this is sort of a mess to convert.
   884         //case SDL_SYSWMEVENT:
   885 
   886         // !!! FIXME: write me
   887         case SDL_KEYDOWN:
   888         case SDL_KEYUP:
   889             return 0;
   890 
   891         // !!! FIXME: write me
   892         case SDL_TEXTEDITING:
   893         case SDL_TEXTINPUT:
   894             return 0;
   895 
   896         case SDL_MOUSEMOTION:
   897         	event12.type = SDL12_MOUSEMOTION;
   898             event12.motion.which = (Uint8) event20->motion.which;
   899             event12.motion.state = event20->motion.state;
   900             event12.motion.x = (Uint16) event20->motion.x;
   901             event12.motion.y = (Uint16) event20->motion.y;
   902             event12.motion.xrel = (Sint16) event20->motion.xrel;
   903             event12.motion.yrel = (Sint16) event20->motion.yrel;
   904             break;
   905 
   906         case SDL_MOUSEBUTTONDOWN:
   907         	event12.type = SDL12_MOUSEBUTTONDOWN;
   908             event12.button.which = (Uint8) event20->button.which;
   909             event12.button.button = event20->button.button;
   910             event12.button.state = event20->button.state;
   911             event12.button.x = (Uint16) event20->button.x;
   912             event12.button.y = (Uint16) event20->button.y;
   913             break;
   914 
   915         case SDL_MOUSEBUTTONUP:
   916         	event12.type = SDL12_MOUSEBUTTONUP;
   917             event12.button.which = (Uint8) event20->button.which;
   918             event12.button.button = event20->button.button;
   919             event12.button.state = event20->button.state;
   920             event12.button.x = (Uint16) event20->button.x;
   921             event12.button.y = (Uint16) event20->button.y;
   922             break;
   923 
   924         case SDL_MOUSEWHEEL:
   925             if (event20->wheel.y == 0)
   926                 break;  /* don't support horizontal wheels in 1.2. */
   927 
   928             event12.type = SDL12_MOUSEBUTTONDOWN;
   929             event12.button.which = (Uint8) event20->wheel.which;
   930             event12.button.button = (event20->wheel.y > 0) ? 4 : 5;  /* wheelup is 4, down is 5. */
   931             event12.button.state = SDL_GetMouseState(&x, &y);
   932             event12.button.x = (Uint16) x;
   933             event12.button.y = (Uint16) y;
   934             PushEventIfNotFiltered(&event12);
   935 
   936             event12.type = SDL12_MOUSEBUTTONUP;  /* immediately release mouse "button" at the end of this switch. */
   937             break;
   938 
   939         case SDL_JOYAXISMOTION:
   940             event12.type = SDL12_JOYAXISMOTION;
   941             event12.jaxis.which = (Uint8) event20->jaxis.which;
   942             event12.jaxis.axis = event20->jaxis.axis;
   943             event12.jaxis.value = event20->jaxis.value;
   944             break;
   945 
   946         case SDL_JOYBALLMOTION:
   947             event12.type = SDL12_JOYBALLMOTION;
   948             event12.jball.which = (Uint8) event20->jball.which;
   949             event12.jball.ball = event20->jball.ball;
   950             event12.jball.xrel = event20->jball.xrel;
   951             event12.jball.yrel = event20->jball.yrel;
   952             break;
   953 
   954         case SDL_JOYHATMOTION:
   955             event12.type = SDL12_JOYHATMOTION;
   956             event12.jhat.which = (Uint8) event20->jhat.which;
   957             event12.jhat.hat = event20->jhat.hat;
   958             event12.jhat.value = event20->jhat.value;
   959             break;
   960 
   961         case SDL_JOYBUTTONDOWN:
   962             event12.type = SDL12_JOYBUTTONDOWN;
   963             event12.jbutton.which = (Uint8) event20->jbutton.which;
   964             event12.jbutton.button = event20->jbutton.button;
   965             event12.jbutton.state = event20->jbutton.state;
   966             break;
   967 
   968         case SDL_JOYBUTTONUP:
   969             event12.type = SDL12_JOYBUTTONUP;
   970             event12.jbutton.which = (Uint8) event20->jbutton.which;
   971             event12.jbutton.button = event20->jbutton.button;
   972             event12.jbutton.state = event20->jbutton.state;
   973             break;
   974 
   975         //case SDL_JOYDEVICEADDED:
   976         //case SDL_JOYDEVICEREMOVED:
   977 	    //case SDL_CONTROLLERAXISMOTION:
   978 	    //case SDL_CONTROLLERBUTTONDOWN:
   979 	    //case SDL_CONTROLLERBUTTONUP:
   980 	    //case SDL_CONTROLLERDEVICEADDED:
   981 	    //case SDL_CONTROLLERDEVICEREMOVED:
   982 	    //case SDL_CONTROLLERDEVICEREMAPPED:
   983         //case SDL_FINGERDOWN:
   984         //case SDL_FINGERUP:
   985         //case SDL_FINGERMOTION:
   986         //case SDL_DOLLARGESTURE:
   987         //case SDL_DOLLARRECORD:
   988         //case SDL_MULTIGESTURE:
   989         //case SDL_CLIPBOARDUPDATE:
   990         //case SDL_DROPFILE:
   991 
   992         default:
   993             return 0;  /* drop everything else. */
   994     }
   995 
   996     PushEventIfNotFiltered(&event12);
   997 
   998     return 0;  /* always drop it from the 2.0 event queue. */
   999 }
  1000 
  1001 void
  1002 SDL_SetEventFilter(SDL12_EventFilter filter12)
  1003 {
  1004     /* We always have a filter installed, but will call the app's too. */
  1005     EventFilter12 = filter12;
  1006 }
  1007 
  1008 SDL12_EventFilter
  1009 SDL_GetEventFilter(void)
  1010 {
  1011     return EventFilter12;
  1012 }
  1013 
  1014 
  1015 static SDL12_Surface *
  1016 Surface20to12(SDL_Surface *surface20)
  1017 {
  1018     SDL12_Surface *surface12 = NULL;
  1019     SDL12_Palette *palette12 = NULL;
  1020     SDL12_PixelFormat *format12 = NULL;
  1021     Uint32 flags = 0;
  1022 
  1023     if (!surface20)
  1024         return NULL;
  1025 
  1026     surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
  1027     if (!surface12)
  1028         goto failed;
  1029 
  1030     palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
  1031     if (!palette12)
  1032         goto failed;
  1033 
  1034     format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
  1035     if (!format12)
  1036         goto failed;
  1037 
  1038     SDL20_zerop(palette12);
  1039     palette12->ncolors = surface20->format->palette->ncolors;
  1040     palette12->colors = surface20->format->palette->colors;
  1041 
  1042     SDL20_zerop(format12);
  1043     format12->palette = palette12;
  1044     format12->BitsPerPixel = surface20->format->BitsPerPixel;
  1045     format12->BytesPerPixel = surface20->format->BytesPerPixel;
  1046     format12->Rloss = surface20->format->Rloss;
  1047     format12->Gloss = surface20->format->Gloss;
  1048     format12->Bloss = surface20->format->Bloss;
  1049     format12->Aloss = surface20->format->Aloss;
  1050     format12->Rshift = surface20->format->Rshift;
  1051     format12->Gshift = surface20->format->Gshift;
  1052     format12->Bshift = surface20->format->Bshift;
  1053     format12->Ashift = surface20->format->Ashift;
  1054     format12->Rmask = surface20->format->Rmask;
  1055     format12->Gmask = surface20->format->Gmask;
  1056     format12->Bmask = surface20->format->Bmask;
  1057     format12->Amask = surface20->format->Amask;
  1058     /* !!! FIXME: format12->colorkey; */
  1059     /* !!! FIXME: format12->alpha; */
  1060 
  1061     SDL20_zerop(surface12);
  1062     flags = surface20->flags;
  1063     #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
  1064     MAPSURFACEFLAGS(PREALLOC);
  1065     MAPSURFACEFLAGS(RLEACCEL);
  1066     /*MAPSURFACEFLAGS(DONTFREE);*/
  1067     #undef MAPSURFACEFLAGS
  1068     SDL_assert(flags == 0);  /* non-zero if there's a flag we didn't map. */
  1069 
  1070     surface12->format = format12;
  1071     surface12->w = surface20->w;
  1072     surface12->h = surface20->h;
  1073     surface12->pitch = (Uint16) surface20->pitch;  /* !!! FIXME: make sure this fits in a Uint16 */
  1074     surface12->pixels = surface20->pixels;
  1075     surface12->offset = 0;
  1076     surface12->surface20 = surface20;
  1077     SDL20_memcpy(&surface12->clip_rect, &surface20->clip_rect, sizeof (SDL_Rect));
  1078     surface12->refcount = surface20->refcount;
  1079 
  1080     return surface12;
  1081 
  1082 failed:
  1083     SDL20_free(surface12);
  1084     SDL20_free(palette12);
  1085     SDL20_free(format12);
  1086     return NULL;
  1087 }
  1088 
  1089 SDL12_Surface *
  1090 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1091 {
  1092     SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
  1093     SDL12_Surface *surface12 = Surface20to12(surface20);
  1094     if (!surface12) {
  1095         SDL20_FreeSurface(surface20);
  1096         return NULL;
  1097     }
  1098 
  1099     SDL_assert(surface12->flags == 0);  // shouldn't have prealloc, rleaccel, or dontfree.
  1100     return surface12;
  1101 }
  1102 
  1103 SDL12_Surface *
  1104 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
  1105 {
  1106     SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
  1107     SDL12_Surface *surface12 = Surface20to12(surface20);
  1108     if (!surface12) {
  1109         SDL20_FreeSurface(surface20);
  1110         return NULL;
  1111     }
  1112 
  1113     SDL_assert(surface12->flags == SDL12_PREALLOC);  // should _only_ have prealloc.
  1114     return surface12;
  1115 }
  1116 
  1117 void SDL_FreeSurface(SDL12_Surface *surface12)
  1118 {
  1119     if (surface12) {
  1120         SDL20_FreeSurface(surface12->surface20);
  1121         if (surface12->format) {
  1122             SDL20_free(surface12->format->palette);
  1123             SDL20_free(surface12->format);
  1124         }
  1125         SDL20_free(surface12);
  1126     }
  1127 }
  1128 
  1129 void
  1130 SDL_GetClipRect(SDL12_Surface *surface12, SDL_Rect *rect)
  1131 {
  1132     if (surface12 && rect)
  1133 	    SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL_Rect));
  1134 }
  1135 
  1136 SDL_bool
  1137 SDL_SetClipRect(SDL12_Surface *surface12, const SDL_Rect *rect)
  1138 {
  1139     SDL_bool retval = SDL_FALSE;
  1140     if (surface12)
  1141     {
  1142         retval = SDL20_SetClipRect(surface12->surface20, rect);
  1143         SDL20_GetClipRect(surface12->surface20, &surface12->clip_rect);
  1144     }
  1145     return retval;
  1146 }
  1147 
  1148 int
  1149 SDL_FillRect(SDL12_Surface *dst, SDL_Rect *dstrect, Uint32 color)
  1150 {
  1151     const SDL_Rect orig_dstrect = *dstrect;
  1152     const int retval = SDL20_FillRect(dst->surface20, &orig_dstrect, color);
  1153     if (retval != -1)
  1154     {
  1155         if (dstrect)  /* 1.2 stores the clip intersection in dstrect */
  1156             SDL20_IntersectRect(&orig_dstrect, &dst->clip_rect, dstrect);
  1157     }
  1158     return retval;
  1159 }
  1160 
  1161 
  1162 static SDL_PixelFormat *
  1163 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
  1164 {
  1165     palette20->ncolors = format12->palette->ncolors;
  1166     palette20->colors = format12->palette->colors;
  1167     palette20->version = 1;
  1168     palette20->refcount = 1;
  1169     format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
  1170     format20->palette = palette20;
  1171     format20->BitsPerPixel = format12->BitsPerPixel;
  1172     format20->BytesPerPixel = format12->BytesPerPixel;
  1173     format20->Rmask = format12->Rmask;
  1174     format20->Gmask = format12->Gmask;
  1175     format20->Bmask = format12->Bmask;
  1176     format20->Amask = format12->Amask;
  1177     format20->Rloss = format12->Rloss;
  1178     format20->Gloss = format12->Gloss;
  1179     format20->Bloss = format12->Bloss;
  1180     format20->Aloss = format12->Aloss;
  1181     format20->Rshift = format12->Rshift;
  1182     format20->Gshift = format12->Gshift;
  1183     format20->Bshift = format12->Bshift;
  1184     format20->Ashift = format12->Ashift;
  1185     format20->refcount = 1;
  1186     format20->next = NULL;
  1187     return format20;
  1188 }
  1189 
  1190 Uint32
  1191 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
  1192 {
  1193     /* This is probably way slower than apps expect. */
  1194     SDL_PixelFormat format20;
  1195     SDL_Palette palette20;
  1196     return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1197 }
  1198 
  1199 Uint32
  1200 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  1201 {
  1202     /* This is probably way slower than apps expect. */
  1203     SDL_PixelFormat format20;
  1204     SDL_Palette palette20;
  1205     return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1206 }
  1207 
  1208 void
  1209 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
  1210 {
  1211     /* This is probably way slower than apps expect. */
  1212     SDL_PixelFormat format20;
  1213     SDL_Palette palette20;
  1214     return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
  1215 }
  1216 
  1217 void
  1218 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
  1219 {
  1220     /* This is probably way slower than apps expect. */
  1221     SDL_PixelFormat format20;
  1222     SDL_Palette palette20;
  1223     return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
  1224 }
  1225 
  1226 const SDL12_VideoInfo *
  1227 SDL_GetVideoInfo(void)
  1228 {
  1229     SDL_DisplayMode mode;
  1230 
  1231     if (!VideoInfo.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
  1232         VideoInfo.vfmt = SDL20_AllocFormat(mode.format);
  1233         VideoInfo.current_w = mode.w;
  1234         VideoInfo.current_h = mode.h;
  1235         // !!! FIXME
  1236         //VideoInfo.wm_available = 1;
  1237         //VideoInfo.video_mem = 1024 * 256;
  1238     }
  1239     return &VideoInfo;
  1240 }
  1241 
  1242 int
  1243 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
  1244 {
  1245     int i, nummodes, actual_bpp = 0;
  1246 
  1247     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1248         return 0;
  1249     }
  1250 
  1251     if (!(sdl12flags & SDL12_FULLSCREEN)) {
  1252         SDL_DisplayMode mode;
  1253         SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
  1254         return SDL_BITSPERPIXEL(mode.format);
  1255     }
  1256 
  1257     nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
  1258     for (i = 0; i < nummodes; ++i) {
  1259         SDL_DisplayMode mode;
  1260         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1261         if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
  1262             if (!mode.format) {
  1263                 return bpp;
  1264             }
  1265             if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
  1266                 actual_bpp = SDL_BITSPERPIXEL(mode.format);
  1267             }
  1268         }
  1269     }
  1270     return actual_bpp;
  1271 }
  1272 
  1273 #if SANITY_CHECK_THIS_CODE
  1274 SDL_Rect **
  1275 SDL_ListModes(const SDL12_PixelFormat *format, Uint32 flags)
  1276 {
  1277     int i, nmodes;
  1278     SDL_Rect **modes;
  1279 
  1280     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1281         return NULL;
  1282     }
  1283 
  1284     if (!(flags & SDL12_FULLSCREEN)) {
  1285         return (SDL_Rect **) (-1);
  1286     }
  1287 
  1288     if (!format) {
  1289         format = VideoInfo.vfmt;
  1290     }
  1291 
  1292     /* !!! FIXME: Memory leak */
  1293     nmodes = 0;
  1294     modes = NULL;
  1295     for (i = 0; i < SDL20_GetNumDisplayModes(VideoDisplayIndex); ++i) {
  1296         SDL_DisplayMode mode;
  1297         int bpp;
  1298 
  1299         SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
  1300         if (!mode.w || !mode.h) {
  1301             return (SDL_Rect **) (-1);
  1302         }
  1303         
  1304         /* Copied from src/video/SDL_pixels.c:SDL_PixelFormatEnumToMasks */
  1305         if (SDL_BYTESPERPIXEL(mode.format) <= 2) {
  1306             bpp = SDL_BITSPERPIXEL(mode.format);
  1307         } else {
  1308             bpp = SDL_BYTESPERPIXEL(mode.format) * 8;
  1309         }
  1310 
  1311         if (bpp != format->BitsPerPixel) {
  1312             continue;
  1313         }
  1314         if (nmodes > 0 && modes[nmodes - 1]->w == mode.w
  1315             && modes[nmodes - 1]->h == mode.h) {
  1316             continue;
  1317         }
  1318 
  1319         modes = SDL20_realloc(modes, (nmodes + 2) * sizeof(*modes));
  1320         if (!modes) {
  1321             return NULL;
  1322         }
  1323         modes[nmodes] = (SDL_Rect *) SDL20_malloc(sizeof(SDL_Rect));
  1324         if (!modes[nmodes]) {
  1325             return NULL;
  1326         }
  1327         modes[nmodes]->x = 0;
  1328         modes[nmodes]->y = 0;
  1329         modes[nmodes]->w = mode.w;
  1330         modes[nmodes]->h = mode.h;
  1331         ++nmodes;
  1332     }
  1333     if (modes) {
  1334         modes[nmodes] = NULL;
  1335     }
  1336     return modes;
  1337 }
  1338 #endif
  1339 
  1340 void
  1341 SDL_FreeCursor(SDL12_Cursor *cursor12)
  1342 {
  1343     if (cursor12)
  1344     {
  1345         if (cursor12->wm_cursor)
  1346             SDL20_FreeCursor(cursor12->wm_cursor);
  1347         SDL20_free(cursor12->data);
  1348         SDL20_free(cursor12->mask);
  1349         SDL20_free(cursor12);
  1350     }
  1351 }
  1352 
  1353 SDL12_Cursor *
  1354 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
  1355 {
  1356     const size_t datasize = h * (w / 8);
  1357     SDL_Cursor *cursor20 = NULL;
  1358     SDL12_Cursor *retval = NULL;
  1359 
  1360     retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
  1361     if (!retval)
  1362         goto outofmem;
  1363 
  1364     SDL20_zerop(retval);
  1365 
  1366     retval->data = (Uint8 *) SDL20_malloc(datasize);
  1367     if (!retval->data)
  1368         goto outofmem;
  1369 
  1370     retval->mask = (Uint8 *) SDL20_malloc(datasize);
  1371     if (!retval->mask)
  1372         goto outofmem;
  1373 
  1374     cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
  1375     if (!cursor20)
  1376         goto failed;
  1377 
  1378     retval->area.w = w;
  1379     retval->area.h = h;
  1380     retval->hot_x = hot_x;
  1381     retval->hot_y = hot_y;
  1382     retval->wm_cursor = cursor20;
  1383     /* we always leave retval->save as null pointers. */
  1384 
  1385     SDL20_memcpy(retval->data, data, datasize);
  1386     SDL20_memcpy(retval->mask, mask, datasize);
  1387 
  1388     return retval;
  1389 
  1390 outofmem:
  1391     SDL20_OutOfMemory();
  1392 
  1393 failed:
  1394     SDL_FreeCursor(retval);
  1395     return NULL;
  1396 }
  1397 
  1398 void
  1399 SDL_SetCursor(SDL12_Cursor *cursor)
  1400 {
  1401     CurrentCursor = cursor;
  1402     SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
  1403 }
  1404 
  1405 SDL12_Cursor *
  1406 SDL_GetCursor(void)
  1407 {
  1408     return CurrentCursor;
  1409 }
  1410 
  1411 static void
  1412 GetEnvironmentWindowPosition(int w, int h, int *x, int *y)
  1413 {
  1414     int display = VideoDisplayIndex;
  1415     const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
  1416     const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
  1417     if (window) {
  1418         if (SDL_sscanf(window, "%d,%d", x, y) == 2) {
  1419             return;
  1420         }
  1421         if (SDL_strcmp(window, "center") == 0) {
  1422             center = window;
  1423         }
  1424     }
  1425     if (center) {
  1426         *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1427         *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
  1428     }
  1429 }
  1430 
  1431 #if SANITY_CHECK_THIS_CODE
  1432 static void
  1433 ClearVideoSurface()
  1434 {
  1435     if (ShadowSurface) {
  1436         SDL20_FillRect(ShadowSurface, NULL,
  1437             SDL20_MapRGB(ShadowSurface->format, 0, 0, 0));
  1438     }
  1439     SDL20_FillRect(WindowSurface, NULL, 0);
  1440     SDL20_UpdateWindowSurface(VideoWindow20);
  1441 }
  1442 #endif
  1443 
  1444 static void
  1445 SetupScreenSaver(int flags12)
  1446 {
  1447     const char *env;
  1448     SDL_bool allow_screensaver;
  1449 
  1450     /* Allow environment override of screensaver disable */
  1451     env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
  1452     if (env) {
  1453         allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
  1454     } else if (flags12 & SDL12_FULLSCREEN) {
  1455         allow_screensaver = SDL_FALSE;
  1456     } else {
  1457         allow_screensaver = SDL_TRUE;
  1458     }
  1459     if (allow_screensaver) {
  1460         SDL20_EnableScreenSaver();
  1461     } else {
  1462         SDL20_DisableScreenSaver();
  1463     }
  1464 }
  1465 
  1466 #if SANITY_CHECK_THIS_CODE
  1467 static int
  1468 ResizeVideoMode(int width, int height, int bpp, Uint32 flags12)
  1469 {
  1470     int w, h;
  1471 
  1472     /* We can't resize something we don't have... */
  1473     if (!VideoSurface) {
  1474         return -1;
  1475     }
  1476 
  1477     /* We probably have to recreate the window in fullscreen mode */
  1478     if (flags12 & SDL12_FULLSCREEN) {
  1479         return -1;
  1480     }
  1481 
  1482     /* I don't think there's any change we can gracefully make in flags */
  1483     if (flags12 != VideoFlags) {
  1484         return -1;
  1485     }
  1486     if (bpp != VideoSurface->format->BitsPerPixel) {
  1487         return -1;
  1488     }
  1489 
  1490     /* Resize the window */
  1491     SDL20_GetWindowSize(VideoWindow20, &w, &h);
  1492     if (w != width || h != height) {
  1493         SDL20_SetWindowSize(VideoWindow20, width, height);
  1494     }
  1495 
  1496     /* If we're in OpenGL mode, just resize the stub surface and we're done! */
  1497     if (flags12 & SDL12_OPENGL) {
  1498         VideoSurface->w = width;
  1499         VideoSurface->h = height;
  1500         return 0;
  1501     }
  1502 
  1503     WindowSurface = SDL20_GetWindowSurface(VideoWindow20);
  1504     if (!WindowSurface) {
  1505         return -1;
  1506     }
  1507     if (VideoSurface->format != WindowSurface->format) {
  1508         return -1;
  1509     }
  1510     VideoSurface->w = width;
  1511     VideoSurface->h = height;
  1512     VideoSurface->pixels = WindowSurface->pixels;
  1513     VideoSurface->pitch = WindowSurface->pitch;
  1514     SDL20_SetClipRect(VideoSurface, NULL);
  1515 
  1516     if (ShadowSurface) {
  1517         ShadowSurface->w = width;
  1518         ShadowSurface->h = height;
  1519         ShadowSurface->pitch = SDL20_CalculatePitch(ShadowSurface);
  1520         ShadowSurface->pixels =
  1521             SDL20_realloc(ShadowSurface->pixels,
  1522                         ShadowSurface->h * ShadowSurface->pitch);
  1523         SDL20_SetClipRect(ShadowSurface, NULL);
  1524         SDL20_InvalidateMap(ShadowSurface->map);
  1525     } else {
  1526         PublicSurface = VideoSurface;
  1527     }
  1528 
  1529     ClearVideoSurface();
  1530 
  1531     return 0;
  1532 }
  1533 
  1534 SDL_Surface *
  1535 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
  1536 {
  1537     SDL_DisplayMode desktop_mode;
  1538     int display = VideoDisplayIndex;
  1539     int window_x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1540     int window_y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(display);
  1541     int window_w;
  1542     int window_h;
  1543     Uint32 window_flags20;
  1544     Uint32 surface_flags12;
  1545 
  1546     if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
  1547         if (SDL_Init(SDL12_INIT_VIDEO | SDL12_INIT_NOPARACHUTE) < 0) {
  1548             return NULL;
  1549         }
  1550     }
  1551 
  1552     SDL20_GetDesktopDisplayMode(display, &desktop_mode);
  1553 
  1554     if (width == 0) {
  1555         width = desktop_mode.w;
  1556     }
  1557     if (height == 0) {
  1558         height = desktop_mode.h;
  1559     }
  1560     if (bpp == 0) {
  1561         bpp = SDL_BITSPERPIXEL(desktop_mode.format);
  1562     }
  1563 
  1564     /* See if we can simply resize the existing window and surface */
  1565     if (ResizeVideoMode(width, height, bpp, flags12) == 0) {
  1566         return PublicSurface;
  1567     }
  1568 
  1569     /* Destroy existing window */
  1570     PublicSurface = NULL;
  1571     if (ShadowSurface) {
  1572         ShadowSurface->flags &= ~SDL_DONTFREE;
  1573         SDL20_FreeSurface(ShadowSurface);
  1574         ShadowSurface = NULL;
  1575     }
  1576     if (VideoSurface) {
  1577         VideoSurface->flags &= ~SDL_DONTFREE;
  1578         SDL20_FreeSurface(VideoSurface);
  1579         VideoSurface = NULL;
  1580     }
  1581     if (VideoContext) {
  1582         /* SDL_GL_MakeCurrent(0, NULL); *//* Doesn't do anything */
  1583         SDL20_GL_DeleteContext(VideoContext);
  1584         VideoContext = NULL;
  1585     }
  1586     if (VideoWindow20) {
  1587         SDL20_GetWindowPosition(VideoWindow20, &window_x, &window_y);
  1588         SDL20_DestroyWindow(VideoWindow20);
  1589     }
  1590 
  1591     /* Create a new window */
  1592     window_flags20 = SDL_WINDOW_SHOWN;
  1593     if (flags12 & SDL12_FULLSCREEN) {
  1594         window_flags20 |= SDL_WINDOW_FULLSCREEN;
  1595     }
  1596     if (flags12 & SDL12_OPENGL) {
  1597         window_flags20 |= SDL_WINDOW_OPENGL;
  1598     }
  1599     if (flags12 & SDL12_RESIZABLE) {
  1600         window_flags20 |= SDL_WINDOW_RESIZABLE;
  1601     }
  1602     if (flags12 & SDL12_NOFRAME) {
  1603         window_flags20 |= SDL_WINDOW_BORDERLESS;
  1604     }
  1605     GetEnvironmentWindowPosition(width, height, &window_x, &window_y);
  1606     VideoWindow20 =
  1607         SDL20_CreateWindow(WindowTitle, window_x, window_y, width, height,
  1608                          window_flags20);
  1609     if (!VideoWindow20) {
  1610         return NULL;
  1611     }
  1612     SDL20_SetWindowIcon(VideoWindow20, VideoIcon);
  1613 
  1614     SetupScreenSaver(flags12);
  1615 
  1616     window_flags20 = SDL20_GetWindowFlags(VideoWindow20);
  1617     surface_flags12 = 0;
  1618     if (window_flags20 & SDL_WINDOW_FULLSCREEN) {
  1619         surface_flags12 |= SDL_FULLSCREEN;
  1620     }
  1621     if ((window_flags & SDL_WINDOW_OPENGL) && (flags12 & SDL_OPENGL)) {
  1622         surface_flags12 |= SDL_OPENGL;
  1623     }
  1624     if (window_flags & SDL_WINDOW_RESIZABLE) {
  1625         surface_flags12 |= SDL_RESIZABLE;
  1626     }
  1627     if (window_flags & SDL_WINDOW_BORDERLESS) {
  1628         surface_flags12 |= SDL_NOFRAME;
  1629     }
  1630 
  1631     VideoFlags = flags12;
  1632 
  1633     /* If we're in OpenGL mode, just create a stub surface and we're done! */
  1634     if (flags12 & SDL_OPENGL) {
  1635 
  1636         VideoContext = SDL_GL_CreateContext(VideoWindow20);
  1637         if (!VideoContext) {
  1638             return NULL;
  1639         }
  1640         if (SDL_GL_MakeCurrent(VideoWindow20, VideoContext) < 0) {
  1641             return NULL;
  1642         }
  1643 
  1644         SDL20_GL_SetSwapInterval(SwapInterval);  /* don't care if this fails. */
  1645 
  1646         VideoSurface =
  1647             SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
  1648         if (!VideoSurface) {
  1649             return NULL;
  1650         }
  1651         VideoSurface->flags |= surface_flags12;
  1652         PublicSurface = VideoSurface;
  1653         return PublicSurface;
  1654     }
  1655 
  1656     /* Create the screen surface */
  1657     WindowSurface = SDL_GetWindowSurface(VideoWindow20);
  1658     if (!WindowSurface) {
  1659         return NULL;
  1660     }
  1661 
  1662     /* Center the public surface in the window surface */
  1663     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1664     VideoViewport.x = (window_w - width)/2;
  1665     VideoViewport.y = (window_h - height)/2;
  1666     VideoViewport.w = width;
  1667     VideoViewport.h = height;
  1668 
  1669     VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1670     VideoSurface->flags |= surface_flags12;
  1671     VideoSurface->flags |= SDL12_DONTFREE;
  1672     SDL_FreeFormat(VideoSurface->format);
  1673     VideoSurface->format = WindowSurface->format;
  1674     VideoSurface->format->refcount++;
  1675     VideoSurface->w = width;
  1676     VideoSurface->h = height;
  1677     VideoSurface->pitch = WindowSurface->pitch;
  1678     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  1679         VideoViewport.y * VideoSurface->pitch +
  1680         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  1681     SDL_SetClipRect(VideoSurface, NULL);
  1682 
  1683     /* Create a shadow surface if necessary */
  1684     if ((bpp != VideoSurface->format->BitsPerPixel)
  1685         && !(flags12 & SDL12_ANYFORMAT)) {
  1686         ShadowSurface =
  1687             SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0);
  1688         if (!ShadowSurface) {
  1689             return NULL;
  1690         }
  1691         ShadowSurface->flags |= surface_flags12;
  1692         ShadowSurface->flags |= SDL12_DONTFREE;
  1693 
  1694         /* 8-bit ShadowSurface surfaces report that they have exclusive palette */
  1695         if (ShadowSurface->format->palette) {
  1696             ShadowSurface->flags |= SDL12_HWPALETTE;
  1697             SDL_DitherColors(ShadowSurface->format->palette->colors,
  1698                              ShadowSurface->format->BitsPerPixel);
  1699         }
  1700         SDL_FillRect(ShadowSurface, NULL,
  1701             SDL_MapRGB(ShadowSurface->format, 0, 0, 0));
  1702     }
  1703     PublicSurface =
  1704         (ShadowSurface ? ShadowSurface : VideoSurface);
  1705 
  1706     ClearVideoSurface();
  1707 
  1708     /* We're finally done! */
  1709     return PublicSurface;
  1710 }
  1711 
  1712 SDL_Surface *
  1713 SDL_GetVideoSurface(void)
  1714 {
  1715     return PublicSurface;
  1716 }
  1717 
  1718 int
  1719 SDL_SetAlpha(SDL_Surface * surface, Uint32 flag, Uint8 value)
  1720 {
  1721     if (flag & SDL_SRCALPHA) {
  1722         /* According to the docs, value is ignored for alpha surfaces */
  1723         if (surface->format->Amask) {
  1724             value = 0xFF;
  1725         }
  1726         SDL_SetSurfaceAlphaMod(surface, value);
  1727         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
  1728     } else {
  1729         SDL_SetSurfaceAlphaMod(surface, 0xFF);
  1730         SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
  1731     }
  1732     SDL_SetSurfaceRLE(surface, (flag & SDL_RLEACCEL));
  1733 
  1734     return 0;
  1735 }
  1736 
  1737 SDL12_Surface *
  1738 SDL_DisplayFormat(SDL12_Surface *surface12)
  1739 {
  1740     SDL12_PixelFormat *format;
  1741 
  1742     if (!PublicSurface) {
  1743         SDL20_SetError("No video mode has been set");
  1744         return NULL;
  1745     }
  1746     format = PublicSurface->format;
  1747 
  1748     /* Set the flags appropriate for copying to display surface */
  1749     return SDL_ConvertSurface(surface, format, SDL12_RLEACCEL);
  1750 }
  1751 
  1752 SDL12_Surface *
  1753 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
  1754 {
  1755     SDL_PixelFormat *vf;
  1756     SDL_PixelFormat *format;
  1757     SDL_Surface *converted;
  1758     /* default to ARGB8888 */
  1759     Uint32 amask = 0xff000000;
  1760     Uint32 rmask = 0x00ff0000;
  1761     Uint32 gmask = 0x0000ff00;
  1762     Uint32 bmask = 0x000000ff;
  1763 
  1764     if (!PublicSurface) {
  1765         SDL20_SetError("No video mode has been set");
  1766         return NULL;
  1767     }
  1768     vf = PublicSurface->format;
  1769 
  1770     switch (vf->BytesPerPixel) {
  1771     case 2:
  1772         /* For XGY5[56]5, use, AXGY8888, where {X, Y} = {R, B}.
  1773            For anything else (like ARGB4444) it doesn't matter
  1774            since we have no special code for it anyway */
  1775         if ((vf->Rmask == 0x1f) &&
  1776             (vf->Bmask == 0xf800 || vf->Bmask == 0x7c00)) {
  1777             rmask = 0xff;
  1778             bmask = 0xff0000;
  1779         }
  1780         break;
  1781 
  1782     case 3:
  1783     case 4:
  1784         /* Keep the video format, as long as the high 8 bits are
  1785            unused or alpha */
  1786         if ((vf->Rmask == 0xff) && (vf->Bmask == 0xff0000)) {
  1787             rmask = 0xff;
  1788             bmask = 0xff0000;
  1789         }
  1790         break;
  1791 
  1792     default:
  1793         /* We have no other optimised formats right now. When/if a new
  1794            optimised alpha format is written, add the converter here */
  1795         break;
  1796     }
  1797     format = SDL_AllocFormat(SDL_MasksToPixelFormatEnum(32, rmask,
  1798                                                             gmask,
  1799                                                             bmask,
  1800                                                             amask));
  1801     if (!format) {
  1802         return NULL;
  1803     }
  1804     converted = SDL_ConvertSurface(surface, format, SDL_RLEACCEL);
  1805     SDL_FreeFormat(format);
  1806     return converted;
  1807 }
  1808 
  1809 void
  1810 SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects)
  1811 {
  1812     int i;
  1813 
  1814     if (screen == ShadowSurface) {
  1815         for (i = 0; i < numrects; ++i) {
  1816             SDL_BlitSurface(ShadowSurface, &rects[i], VideoSurface,
  1817                             &rects[i]);
  1818         }
  1819 
  1820         /* Fall through to video surface update */
  1821         screen = VideoSurface;
  1822     }
  1823     if (screen == VideoSurface) {
  1824         if (VideoViewport.x || VideoViewport.y) {
  1825             SDL_Rect *stackrects = SDL_stack_alloc(SDL_Rect, numrects);
  1826             SDL_Rect *stackrect;
  1827             const SDL_Rect *rect;
  1828             
  1829             /* Offset all the rectangles before updating */
  1830             for (i = 0; i < numrects; ++i) {
  1831                 rect = &rects[i];
  1832                 stackrect = &stackrects[i];
  1833                 stackrect->x = VideoViewport.x + rect->x;
  1834                 stackrect->y = VideoViewport.y + rect->y;
  1835                 stackrect->w = rect->w;
  1836                 stackrect->h = rect->h;
  1837             }
  1838             SDL_UpdateWindowSurfaceRects(VideoWindow20, stackrects, numrects);
  1839             SDL_stack_free(stackrects);
  1840         } else {
  1841             SDL_UpdateWindowSurfaceRects(VideoWindow20, rects, numrects);
  1842         }
  1843     }
  1844 }
  1845 #endif
  1846 
  1847 void
  1848 SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
  1849 {
  1850     if (screen) {
  1851         SDL_Rect rect;
  1852         rect.x = (int) x;
  1853         rect.y = (int) y;
  1854         rect.w = (int) (w ? w : screen->w);
  1855         rect.h = (int) (h ? h : screen->h);
  1856         SDL_UpdateRects(screen, 1, &rect);
  1857     }
  1858 }
  1859 
  1860 int
  1861 SDL_Flip(SDL_Surface * screen)
  1862 {
  1863     SDL_UpdateRect(screen, 0, 0, 0, 0);
  1864     return 0;
  1865 }
  1866 
  1867 void
  1868 SDL_WM_SetCaption(const char *title, const char *icon)
  1869 {
  1870     if (WindowTitle) {
  1871         SDL20_free(WindowTitle);
  1872     }
  1873     if (WindowIconTitle) {
  1874         SDL20_free(WindowIconTitle);
  1875     }
  1876     WindowTitle = title ? SDL_strdup(title) : NULL;
  1877     WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
  1878     SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
  1879 }
  1880 
  1881 void
  1882 SDL_WM_GetCaption(const char **title, const char **icon)
  1883 {
  1884     if (title) {
  1885         *title = WindowTitle;
  1886     }
  1887     if (icon) {
  1888         *icon = WindowIconTitle;
  1889     }
  1890 }
  1891 
  1892 #if SANITY_CHECK_THIS_CODE
  1893 void
  1894 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
  1895 {
  1896     // !!! FIXME: free previous icon?
  1897     VideoIcon = icon;
  1898     ++VideoIcon->refcount;
  1899 }
  1900 #endif
  1901 
  1902 int
  1903 SDL_WM_IconifyWindow(void)
  1904 {
  1905     SDL20_MinimizeWindow(VideoWindow20);
  1906     return 0;
  1907 }
  1908 
  1909 #if SANITY_CHECK_THIS_CODE
  1910 int
  1911 SDL_WM_ToggleFullScreen(SDL_Surface *surface)
  1912 {
  1913     int length;
  1914     void *pixels;
  1915     Uint8 *src, *dst;
  1916     int row;
  1917     int window_w;
  1918     int window_h;
  1919 
  1920     if (!PublicSurface) {
  1921         SDL20_SetError("SDL_SetVideoMode() hasn't been called");
  1922         return 0;
  1923     }
  1924 
  1925     /* Copy the old bits out */
  1926     length = PublicSurface->w * PublicSurface->format->BytesPerPixel;
  1927     pixels = SDL20_malloc(PublicSurface->h * length);
  1928     if (pixels && PublicSurface->pixels) {
  1929         src = (Uint8*)PublicSurface->pixels;
  1930         dst = (Uint8*)pixels;
  1931         for (row = 0; row < PublicSurface->h; ++row) {
  1932             SDL_memcpy(dst, src, length);
  1933             src += PublicSurface->pitch;
  1934             dst += length;
  1935         }
  1936     }
  1937 
  1938     /* Do the physical mode switch */
  1939     if (SDL20_GetWindowFlags(VideoWindow20) & SDL_WINDOW_FULLSCREEN) {
  1940         if (SDL20_SetWindowFullscreen(VideoWindow20, 0) < 0) {
  1941             return 0;
  1942         }
  1943         PublicSurface->flags &= ~SDL_FULLSCREEN;
  1944     } else {
  1945         if (SDL20_SetWindowFullscreen(VideoWindow20, 1) < 0) {
  1946             return 0;
  1947         }
  1948         PublicSurface->flags |= SDL_FULLSCREEN;
  1949     }
  1950 
  1951     /* Recreate the screen surface */
  1952     WindowSurface = SDL20_GetWindowSurface(VideoWindow20);
  1953     if (!WindowSurface) {
  1954         /* We're totally hosed... */
  1955         return 0;
  1956     }
  1957 
  1958     /* Center the public surface in the window surface */
  1959     SDL_GetWindowSize(VideoWindow20, &window_w, &window_h);
  1960     VideoViewport.x = (window_w - VideoSurface->w)/2;
  1961     VideoViewport.y = (window_h - VideoSurface->h)/2;
  1962     VideoViewport.w = VideoSurface->w;
  1963     VideoViewport.h = VideoSurface->h;
  1964 
  1965     /* Do some shuffling behind the application's back if format changes */
  1966     if (VideoSurface->format->format != WindowSurface->format->format) {
  1967         if (ShadowSurface) {
  1968             if (ShadowSurface->format->format == WindowSurface->format->format) {
  1969                 /* Whee!  We don't need a shadow surface anymore! */
  1970                 VideoSurface->flags &= ~SDL_DONTFREE;
  1971                 SDL_FreeSurface(VideoSurface);
  1972                 SDL20_free(ShadowSurface->pixels);
  1973                 VideoSurface = ShadowSurface;
  1974                 VideoSurface->flags |= SDL_PREALLOC;
  1975                 ShadowSurface = NULL;
  1976             } else {
  1977                 /* No problem, just change the video surface format */
  1978                 SDL_FreeFormat(VideoSurface->format);
  1979                 VideoSurface->format = WindowSurface->format;
  1980                 VideoSurface->format->refcount++;
  1981                 SDL_InvalidateMap(ShadowSurface->map);
  1982             }
  1983         } else {
  1984             /* We can make the video surface the shadow surface */
  1985             ShadowSurface = VideoSurface;
  1986             ShadowSurface->pitch = SDL_CalculatePitch(ShadowSurface);
  1987             ShadowSurface->pixels = SDL20_malloc(ShadowSurface->h * ShadowSurface->pitch);
  1988             if (!ShadowSurface->pixels) {
  1989                 /* Uh oh, we're hosed */
  1990                 ShadowSurface = NULL;
  1991                 return 0;
  1992             }
  1993             ShadowSurface->flags &= ~SDL_PREALLOC;
  1994 
  1995             VideoSurface = SDL_CreateRGBSurfaceFrom(NULL, 0, 0, 32, 0, 0, 0, 0, 0);
  1996             VideoSurface->flags = ShadowSurface->flags;
  1997             VideoSurface->flags |= SDL_PREALLOC;
  1998             SDL_FreeFormat(VideoSurface->format);
  1999             VideoSurface->format = WindowSurface->format;
  2000             VideoSurface->format->refcount++;
  2001             VideoSurface->w = ShadowSurface->w;
  2002             VideoSurface->h = ShadowSurface->h;
  2003         }
  2004     }
  2005 
  2006     /* Update the video surface */
  2007     VideoSurface->pitch = WindowSurface->pitch;
  2008     VideoSurface->pixels = (void *)((Uint8 *)WindowSurface->pixels +
  2009         VideoViewport.y * VideoSurface->pitch +
  2010         VideoViewport.x  * VideoSurface->format->BytesPerPixel);
  2011     SDL_SetClipRect(VideoSurface, NULL);
  2012 
  2013     /* Copy the old bits back */
  2014     if (pixels) {
  2015         src = (Uint8*)pixels;
  2016         dst = (Uint8*)PublicSurface->pixels;
  2017         for (row = 0; row < PublicSurface->h; ++row) {
  2018             SDL_memcpy(dst, src, length);
  2019             src += length;
  2020             dst += PublicSurface->pitch;
  2021         }
  2022         SDL_Flip(PublicSurface);
  2023         SDL20_free(pixels);
  2024     }
  2025 
  2026     /* We're done! */
  2027     return 1;
  2028 }
  2029 #endif
  2030 
  2031 typedef enum
  2032 {
  2033     SDL12_GRAB_QUERY = -1,
  2034     SDL12_GRAB_OFF = 0,
  2035     SDL12_GRAB_ON = 1
  2036 } SDL12_GrabMode;
  2037 
  2038 SDL12_GrabMode
  2039 SDL_WM_GrabInput(SDL12_GrabMode mode)
  2040 {
  2041     if (mode != SDL12_GRAB_QUERY) {
  2042         SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
  2043     }
  2044     return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
  2045 }
  2046 
  2047 Uint8
  2048 SDL_GetMouseState(int *x, int *y)
  2049 {
  2050     const Uint32 state20 = SDL20_GetMouseState(x, y);
  2051     Uint8 retval = (state20 & 0x7);  /* left, right, and middle will match. */
  2052 
  2053     /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
  2054     if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
  2055         retval |= (1<<5);
  2056     if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
  2057         retval |= (1<<6);
  2058 
  2059     return retval;
  2060 }
  2061 
  2062 void
  2063 SDL_WarpMouse(Uint16 x, Uint16 y)
  2064 {
  2065     SDL20_WarpMouseInWindow(VideoWindow20, x, y);
  2066 }
  2067 
  2068 Uint8
  2069 SDL_GetAppState(void)
  2070 {
  2071     Uint8 state12 = 0;
  2072     Uint32 flags20 = 0;
  2073 
  2074     flags20 = SDL20_GetWindowFlags(VideoWindow20);
  2075     if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
  2076         state12 |= SDL12_APPACTIVE;
  2077     }
  2078     if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
  2079         state12 |= SDL12_APPINPUTFOCUS;
  2080     }
  2081     if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
  2082         state12 |= SDL12_APPMOUSEFOCUS;
  2083     }
  2084     return state12;
  2085 }
  2086 
  2087 #if SANITY_CHECK_THIS_CODE
  2088 int
  2089 SDL_SetPalette(SDL_Surface * surface, int flags, const SDL_Color * colors,
  2090                int firstcolor, int ncolors)
  2091 {
  2092     return SDL_SetColors(surface, colors, firstcolor, ncolors);
  2093 }
  2094 
  2095 int
  2096 SDL_SetColors(SDL_Surface * surface, const SDL_Color * colors, int firstcolor,
  2097               int ncolors)
  2098 {
  2099     if (SDL_SetPaletteColors
  2100         (surface->format->palette, colors, firstcolor, ncolors) == 0) {
  2101         return 1;
  2102     } else {
  2103         return 0;
  2104     }
  2105 }
  2106 
  2107 int
  2108 SDL_GetWMInfo(SDL_SysWMinfo * info)
  2109 {
  2110     return SDL_GetWindowWMInfo(VideoWindow20, info);
  2111 }
  2112 
  2113 #if 0
  2114 void
  2115 SDL_MoveCursor(int x, int y)
  2116 {
  2117     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2118 
  2119     /* Erase and update the current mouse position */
  2120     if (SHOULD_DRAWCURSOR(SDL_cursorstate)) {
  2121         /* Erase and redraw mouse cursor in new position */
  2122         SDL_LockCursor();
  2123         SDL_EraseCursor(VideoSurface);
  2124         SDL_cursor->area.x = (x - SDL_cursor->hot_x);
  2125         SDL_cursor->area.y = (y - SDL_cursor->hot_y);
  2126         SDL_DrawCursor(VideoSurface);
  2127         SDL_UnlockCursor();
  2128     } else if (_this->MoveWMCursor) {
  2129         _this->MoveWMCursor(_this, x, y);
  2130     }
  2131 }
  2132 
  2133 /* Keep track of the current cursor colors */
  2134 static int palette_changed = 1;
  2135 static Uint8 pixels8[2];
  2136 
  2137 void
  2138 SDL_CursorPaletteChanged(void)
  2139 {
  2140     palette_changed = 1;
  2141 }
  2142 
  2143 void
  2144 SDL_MouseRect(SDL_Rect * area)
  2145 {
  2146     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2147     int clip_diff;
  2148 
  2149     *area = SDL_cursor->area;
  2150     if (area->x < 0) {
  2151         area->w += area->x;
  2152         area->x = 0;
  2153     }
  2154     if (area->y < 0) {
  2155         area->h += area->y;
  2156         area->y = 0;
  2157     }
  2158     clip_diff = (area->x + area->w) - VideoSurface->w;
  2159     if (clip_diff > 0) {
  2160         area->w = area->w < clip_diff ? 0 : area->w - clip_diff;
  2161     }
  2162     clip_diff = (area->y + area->h) - VideoSurface->h;
  2163     if (clip_diff > 0) {
  2164         area->h = area->h < clip_diff ? 0 : area->h - clip_diff;
  2165     }
  2166 }
  2167 
  2168 static void
  2169 SDL_DrawCursorFast(SDL_Surface * screen, SDL_Rect * area)
  2170 {
  2171     const Uint32 pixels[2] = { 0xFFFFFFFF, 0x00000000 };
  2172     int i, w, h;
  2173     Uint8 *data, datab;
  2174     Uint8 *mask, maskb;
  2175 
  2176     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  2177     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  2178     switch (screen->format->BytesPerPixel) {
  2179 
  2180     case 1:
  2181         {
  2182             Uint8 *dst;
  2183             int dstskip;
  2184 
  2185             if (palette_changed) {
  2186                 pixels8[0] =
  2187                     (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  2188                 pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  2189                 palette_changed = 0;
  2190             }
  2191             dst = (Uint8 *) screen->pixels +
  2192                 (SDL_cursor->area.y + area->y) * screen->pitch +
  2193                 SDL_cursor->area.x;
  2194             dstskip = screen->pitch - area->w;
  2195 
  2196             for (h = area->h; h; h--) {
  2197                 for (w = area->w / 8; w; w--) {
  2198                     maskb = *mask++;
  2199                     datab = *data++;
  2200                     for (i = 0; i < 8; ++i) {
  2201                         if (maskb & 0x80) {
  2202                             *dst = pixels8[datab >> 7];
  2203                         }
  2204                         maskb <<= 1;
  2205                         datab <<= 1;
  2206                         dst++;
  2207                     }
  2208                 }
  2209                 dst += dstskip;
  2210             }
  2211         }
  2212         break;
  2213 
  2214     case 2:
  2215         {
  2216             Uint16 *dst;
  2217             int dstskip;
  2218 
  2219             dst = (Uint16 *) screen->pixels +
  2220                 (SDL_cursor->area.y + area->y) * screen->pitch / 2 +
  2221                 SDL_cursor->area.x;
  2222             dstskip = (screen->pitch / 2) - area->w;
  2223 
  2224             for (h = area->h; h; h--) {
  2225                 for (w = area->w / 8; w; w--) {
  2226                     maskb = *mask++;
  2227                     datab = *data++;
  2228                     for (i = 0; i < 8; ++i) {
  2229                         if (maskb & 0x80) {
  2230                             *dst = (Uint16) pixels[datab >> 7];
  2231                         }
  2232                         maskb <<= 1;
  2233                         datab <<= 1;
  2234                         dst++;
  2235                     }
  2236                 }
  2237                 dst += dstskip;
  2238             }
  2239         }
  2240         break;
  2241 
  2242     case 3:
  2243         {
  2244             Uint8 *dst;
  2245             int dstskip;
  2246 
  2247             dst = (Uint8 *) screen->pixels +
  2248                 (SDL_cursor->area.y + area->y) * screen->pitch +
  2249                 SDL_cursor->area.x * 3;
  2250             dstskip = screen->pitch - area->w * 3;
  2251 
  2252             for (h = area->h; h; h--) {
  2253                 for (w = area->w / 8; w; w--) {
  2254                     maskb = *mask++;
  2255                     datab = *data++;
  2256                     for (i = 0; i < 8; ++i) {
  2257                         if (maskb & 0x80) {
  2258                             SDL_memset(dst, pixels[datab >> 7], 3);
  2259                         }
  2260                         maskb <<= 1;
  2261                         datab <<= 1;
  2262                         dst += 3;
  2263                     }
  2264                 }
  2265                 dst += dstskip;
  2266             }
  2267         }
  2268         break;
  2269 
  2270     case 4:
  2271         {
  2272             Uint32 *dst;
  2273             int dstskip;
  2274 
  2275             dst = (Uint32 *) screen->pixels +
  2276                 (SDL_cursor->area.y + area->y) * screen->pitch / 4 +
  2277                 SDL_cursor->area.x;
  2278             dstskip = (screen->pitch / 4) - area->w;
  2279 
  2280             for (h = area->h; h; h--) {
  2281                 for (w = area->w / 8; w; w--) {
  2282                     maskb = *mask++;
  2283                     datab = *data++;
  2284                     for (i = 0; i < 8; ++i) {
  2285                         if (maskb & 0x80) {
  2286                             *dst = pixels[datab >> 7];
  2287                         }
  2288                         maskb <<= 1;
  2289                         datab <<= 1;
  2290                         dst++;
  2291                     }
  2292                 }
  2293                 dst += dstskip;
  2294             }
  2295         }
  2296         break;
  2297     }
  2298 }
  2299 
  2300 static void
  2301 SDL_DrawCursorSlow(SDL_Surface * screen, SDL_Rect * area)
  2302 {
  2303     const Uint32 pixels[2] = { 0xFFFFFF, 0x000000 };
  2304     int h;
  2305     int x, minx, maxx;
  2306     Uint8 *data, datab = 0;
  2307     Uint8 *mask, maskb = 0;
  2308     Uint8 *dst;
  2309     int dstbpp, dstskip;
  2310 
  2311     data = SDL_cursor->data + area->y * SDL_cursor->area.w / 8;
  2312     mask = SDL_cursor->mask + area->y * SDL_cursor->area.w / 8;
  2313     dstbpp = screen->format->BytesPerPixel;
  2314     dst = (Uint8 *) screen->pixels +
  2315         (SDL_cursor->area.y + area->y) * screen->pitch +
  2316         SDL_cursor->area.x * dstbpp;
  2317     dstskip = screen->pitch - SDL_cursor->area.w * dstbpp;
  2318 
  2319     minx = area->x;
  2320     maxx = area->x + area->w;
  2321     if (screen->format->BytesPerPixel == 1) {
  2322         if (palette_changed) {
  2323             pixels8[0] = (Uint8) SDL_MapRGB(screen->format, 255, 255, 255);
  2324             pixels8[1] = (Uint8) SDL_MapRGB(screen->format, 0, 0, 0);
  2325             palette_changed = 0;
  2326         }
  2327         for (h = area->h; h; h--) {
  2328             for (x = 0; x < SDL_cursor->area.w; ++x) {
  2329                 if ((x % 8) == 0) {
  2330                     maskb = *mask++;
  2331                     datab = *data++;
  2332                 }
  2333                 if ((x >= minx) && (x < maxx)) {
  2334                     if (maskb & 0x80) {
  2335                         SDL_memset(dst, pixels8[datab >> 7], dstbpp);
  2336                     }
  2337                 }
  2338                 maskb <<= 1;
  2339                 datab <<= 1;
  2340                 dst += dstbpp;
  2341             }
  2342             dst += dstskip;
  2343         }
  2344     } else {
  2345         for (h = area->h; h; h--) {
  2346             for (x = 0; x < SDL_cursor->area.w; ++x) {
  2347                 if ((x % 8) == 0) {
  2348                     maskb = *mask++;
  2349                     datab = *data++;
  2350                 }
  2351                 if ((x >= minx) && (x < maxx)) {
  2352                     if (maskb & 0x80) {
  2353                         SDL_memset(dst, pixels[datab >> 7], dstbpp);
  2354                     }
  2355                 }
  2356                 maskb <<= 1;
  2357                 datab <<= 1;
  2358                 dst += dstbpp;
  2359             }
  2360             dst += dstskip;
  2361         }
  2362     }
  2363 }
  2364 
  2365 /* This handles the ugly work of converting the saved cursor background from
  2366    the pixel format of the shadow surface to that of the video surface.
  2367    This is only necessary when blitting from a shadow surface of a different
  2368    pixel format than the video surface, and using a software rendered cursor.
  2369 */
  2370 static void
  2371 SDL_ConvertCursorSave(SDL_Surface * screen, int w, int h)
  2372 {
  2373     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2374     SDL_BlitInfo info;
  2375     SDL_loblit RunBlit;
  2376 
  2377     /* Make sure we can steal the blit mapping */
  2378     if (screen->map->dst != VideoSurface) {
  2379         return;
  2380     }
  2381 
  2382     /* Set up the blit information */
  2383     info.s_pixels = SDL_cursor->save[1];
  2384     info.s_width = w;
  2385     info.s_height = h;
  2386     info.s_skip = 0;
  2387     info.d_pixels = SDL_cursor->save[0];
  2388     info.d_width = w;
  2389     info.d_height = h;
  2390     info.d_skip = 0;
  2391     info.aux_data = screen->map->sw_data->aux_data;
  2392     info.src = screen->format;
  2393     info.table = screen->map->table;
  2394     info.dst = VideoSurface->format;
  2395     RunBlit = screen->map->sw_data->blit;
  2396 
  2397     /* Run the actual software blit */
  2398     RunBlit(&info);
  2399 }
  2400 
  2401 void
  2402 SDL_DrawCursorNoLock(SDL_Surface * screen)
  2403 {
  2404     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2405     SDL_Rect area;
  2406 
  2407     /* Get the mouse rectangle, clipped to the screen */
  2408     SDL_MouseRect(&area);
  2409     if ((area.w == 0) || (area.h == 0)) {
  2410         return;
  2411     }
  2412 
  2413     /* Copy mouse background */
  2414     {
  2415         int w, h, screenbpp;
  2416         Uint8 *src, *dst;
  2417 
  2418         /* Set up the copy pointers */
  2419         screenbpp = screen->format->BytesPerPixel;
  2420         if ((screen == VideoSurface) ||
  2421             FORMAT_EQUAL(screen->format, VideoSurface->format)) {
  2422             dst = SDL_cursor->save[0];
  2423         } else {
  2424             dst = SDL_cursor->save[1];
  2425         }
  2426         src = (Uint8 *) screen->pixels + area.y * screen->pitch +
  2427             area.x * screenbpp;
  2428 
  2429         /* Perform the copy */
  2430         w = area.w * screenbpp;
  2431         h = area.h;
  2432         while (h--) {
  2433             SDL_memcpy(dst, src, w);
  2434             dst += w;
  2435             src += screen->pitch;
  2436         }
  2437     }
  2438 
  2439     /* Draw the mouse cursor */
  2440     area.x -= SDL_cursor->area.x;
  2441     area.y -= SDL_cursor->area.y;
  2442     if ((area.x == 0) && (area.w == SDL_cursor->area.w)) {
  2443         SDL_DrawCursorFast(screen, &area);
  2444     } else {
  2445         SDL_DrawCursorSlow(screen, &area);
  2446     }
  2447 }
  2448 
  2449 void
  2450 SDL_DrawCursor(SDL_Surface * screen)
  2451 {
  2452     /* Lock the screen if necessary */
  2453     if (screen == NULL) {
  2454         return;
  2455     }
  2456     if (SDL_MUSTLOCK(screen)) {
  2457         if (SDL_LockSurface(screen) < 0) {
  2458             return;
  2459         }
  2460     }
  2461 
  2462     SDL_DrawCursorNoLock(screen);
  2463 
  2464     /* Unlock the screen and update if necessary */
  2465     if (SDL_MUSTLOCK(screen)) {
  2466         SDL_UnlockSurface(screen);
  2467     }
  2468     if (screen->flags & SDL_SCREEN_SURFACE) {
  2469         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2470         SDL_Window *window;
  2471         SDL_Rect area;
  2472 
  2473         window = SDL_GetWindowFromSurface(screen);
  2474         if (!window) {
  2475             return;
  2476         }
  2477 
  2478         SDL_MouseRect(&area);
  2479 
  2480         if (_this->UpdateWindowSurface) {
  2481             _this->UpdateWindowSurface(_this, window, 1, &area);
  2482         }
  2483     }
  2484 }
  2485 
  2486 void
  2487 SDL_EraseCursorNoLock(SDL_Surface * screen)
  2488 {
  2489     SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2490     SDL_Window *window;
  2491     SDL_Rect area;
  2492 
  2493     /* Get the window associated with the surface */
  2494     window = SDL_GetWindowFromSurface(screen);
  2495     if (!window || !window->surface) {
  2496         return;
  2497     }
  2498 
  2499     /* Get the mouse rectangle, clipped to the screen */
  2500     SDL_MouseRect(&area);
  2501     if ((area.w == 0) || (area.h == 0)) {
  2502         return;
  2503     }
  2504 
  2505     /* Copy mouse background */
  2506     {
  2507         int w, h, screenbpp;
  2508         Uint8 *src, *dst;
  2509 
  2510         /* Set up the copy pointers */
  2511         screenbpp = screen->format->BytesPerPixel;
  2512         if ((screen->flags & SDL_SCREEN_SURFACE) ||
  2513             FORMAT_EQUAL(screen->format, window->surface->format)) {
  2514             src = SDL_cursor->save[0];
  2515         } else {
  2516             src = SDL_cursor->save[1];
  2517         }
  2518         dst = (Uint8 *) screen->pixels + area.y * screen->pitch +
  2519             area.x * screenbpp;
  2520 
  2521         /* Perform the copy */
  2522         w = area.w * screenbpp;
  2523         h = area.h;
  2524         while (h--) {
  2525             SDL_memcpy(dst, src, w);
  2526             src += w;
  2527             dst += screen->pitch;
  2528         }
  2529 
  2530         /* Perform pixel conversion on cursor background */
  2531         if (src > SDL_cursor->save[1]) {
  2532             SDL_ConvertCursorSave(screen, area.w, area.h);
  2533         }
  2534     }
  2535 }
  2536 
  2537 void
  2538 SDL_EraseCursor(SDL_Surface * screen)
  2539 {
  2540     /* Lock the screen if necessary */
  2541     if (screen == NULL) {
  2542         return;
  2543     }
  2544     if (SDL_MUSTLOCK(screen)) {
  2545         if (SDL_LockSurface(screen) < 0) {
  2546             return;
  2547         }
  2548     }
  2549 
  2550     SDL_EraseCursorNoLock(screen);
  2551 
  2552     /* Unlock the screen and update if necessary */
  2553     if (SDL_MUSTLOCK(screen)) {
  2554         SDL_UnlockSurface(screen);
  2555     }
  2556     if (screen->flags & SDL_SCREEN_SURFACE) {
  2557         SDL_VideoDevice *_this = SDL_GetVideoDevice();
  2558         SDL_Window *window;
  2559         SDL_Rect area;
  2560 
  2561         window = SDL_GetWindowFromSurface(screen);
  2562         if (!window) {
  2563             return;
  2564         }
  2565 
  2566         SDL_MouseRect(&area);
  2567 
  2568         if (_this->UpdateWindowSurface) {
  2569             _this->UpdateWindowSurface(_this, window, 1, &area);
  2570         }
  2571     }
  2572 }
  2573 
  2574 /* Reset the cursor on video mode change
  2575    FIXME:  Keep track of all cursors, and reset them all.
  2576  */
  2577 void
  2578 SDL_ResetCursor(void)
  2579 {
  2580     int savelen;
  2581 
  2582     if (SDL_cursor) {
  2583         savelen = SDL_cursor->area.w * 4 * SDL_cursor->area.h;
  2584         SDL_cursor->area.x = 0;
  2585         SDL_cursor->area.y = 0;
  2586         SDL_memset(SDL_cursor->save[0], 0, savelen);
  2587     }
  2588 }
  2589 #endif
  2590 
  2591 struct private_yuvhwdata
  2592 {
  2593     SDL_SW_YUVTexture *texture;
  2594     SDL_Surface *display;
  2595     Uint32 display_format;
  2596 };
  2597 
  2598 SDL_Overlay *
  2599 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
  2600 {
  2601     SDL_Overlay *overlay;
  2602     Uint32 texture_format;
  2603     SDL_SW_YUVTexture *texture;
  2604 
  2605     if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
  2606         SDL20_SetError("YUV overlays are not supported in OpenGL mode");
  2607         return NULL;
  2608     }
  2609 
  2610     if (display != PublicSurface) {
  2611         SDL20_SetError("YUV display is only supported on the screen surface");
  2612         return NULL;
  2613     }
  2614 
  2615     switch (format) {
  2616     case SDL_YV12_OVERLAY:
  2617         texture_format = SDL_PIXELFORMAT_YV12;
  2618         break;
  2619     case SDL_IYUV_OVERLAY:
  2620         texture_format = SDL_PIXELFORMAT_IYUV;
  2621         break;
  2622     case SDL_YUY2_OVERLAY:
  2623         texture_format = SDL_PIXELFORMAT_YUY2;
  2624         break;
  2625     case SDL_UYVY_OVERLAY:
  2626         texture_format = SDL_PIXELFORMAT_UYVY;
  2627         break;
  2628     case SDL_YVYU_OVERLAY:
  2629         texture_format = SDL_PIXELFORMAT_YVYU;
  2630         break;
  2631     default:
  2632         SDL20_SetError("Unknown YUV format");
  2633         return NULL;
  2634     }
  2635 
  2636     overlay = (SDL_Overlay *) SDL20_malloc(sizeof(*overlay));
  2637     if (!overlay) {
  2638         SDL20_OutOfMemory();
  2639         return NULL;
  2640     }
  2641     SDL20_zerop(overlay);
  2642 
  2643     overlay->hwdata =
  2644         (struct private_yuvhwdata *) SDL20_malloc(sizeof(*overlay->hwdata));
  2645     if (!overlay->hwdata) {
  2646         SDL20_free(overlay);
  2647         SDL20_OutOfMemory();
  2648         return NULL;
  2649     }
  2650 
  2651     texture = SDL_SW_CreateYUVTexture(texture_format, w, h);
  2652     if (!texture) {
  2653         SDL20_free(overlay->hwdata);
  2654         SDL20_free(overlay);
  2655         return NULL;
  2656     }
  2657     overlay->hwdata->texture = texture;
  2658     overlay->hwdata->display = NULL;
  2659     overlay->hwdata->display_format = SDL_PIXELFORMAT_UNKNOWN;
  2660 
  2661     overlay->format = format;
  2662     overlay->w = w;
  2663     overlay->h = h;
  2664     if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
  2665         overlay->planes = 3;
  2666     } else {
  2667         overlay->planes = 1;
  2668     }
  2669     overlay->pitches = texture->pitches;
  2670     overlay->pixels = texture->planes;
  2671 
  2672     return overlay;
  2673 }
  2674 
  2675 int
  2676 SDL_LockYUVOverlay(SDL_Overlay * overlay)
  2677 {
  2678     SDL_Rect rect;
  2679     void *pixels;
  2680     int pitch;
  2681 
  2682     if (!overlay) {
  2683         return SDL20_SetError("Passed a NULL overlay");
  2684     }
  2685 
  2686     rect.x = 0;
  2687     rect.y = 0;
  2688     rect.w = overlay->w;
  2689     rect.h = overlay->h;
  2690 
  2691     if (SDL_SW_LockYUVTexture(overlay->hwdata->texture, &rect, &pixels, &pitch) < 0) {
  2692         return -1;
  2693     }
  2694 
  2695     overlay->pixels[0] = (Uint8 *) pixels;
  2696     overlay->pitches[0] = pitch;
  2697     switch (overlay->format) {
  2698     case SDL_YV12_OVERLAY:
  2699     case SDL_IYUV_OVERLAY:
  2700         overlay->pitches[1] = pitch / 2;
  2701         overlay->pitches[2] = pitch / 2;
  2702         overlay->pixels[1] =
  2703             overlay->pixels[0] + overlay->pitches[0] * overlay->h;
  2704         overlay->pixels[2] =
  2705             overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
  2706         break;
  2707     case SDL_YUY2_OVERLAY:
  2708     case SDL_UYVY_OVERLAY:
  2709     case SDL_YVYU_OVERLAY:
  2710         break;
  2711     }
  2712     return 0;
  2713 }
  2714 
  2715 void
  2716 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
  2717 {
  2718     if (!overlay) {
  2719         return;
  2720     }
  2721 
  2722     SDL_SW_UnlockYUVTexture(overlay->hwdata->texture);
  2723 }
  2724 
  2725 int
  2726 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
  2727 {
  2728     SDL_Surface *display;
  2729     SDL_Rect src_rect;
  2730     SDL_Rect dst_rect;
  2731     void *pixels;
  2732 
  2733     if (!overlay || !dstrect) {
  2734         return SDL20_SetError("Passed a NULL overlay or dstrect");
  2735     }
  2736 
  2737     display = overlay->hwdata->display;
  2738     if (display != VideoSurface) {
  2739         overlay->hwdata->display = display = VideoSurface;
  2740         overlay->hwdata->display_format = SDL_MasksToPixelFormatEnum(
  2741                                                 display->format->BitsPerPixel,
  2742                                                 display->format->Rmask,
  2743                                                 display->format->Gmask,
  2744                                                 display->format->Bmask,
  2745                                                 display->format->Amask);
  2746     }
  2747 
  2748     src_rect.x = 0;
  2749     src_rect.y = 0;
  2750     src_rect.w = overlay->w;
  2751     src_rect.h = overlay->h;
  2752 
  2753     if (!SDL_IntersectRect(&display->clip_rect, dstrect, &dst_rect)) {
  2754         return 0;
  2755     }
  2756      
  2757     pixels = (void *)((Uint8 *)display->pixels +
  2758                         dst_rect.y * display->pitch +
  2759                         dst_rect.x * display->format->BytesPerPixel);
  2760 
  2761     if (SDL_SW_CopyYUVToRGB(overlay->hwdata->texture, &src_rect,
  2762                             overlay->hwdata->display_format,
  2763                             dst_rect.w, dst_rect.h,
  2764                             pixels, display->pitch) < 0) {
  2765         return -1;
  2766     }
  2767     SDL_UpdateWindowSurface(VideoWindow20);
  2768     return 0;
  2769 }
  2770 
  2771 void
  2772 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
  2773 {
  2774     if (!overlay) {
  2775         return;
  2776     }
  2777     if (overlay->hwdata) {
  2778         if (overlay->hwdata->texture) {
  2779             SDL_SW_DestroyYUVTexture(overlay->hwdata->texture);
  2780         }
  2781         SDL20_free(overlay->hwdata);
  2782     }
  2783     SDL20_free(overlay);
  2784 }
  2785 #endif
  2786 
  2787 int
  2788 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
  2789 {
  2790     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2791         return SDL20_SetError("Unknown GL attribute");
  2792 
  2793     /* swap control was moved out of this API, everything else lines up. */
  2794     if (attr == SDL12_GL_SWAP_CONTROL)
  2795     {
  2796         SwapInterval = value;
  2797         return 0;
  2798     }
  2799 
  2800     return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
  2801 }
  2802 
  2803 int
  2804 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
  2805 {
  2806     if (attr >= SDL12_GL_MAX_ATTRIBUTE)
  2807         return SDL20_SetError("Unknown GL attribute");
  2808 
  2809     /* swap control was moved out of this API, everything else lines up. */
  2810     if (attr == SDL12_GL_SWAP_CONTROL)
  2811     {
  2812         *value = SDL20_GL_GetSwapInterval();
  2813         return 0;
  2814     }
  2815 
  2816     return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
  2817 }
  2818 
  2819 
  2820 void
  2821 SDL_GL_SwapBuffers(void)
  2822 {
  2823     if (VideoWindow20)
  2824         SDL20_GL_SwapWindow(VideoWindow20);
  2825 }
  2826 
  2827 int
  2828 SDL_SetGamma(float red, float green, float blue)
  2829 {
  2830     Uint16 red_ramp[256];
  2831     Uint16 green_ramp[256];
  2832     Uint16 blue_ramp[256];
  2833 
  2834     SDL20_CalculateGammaRamp(red, red_ramp);
  2835     if (green == red) {
  2836         SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
  2837     } else {
  2838         SDL20_CalculateGammaRamp(green, green_ramp);
  2839     }
  2840     if (blue == red) {
  2841         SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
  2842     } else if (blue == green) {
  2843         SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
  2844     } else {
  2845         SDL20_CalculateGammaRamp(blue, blue_ramp);
  2846     }
  2847     return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
  2848 }
  2849 
  2850 int
  2851 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
  2852 {
  2853     return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
  2854 }
  2855 
  2856 int
  2857 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  2858 {
  2859     return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
  2860 }
  2861 
  2862 int
  2863 SDL_EnableKeyRepeat(int delay, int interval)
  2864 {
  2865     return 0;
  2866 }
  2867 
  2868 void
  2869 SDL_GetKeyRepeat(int *delay, int *interval)
  2870 {
  2871     if (delay) {
  2872         *delay = SDL12_DEFAULT_REPEAT_DELAY;
  2873     }
  2874     if (interval) {
  2875         *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
  2876     }
  2877 }
  2878 
  2879 #if SANITY_CHECK_THIS_CODE
  2880 int
  2881 SDL_EnableUNICODE(int enable)
  2882 {
  2883     int previous = EnabledUnicode;
  2884 
  2885     switch (enable) {
  2886     case 1:
  2887         EnabledUnicode = 1;
  2888         SDL20_StartTextInput();
  2889         break;
  2890     case 0:
  2891         EnabledUnicode = 0;
  2892         SDL20_StopTextInput();
  2893         break;
  2894     }
  2895     return previous;
  2896 }
  2897 #endif
  2898 
  2899 static Uint32
  2900 SetTimerOld_Callback(Uint32 interval, void* param)
  2901 {
  2902     return ((SDL12_TimerCallback)param)(interval);
  2903 }
  2904 
  2905 int
  2906 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
  2907 {
  2908     static SDL_TimerID compat_timer;
  2909 
  2910     if (compat_timer) {
  2911         SDL20_RemoveTimer(compat_timer);
  2912         compat_timer = 0;
  2913     }
  2914 
  2915     if (interval && callback) {
  2916         compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
  2917         if (!compat_timer) {
  2918             return -1;
  2919         }
  2920     }
  2921     return 0;
  2922 }
  2923 
  2924 int
  2925 SDL_putenv(const char *_var)
  2926 {
  2927     char *ptr = NULL;
  2928     char *var = SDL20_strdup(_var);
  2929     if (var == NULL) {
  2930         return -1;  /* we don't set errno. */
  2931     }
  2932 
  2933     ptr = SDL20_strchr(var, '=');
  2934     if (ptr == NULL) {
  2935         SDL20_free(var);
  2936         return -1;
  2937     }
  2938 
  2939     *ptr = '\0';  /* split the string into name and value. */
  2940     SDL20_setenv(var, ptr + 1, 1);
  2941     SDL20_free(var);
  2942     return 0;
  2943 }
  2944 
  2945 
  2946 
  2947 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
  2948 
  2949 typedef void *SDL12_CD;  /* close enough.  :) */
  2950 typedef int SDL12_CDstatus;  /* close enough.  :) */
  2951 
  2952 int
  2953 SDL_CDNumDrives(void)
  2954 {
  2955     return 0;  /* !!! FIXME: should return -1 without SDL_INIT_CDROM */
  2956 }
  2957 
  2958 const char *SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
  2959 SDL12_CD * SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
  2960 SDL12_CDstatus SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2961 int SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
  2962 int SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
  2963 int SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2964 int SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2965 int SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2966 int SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
  2967 void SDL_CDClose(SDL12_CD *cdrom) {}
  2968 
  2969 
  2970 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
  2971 SDL_Thread *
  2972 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
  2973 {
  2974     return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
  2975 }
  2976 #else
  2977 SDL_Thread *
  2978 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
  2979 {
  2980     return SDL20_CreateThread(fn, NULL, data);
  2981 }
  2982 #endif
  2983 
  2984 
  2985 /* !!! FIXME: Removed from 2.0; do nothing. We can't even report failure. */
  2986 void SDL_KillThread(SDL_Thread *thread) {}
  2987 
  2988 /* This changed from an opaque pointer to an int in 2.0. */
  2989 typedef struct _SDL12_TimerID *SDL12_TimerID;
  2990 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
  2991 
  2992 
  2993 SDL12_TimerID
  2994 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
  2995 {
  2996     return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
  2997 }
  2998 
  2999 SDL_bool
  3000 SDL_RemoveTimer(SDL12_TimerID id)
  3001 {
  3002     return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
  3003 }
  3004 
  3005 
  3006 typedef struct SDL12_RWops {
  3007     int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
  3008     int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
  3009     int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
  3010     int (SDLCALL *close)(struct SDL12_RWops *context);
  3011     Uint32 type;
  3012     void *padding[8];
  3013     SDL_RWops *rwops20;
  3014 } SDL12_RWops;
  3015 
  3016 
  3017 SDL12_RWops *
  3018 SDL_AllocRW(void)
  3019 {
  3020     SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
  3021     if (!rwops)
  3022         SDL20_OutOfMemory();
  3023     return rwops;
  3024 }
  3025 
  3026 void
  3027 SDL_FreeRW(SDL12_RWops *rwops12)
  3028 {
  3029     SDL20_free(rwops12);
  3030 }
  3031 
  3032 static int SDLCALL
  3033 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
  3034 {
  3035     return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
  3036 }
  3037 
  3038 static int SDLCALL
  3039 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
  3040 {
  3041     return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
  3042 }
  3043 
  3044 static int SDLCALL
  3045 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
  3046 {
  3047     return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
  3048 }
  3049 
  3050 static int SDLCALL
  3051 RWops20to12_close(struct SDL12_RWops *rwops12)
  3052 {
  3053     int rc = 0;
  3054     if (rwops12)
  3055     {
  3056         rc = rwops12->rwops20->close(rwops12->rwops20);
  3057         if (rc == 0)
  3058             SDL_FreeRW(rwops12);
  3059     }
  3060     return rc;
  3061 }
  3062 
  3063 static SDL12_RWops *
  3064 RWops20to12(SDL_RWops *rwops20)
  3065 {
  3066     SDL12_RWops *rwops12;
  3067 
  3068     if (!rwops20)
  3069         return NULL;
  3070 
  3071     rwops12 = SDL_AllocRW();
  3072     if (!rwops12)
  3073         return NULL;
  3074 
  3075     SDL20_zerop(rwops12);
  3076     rwops12->type = rwops20->type;
  3077     rwops12->rwops20 = rwops20;
  3078     rwops12->seek = RWops20to12_seek;
  3079     rwops12->read = RWops20to12_read;
  3080     rwops12->write = RWops20to12_write;
  3081     rwops12->close = RWops20to12_close;
  3082 
  3083     return rwops12;
  3084 }
  3085 
  3086 SDL12_RWops *
  3087 SDL_RWFromFile(const char *file, const char *mode)
  3088 {
  3089     return RWops20to12(SDL20_RWFromFile(file, mode));
  3090 }
  3091 
  3092 SDL12_RWops *
  3093 SDL_RWFromFP(FILE *io, int autoclose)
  3094 {
  3095     return RWops20to12(SDL20_RWFromFP(io, autoclose));
  3096 }
  3097 
  3098 SDL12_RWops *
  3099 SDL_RWFromMem(void *mem, int size)
  3100 {
  3101     return RWops20to12(SDL20_RWFromMem(mem, size));
  3102 }
  3103 
  3104 SDL12_RWops *
  3105 SDL_RWFromConstMem(const void *mem, int size)
  3106 {
  3107     return RWops20to12(SDL20_RWFromConstMem(mem, size));
  3108 }
  3109 
  3110 #define READ_AND_BYTESWAP(endian, bits) \
  3111     Uint##bits SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
  3112         Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
  3113         return SDL_Swap##endian##bits(val); \
  3114     }
  3115 
  3116 READ_AND_BYTESWAP(LE,16)
  3117 READ_AND_BYTESWAP(BE,16)
  3118 READ_AND_BYTESWAP(LE,32)
  3119 READ_AND_BYTESWAP(BE,32)
  3120 READ_AND_BYTESWAP(LE,64)
  3121 READ_AND_BYTESWAP(BE,64)
  3122 #undef READ_AND_BYTESWAP
  3123 
  3124 #define BYTESWAP_AND_WRITE(endian, bits) \
  3125     int SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
  3126         val = SDL_Swap##endian##bits(val); \
  3127         return rwops12->write(rwops12, &val, sizeof (val), 1); \
  3128     }
  3129 BYTESWAP_AND_WRITE(LE,16)
  3130 BYTESWAP_AND_WRITE(BE,16)
  3131 BYTESWAP_AND_WRITE(LE,32)
  3132 BYTESWAP_AND_WRITE(BE,32)
  3133 BYTESWAP_AND_WRITE(LE,64)
  3134 BYTESWAP_AND_WRITE(BE,64)
  3135 #undef BYTESWAP_AND_WRITE
  3136 
  3137 
  3138 static Sint64 SDLCALL
  3139 RWops12to20_size(struct SDL_RWops *rwops20)
  3140 {
  3141     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3142     int size = rwops20->hidden.unknown.data2;
  3143     int pos;
  3144 
  3145     if (size != -1)
  3146         return size;
  3147 
  3148     pos = rwops12->seek(rwops12, 0, SEEK_CUR);
  3149     if (pos == -1)
  3150         return -1;
  3151 
  3152     size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
  3153     if (size == -1)
  3154         return -1;
  3155 
  3156     rwops12->seek(rwops12, pos, SEEK_SET);  /* !!! FIXME: and if this fails? */
  3157     rwops20->hidden.unknown.data2 = size;
  3158     return size;
  3159 }
  3160 
  3161 static Sint64
  3162 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
  3163 {
  3164     /* !!! FIXME: fail if (offset) is too big */
  3165     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3166     return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
  3167 }
  3168 
  3169 static size_t SDLCALL
  3170 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
  3171 {
  3172     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  3173     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3174     return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
  3175 }
  3176 
  3177 static size_t SDLCALL
  3178 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
  3179 {
  3180     /* !!! FIXME: fail if (size) or (maxnum) is too big */
  3181     SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3182     return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
  3183 }
  3184 
  3185 static int SDLCALL
  3186 RWops12to20_close(struct SDL_RWops *rwops20)
  3187 {
  3188     int rc = 0;
  3189     if (rwops20)
  3190     {
  3191         SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
  3192         rc = rwops12->close(rwops12);
  3193         if (rc == 0)
  3194             SDL20_FreeRW(rwops20);
  3195     }
  3196     return rc;
  3197 }
  3198 
  3199 static SDL_RWops *
  3200 RWops12to20(SDL12_RWops *rwops12)
  3201 {
  3202     SDL_RWops *rwops20;
  3203 
  3204     if (!rwops12)
  3205         return NULL;
  3206 
  3207     rwops20 = SDL20_AllocRW();
  3208     if (!rwops20)
  3209         return NULL;
  3210 
  3211     SDL20_zerop(rwops20);
  3212     rwops20->type = rwops12->type;
  3213     rwops20->hidden.unknown.data1 = rwops12;
  3214     rwops20->hidden.unknown.data2 = -1;  /* cached size of stream */
  3215     rwops20->size = RWops12to20_size;
  3216     rwops20->seek = RWops12to20_seek;
  3217     rwops20->read = RWops12to20_read;
  3218     rwops20->write = RWops12to20_write;
  3219     rwops20->close = RWops12to20_close;
  3220     return rwops20;
  3221 }
  3222 
  3223 SDL12_Surface *
  3224 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
  3225 {
  3226     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3227     SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
  3228     SDL12_Surface *surface12 = Surface20to12(surface20);
  3229     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3230         SDL20_FreeRW(rwops20);
  3231     if ((!surface12) && (surface20))
  3232         SDL20_FreeSurface(surface20);
  3233     return surface12;
  3234 }
  3235 
  3236 int
  3237 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
  3238 {
  3239     // !!! FIXME: wrap surface.
  3240     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3241     const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
  3242     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3243         SDL20_FreeRW(rwops20);
  3244     return retval;
  3245 }
  3246 
  3247 SDL_AudioSpec *
  3248 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
  3249                SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
  3250 {
  3251     SDL_RWops *rwops20 = RWops12to20(rwops12);
  3252     SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
  3253     if (!freerwops12)  /* free our wrapper if SDL2 didn't close it. */
  3254         SDL20_FreeRW(rwops20);
  3255     return retval;
  3256 }
  3257 
  3258 /* vi: set ts=4 sw=4 expandtab: */