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