SDL_GL_LoadLibrary() has slightly different behavior between 1.2 and 2.0.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
22 /* This file contains functions for backwards compatibility with SDL 1.2 */
24 // !!! FIXME: clean up code conventions
25 // !!! FIXME: grep for VideoWindow20 places that might care if it's NULL
27 #include "SDL20_include_wrapper.h"
29 #if !SDL_VERSION_ATLEAST(2,0,0)
30 #error You need to compile against SDL 2.0 headers.
34 * We report the library version as 1.2.$(SDL12_COMPAT_VERSION). This number
35 * should be way ahead of what SDL-1.2 Classic would report, so apps can
36 * decide if they're running under the compat layer, if they really care.
38 #define SDL12_COMPAT_VERSION 50
42 // !!! IMPLEMENT_ME SDL_CDClose
43 // !!! IMPLEMENT_ME SDL_CDEject
44 // !!! IMPLEMENT_ME SDL_CDName
45 // !!! IMPLEMENT_ME SDL_CDNumDrives
46 // !!! IMPLEMENT_ME SDL_CDOpen
47 // !!! IMPLEMENT_ME SDL_CDPause
48 // !!! IMPLEMENT_ME SDL_CDPlay
49 // !!! IMPLEMENT_ME SDL_CDPlayTracks
50 // !!! IMPLEMENT_ME SDL_CDResume
51 // !!! IMPLEMENT_ME SDL_CDStatus
52 // !!! IMPLEMENT_ME SDL_CDStop
53 // !!! IMPLEMENT_ME SDL_CreateYUVOverlay
55 // !!! IMPLEMENT_ME SDL_DisplayFormatAlpha
56 // !!! IMPLEMENT_ME SDL_DisplayYUVOverlay
57 // !!! IMPLEMENT_ME SDL_EnableKeyRepeat
58 // !!! IMPLEMENT_ME SDL_EnableUNICODE
59 // !!! IMPLEMENT_ME SDL_FreeYUVOverlay
61 // !!! IMPLEMENT_ME SDL_GL_Lock
62 // !!! IMPLEMENT_ME SDL_GL_Unlock
63 // !!! IMPLEMENT_ME SDL_GL_UpdateRects
65 // !!! IMPLEMENT_ME SDL_GetKeyName
66 // !!! IMPLEMENT_ME SDL_GetKeyState
67 // !!! IMPLEMENT_ME SDL_GetModState
68 // !!! IMPLEMENT_ME SDL_GetRelativeMouseState
70 // !!! IMPLEMENT_ME SDL_GetVideoSurface
71 // !!! IMPLEMENT_ME SDL_GetWMInfo
73 // !!! IMPLEMENT_ME SDL_LockSurface
74 // !!! IMPLEMENT_ME SDL_LockYUVOverlay
75 // !!! IMPLEMENT_ME SDL_LowerBlit
77 // !!! IMPLEMENT_ME SDL_SetAlpha
78 // !!! IMPLEMENT_ME SDL_SetColorKey
79 // !!! IMPLEMENT_ME SDL_SetColors
81 // !!! IMPLEMENT_ME SDL_SetModState
82 // !!! IMPLEMENT_ME SDL_SetPalette
83 // !!! IMPLEMENT_ME SDL_SetVideoMode
84 // !!! IMPLEMENT_ME SDL_SoftStretch
85 // !!! IMPLEMENT_ME SDL_UnlockSurface
86 // !!! IMPLEMENT_ME SDL_UnlockYUVOverlay
87 // !!! IMPLEMENT_ME SDL_UpdateRects
88 // !!! IMPLEMENT_ME SDL_UpperBlit
90 // !!! FIXME: should SDL_VideoInit really be a passthrough?
91 // !!! FIXME: should SDL_VideoQuit really be a passthrough?
93 // !!! IMPLEMENT_ME SDL_WM_SetIcon
94 // !!! IMPLEMENT_ME SDL_WM_ToggleFullScreen
96 // !!! IMPLEMENT_ME X11_KeyToUnicode
98 #define SDL_BlitSurface SDL_UpperBlit
102 #define FIXME(x) do {} while (0)
106 static SDL_bool seen = SDL_FALSE; \
108 fprintf(stderr, "FIXME: %s (%s:%d)\n", x, __FILE__, __LINE__); \
114 #define SDL20_SYM(rc,fn,params,args,ret) \
115 typedef rc (SDLCALL *SDL20_##fn##_t) params; \
116 static SDL20_##fn##_t SDL20_##fn = NULL;
117 #include "SDL20_syms.h"
119 /* Things that _should_ be binary compatible pass right through... */
120 #define SDL20_SYM_PASSTHROUGH(rc,fn,params,args,ret) \
121 DECLSPEC rc SDLCALL SDL_##fn params { ret SDL20_##fn args; }
122 #include "SDL20_syms.h"
125 /* these are macros (etc) in the SDL headers, so make our own. */
126 #define SDL20_OutOfMemory() SDL20_Error(SDL_ENOMEM)
127 #define SDL20_Unsupported() SDL20_Error(SDL_UNSUPPORTED)
128 #define SDL20_InvalidParamError(param) SDL20_SetError("Parameter '%s' is invalid", (param))
129 #define SDL20_zero(x) SDL20_memset(&(x), 0, sizeof((x)))
130 #define SDL20_zerop(x) SDL20_memset((x), 0, sizeof(*(x)))
131 #define SDL_ReportAssertion SDL20_ReportAssertion
133 #define SDL12_DEFAULT_REPEAT_DELAY 500
134 #define SDL12_DEFAULT_REPEAT_INTERVAL 30
136 #define SDL12_INIT_TIMER 0x00000001
137 #define SDL12_INIT_AUDIO 0x00000010
138 #define SDL12_INIT_VIDEO 0x00000020
139 #define SDL12_INIT_CDROM 0x00000100
140 #define SDL12_INIT_JOYSTICK 0x00000200
141 #define SDL12_INIT_NOPARACHUTE 0x00100000
142 #define SDL12_INIT_EVENTTHREAD 0x01000000
143 #define SDL12_INIT_EVERYTHING 0x0000FFFF
145 typedef struct SDL12_Rect
153 typedef struct SDL12_Palette
159 typedef struct SDL12_PixelFormat
161 SDL12_Palette *palette;
180 typedef struct SDL12_Surface
183 SDL12_PixelFormat *format;
189 SDL_Surface *surface20; /* the real SDL 1.2 has an opaque pointer to a platform-specific thing here named "hwdata". */
190 SDL12_Rect clip_rect;
194 unsigned int format_version;
198 typedef struct SDL12_Overlay
208 Uint32 hw_overlay :1;
209 Uint32 UnusedBits :31;
214 Uint32 hw_available :1;
215 Uint32 wm_available :1;
216 Uint32 UnusedBits1 :6;
217 Uint32 UnusedBits2 :1;
219 Uint32 blit_hw_CC :1;
222 Uint32 blit_sw_CC :1;
225 Uint32 UnusedBits3 :16;
227 SDL_PixelFormat *vfmt;
233 #define SDL12_HWSURFACE 0x00000001
234 #define SDL12_ASYNCBLIT 0x00000004
235 #define SDL12_ANYFORMAT 0x10000000
236 #define SDL12_HWPALETTE 0x20000000
237 #define SDL12_DOUBLEBUF 0x40000000
238 #define SDL12_FULLSCREEN 0x80000000
239 #define SDL12_OPENGL 0x00000002
240 #define SDL12_OPENGLBLIT 0x0000000A
241 #define SDL12_RESIZABLE 0x00000010
242 #define SDL12_NOFRAME 0x00000020
243 #define SDL12_HWACCEL 0x00000100
244 #define SDL12_SRCCOLORKEY 0x00001000
245 #define SDL12_RLEACCELOK 0x00002000
246 #define SDL12_RLEACCEL 0x00004000
247 #define SDL12_SRCALPHA 0x00010000
248 #define SDL12_PREALLOC 0x01000000
254 SDLK12_BACKSPACE = 8,
262 SDLK12_QUOTEDBL = 34,
265 SDLK12_AMPERSAND = 38,
267 SDLK12_LEFTPAREN = 40,
268 SDLK12_RIGHTPAREN = 41,
269 SDLK12_ASTERISK = 42,
286 SDLK12_SEMICOLON = 59,
290 SDLK12_QUESTION = 63,
292 SDLK12_LEFTBRACKET = 91,
293 SDLK12_BACKSLASH = 92,
294 SDLK12_RIGHTBRACKET = 93,
296 SDLK12_UNDERSCORE = 95,
297 SDLK12_BACKQUOTE = 96,
325 SDLK12_WORLD_0 = 160,
326 SDLK12_WORLD_1 = 161,
327 SDLK12_WORLD_2 = 162,
328 SDLK12_WORLD_3 = 163,
329 SDLK12_WORLD_4 = 164,
330 SDLK12_WORLD_5 = 165,
331 SDLK12_WORLD_6 = 166,
332 SDLK12_WORLD_7 = 167,
333 SDLK12_WORLD_8 = 168,
334 SDLK12_WORLD_9 = 169,
335 SDLK12_WORLD_10 = 170,
336 SDLK12_WORLD_11 = 171,
337 SDLK12_WORLD_12 = 172,
338 SDLK12_WORLD_13 = 173,
339 SDLK12_WORLD_14 = 174,
340 SDLK12_WORLD_15 = 175,
341 SDLK12_WORLD_16 = 176,
342 SDLK12_WORLD_17 = 177,
343 SDLK12_WORLD_18 = 178,
344 SDLK12_WORLD_19 = 179,
345 SDLK12_WORLD_20 = 180,
346 SDLK12_WORLD_21 = 181,
347 SDLK12_WORLD_22 = 182,
348 SDLK12_WORLD_23 = 183,
349 SDLK12_WORLD_24 = 184,
350 SDLK12_WORLD_25 = 185,
351 SDLK12_WORLD_26 = 186,
352 SDLK12_WORLD_27 = 187,
353 SDLK12_WORLD_28 = 188,
354 SDLK12_WORLD_29 = 189,
355 SDLK12_WORLD_30 = 190,
356 SDLK12_WORLD_31 = 191,
357 SDLK12_WORLD_32 = 192,
358 SDLK12_WORLD_33 = 193,
359 SDLK12_WORLD_34 = 194,
360 SDLK12_WORLD_35 = 195,
361 SDLK12_WORLD_36 = 196,
362 SDLK12_WORLD_37 = 197,
363 SDLK12_WORLD_38 = 198,
364 SDLK12_WORLD_39 = 199,
365 SDLK12_WORLD_40 = 200,
366 SDLK12_WORLD_41 = 201,
367 SDLK12_WORLD_42 = 202,
368 SDLK12_WORLD_43 = 203,
369 SDLK12_WORLD_44 = 204,
370 SDLK12_WORLD_45 = 205,
371 SDLK12_WORLD_46 = 206,
372 SDLK12_WORLD_47 = 207,
373 SDLK12_WORLD_48 = 208,
374 SDLK12_WORLD_49 = 209,
375 SDLK12_WORLD_50 = 210,
376 SDLK12_WORLD_51 = 211,
377 SDLK12_WORLD_52 = 212,
378 SDLK12_WORLD_53 = 213,
379 SDLK12_WORLD_54 = 214,
380 SDLK12_WORLD_55 = 215,
381 SDLK12_WORLD_56 = 216,
382 SDLK12_WORLD_57 = 217,
383 SDLK12_WORLD_58 = 218,
384 SDLK12_WORLD_59 = 219,
385 SDLK12_WORLD_60 = 220,
386 SDLK12_WORLD_61 = 221,
387 SDLK12_WORLD_62 = 222,
388 SDLK12_WORLD_63 = 223,
389 SDLK12_WORLD_64 = 224,
390 SDLK12_WORLD_65 = 225,
391 SDLK12_WORLD_66 = 226,
392 SDLK12_WORLD_67 = 227,
393 SDLK12_WORLD_68 = 228,
394 SDLK12_WORLD_69 = 229,
395 SDLK12_WORLD_70 = 230,
396 SDLK12_WORLD_71 = 231,
397 SDLK12_WORLD_72 = 232,
398 SDLK12_WORLD_73 = 233,
399 SDLK12_WORLD_74 = 234,
400 SDLK12_WORLD_75 = 235,
401 SDLK12_WORLD_76 = 236,
402 SDLK12_WORLD_77 = 237,
403 SDLK12_WORLD_78 = 238,
404 SDLK12_WORLD_79 = 239,
405 SDLK12_WORLD_80 = 240,
406 SDLK12_WORLD_81 = 241,
407 SDLK12_WORLD_82 = 242,
408 SDLK12_WORLD_83 = 243,
409 SDLK12_WORLD_84 = 244,
410 SDLK12_WORLD_85 = 245,
411 SDLK12_WORLD_86 = 246,
412 SDLK12_WORLD_87 = 247,
413 SDLK12_WORLD_88 = 248,
414 SDLK12_WORLD_89 = 249,
415 SDLK12_WORLD_90 = 250,
416 SDLK12_WORLD_91 = 251,
417 SDLK12_WORLD_92 = 252,
418 SDLK12_WORLD_93 = 253,
419 SDLK12_WORLD_94 = 254,
420 SDLK12_WORLD_95 = 255,
431 SDLK12_KP_PERIOD = 266,
432 SDLK12_KP_DIVIDE = 267,
433 SDLK12_KP_MULTIPLY = 268,
434 SDLK12_KP_MINUS = 269,
435 SDLK12_KP_PLUS = 270,
436 SDLK12_KP_ENTER = 271,
437 SDLK12_KP_EQUALS = 272,
446 SDLK12_PAGEDOWN = 281,
462 SDLK12_NUMLOCK = 300,
463 SDLK12_CAPSLOCK = 301,
464 SDLK12_SCROLLOCK = 302,
476 SDLK12_COMPOSE = 314,
490 KMOD12_NONE = 0x0000,
491 KMOD12_LSHIFT = 0x0001,
492 KMOD12_RSHIFT = 0x0002,
493 KMOD12_LCTRL = 0x0040,
494 KMOD12_RCTRL = 0x0080,
495 KMOD12_LALT = 0x0100,
496 KMOD12_RALT = 0x0200,
497 KMOD12_LMETA = 0x0400,
498 KMOD12_RMETA = 0x0800,
500 KMOD12_CAPS = 0x2000,
501 KMOD12_MODE = 0x4000,
502 KMOD12_RESERVED = 0x8000
505 typedef struct SDL12_keysym
520 SDL12_MOUSEBUTTONDOWN,
529 SDL12_EVENT_RESERVEDA,
530 SDL12_EVENT_RESERVEDB,
533 SDL12_USEREVENT = 24,
538 #define SDL12_APPMOUSEFOCUS (1<<0)
539 #define SDL12_APPINPUTFOCUS (1<<1)
540 #define SDL12_APPACTIVE (1<<2)
555 } SDL12_KeyboardEvent;
565 } SDL12_MouseMotionEvent;
574 } SDL12_MouseButtonEvent;
582 } SDL12_JoyAxisEvent;
591 } SDL12_JoyBallEvent;
607 } SDL12_JoyButtonEvent;
643 SDL12_ActiveEvent active;
644 SDL12_KeyboardEvent key;
645 SDL12_MouseMotionEvent motion;
646 SDL12_MouseButtonEvent button;
647 SDL12_JoyAxisEvent jaxis;
648 SDL12_JoyBallEvent jball;
649 SDL12_JoyHatEvent jhat;
650 SDL12_JoyButtonEvent jbutton;
651 SDL12_ResizeEvent resize;
652 SDL12_ExposeEvent expose;
653 SDL12_QuitEvent quit;
654 SDL12_UserEvent user;
655 SDL12_SysWMEvent syswm;
658 typedef int (SDLCALL *SDL12_EventFilter)(const SDL12_Event *event12);
659 static int EventFilter20to12(void *data, SDL_Event *event20);
661 typedef Uint32 (SDLCALL *SDL12_TimerCallback)(Uint32 interval);
662 typedef SDL_TimerCallback SDL12_NewTimerCallback;
672 SDL_Cursor *wm_cursor; /* the real SDL 1.2 has an opaque pointer to a platform-specific cursor here. */
681 SDL12_GL_BUFFER_SIZE,
682 SDL12_GL_DOUBLEBUFFER,
684 SDL12_GL_STENCIL_SIZE,
685 SDL12_GL_ACCUM_RED_SIZE,
686 SDL12_GL_ACCUM_GREEN_SIZE,
687 SDL12_GL_ACCUM_BLUE_SIZE,
688 SDL12_GL_ACCUM_ALPHA_SIZE,
690 SDL12_GL_MULTISAMPLEBUFFERS,
691 SDL12_GL_MULTISAMPLESAMPLES,
692 SDL12_GL_ACCELERATED_VISUAL,
693 SDL12_GL_SWAP_CONTROL,
694 SDL12_GL_MAX_ATTRIBUTE
701 SDL12_Rect *modeslist12;
702 SDL12_Rect **modes12; /* ptrs to each item in modeslist, for SDL_ListModes() */
708 SDL_Joystick *joystick;
709 } JoystickOpenedItem;
711 // !!! FIXME: go through all of these.
712 static VideoModeList *VideoModes = NULL;
713 static int VideoModesCount = 0;
714 static SDL12_VideoInfo VideoInfo12;
715 static SDL_Window *VideoWindow20 = NULL;
716 static SDL_Renderer *VideoRenderer20 = NULL;
717 static SDL_Texture *VideoTexture20 = NULL;
718 static SDL12_Surface *VideoSurface12 = NULL;
719 static SDL_Surface *VideoConvertSurface20 = NULL;
720 static SDL_GLContext *VideoGLContext20 = NULL;
721 static char *WindowTitle = NULL;
722 static char *WindowIconTitle = NULL;
723 static SDL12_Surface *VideoIcon12;
724 static int EnabledUnicode = 0;
725 static int VideoDisplayIndex = 0;
726 static int CDRomInit = 0;
727 static SDL12_EventFilter EventFilter12 = NULL;
728 static SDL12_Cursor *CurrentCursor12 = NULL;
729 static Uint8 EventStates[SDL12_NUMEVENTS];
730 static int SwapInterval = 0;
731 static JoystickOpenedItem JoystickOpenList[16];
733 // !!! FIXME: need a mutex for the event queue.
734 #define SDL12_MAXEVENTS 128
735 typedef struct EventQueueType
738 struct EventQueueType *next;
741 static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
742 static EventQueueType *EventQueueHead = NULL;
743 static EventQueueType *EventQueueTail = NULL;
744 static EventQueueType *EventQueueAvailable = NULL;
747 /* Obviously we can't use SDL_LoadObject() to load SDL2. :) */
748 #if defined(_WINDOWS)
749 #define WIN32_LEAN_AND_MEAN 1
751 #define SDL20_LIBNAME "SDL2.dll"
752 static HANDLE Loaded_SDL20 = NULL;
753 #define LoadSDL20Library() ((Loaded_SDL20 = LoadLibraryA(SDL20_LIBNAME)) != NULL)
754 #define LookupSDL20Sym(sym) GetProcAddress(Loaded_SDL20, sym)
755 #define CloseSDL20Library() { { if (Loaded_SDL20) { FreeLibrary(Loaded_SDL20); Loaded_SDL20 = NULL; } }
756 #elif defined(unix) || defined(__APPLE__)
759 #define SDL20_LIBNAME "libSDL2.dylib"
761 #define SDL20_LIBNAME "libSDL2-2.0.so.0"
763 static void *Loaded_SDL20 = NULL;
764 #define LoadSDL20Library() ((Loaded_SDL20 = dlopen(SDL20_LIBNAME, RTLD_LOCAL|RTLD_NOW)) != NULL)
765 #define LookupSDL20Sym(sym) dlsym(Loaded_SDL20, sym)
766 #define CloseSDL20Library() { if (Loaded_SDL20) { dlclose(Loaded_SDL20); Loaded_SDL20 = NULL; } }
768 #error Please define your platform.
772 LoadSDL20Symbol(const char *fn, int *okay)
775 if (*okay) { /* only bother trying if we haven't previously failed. */
776 retval = LookupSDL20Sym(fn);
777 if (retval == NULL) {
778 /* Flip to 1 to warn but maybe work if nothing calls that function, flip to zero to fail out. */
780 fprintf(stderr, "WARNING: LOAD FAILED: %s\n", fn);
792 #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = NULL;
793 #include "SDL20_syms.h"
803 okay = LoadSDL20Library();
804 #define SDL20_SYM(rc,fn,params,args,ret) SDL20_##fn = (SDL20_##fn##_t) LoadSDL20Symbol("SDL_" #fn, &okay);
805 #include "SDL20_syms.h"
812 DECLSPEC const SDL_version * SDLCALL
813 SDL_Linked_Version(void)
815 static const SDL_version version = { 1, 2, SDL12_COMPAT_VERSION };
820 SDL_sscanf(const char *text, const char *fmt, ...)
825 retval = (int) SDL20_sscanf(text, fmt, ap);
831 SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
836 retval = (int) SDL20_vsnprintf(text, maxlen, fmt, ap);
841 DECLSPEC void * SDLCALL
842 SDL_revcpy(void *dst, const void *src, size_t len)
844 /* this doesn't reverse the data...I think this was just a memcpy that
845 was meant to be CPU-cache friendly if you knew you were working with
846 data going backwards in memory, instead of jumping over pages to copy
847 from the start...? Whatever, just do a memcpy here. */
848 return SDL_memcpy(dst, src, len);
852 DECLSPEC SDL_bool SDLCALL
855 /* this isn't accurate, but SDL2 doesn't have this for some reason.
856 MMXExt is available in all SSE1 machines, except early Athlon chips,
857 so we'll just say it's available if they have SSE1. Oh well. */
858 return SDL20_HasSSE();
861 DECLSPEC SDL_bool SDLCALL
862 SDL_Has3DNowExt(void)
865 return SDL20_HasSSE();
868 DECLSPEC SDL_Joystick * SDLCALL
869 SDL_JoystickOpen(int device_index)
872 SDL20_LockJoysticks();
873 for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
874 if (JoystickOpenList[i].joystick == NULL) {
879 if (i == SDL_arraysize(JoystickOpenList)) {
880 SDL20_UnlockJoysticks();
881 SDL20_SetError("Too many open joysticks");
885 JoystickOpenList[i].joystick = SDL20_JoystickOpen(device_index);
886 if (JoystickOpenList[i].joystick) {
887 JoystickOpenList[i].device_index = device_index;
890 SDL20_UnlockJoysticks();
891 return JoystickOpenList[i].joystick;
894 DECLSPEC void SDLCALL
895 SDL_JoystickClose(SDL_Joystick *joystick)
898 SDL20_LockJoysticks();
899 for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
900 if (JoystickOpenList[i].joystick == joystick) {
905 if (i < SDL_arraysize(JoystickOpenList)) {
906 JoystickOpenList[i].joystick = NULL;
909 SDL20_UnlockJoysticks();
911 SDL20_JoystickClose(joystick);
914 DECLSPEC const char * SDLCALL
915 SDL_JoystickName(int device_index)
917 return SDL20_JoystickNameForIndex(device_index);
921 SDL_JoystickIndex(SDL_Joystick *joystick)
925 SDL20_LockJoysticks(); {
926 for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
927 if (JoystickOpenList[i].joystick == joystick) {
932 if (i < SDL_arraysize(JoystickOpenList)) {
933 SDL20_UnlockJoysticks();
934 return JoystickOpenList[i].device_index;
938 SDL20_UnlockJoysticks();
939 return SDL20_SetError("Can't find joystick");
942 DECLSPEC int SDLCALL SDL_JoystickOpened(int device_index)
946 SDL20_LockJoysticks();
947 for (i = 0; i < SDL_arraysize(JoystickOpenList); i++) {
948 if ((JoystickOpenList[i].joystick) && (JoystickOpenList[i].device_index == device_index)) {
953 SDL20_UnlockJoysticks();
960 FIXME("cache this value during SDL_Init() so it doesn't change.");
961 const char *variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY");
963 variable = SDL20_getenv("SDL_VIDEO_FULLSCREEN_HEAD");
966 return SDL20_atoi(variable);
972 /* This sets up VideoModes and VideoModesCount. You end up with arrays by pixel
973 format, each with a value that 1.2's SDL_ListModes() can return. */
977 const int total = SDL20_GetNumDisplayModes(VideoDisplayIndex);
978 VideoModeList *vmode = NULL;
983 if (VideoModesCount > 0) {
984 return 0; // already did this.
987 SDL_assert(VideoModes == NULL);
989 for (i = 0; i < total; ++i) {
990 SDL_DisplayMode mode;
992 if (SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode) == -1) {
994 } else if (!mode.w || !mode.h) {
995 SDL_assert(0 && "Can this actually happen?");
999 if (!vmode || (mode.format != vmode->format)) { // SDL20_GetDisplayMode() sorts on bpp first. We know when to change arrays.
1000 if (VideoModesCount > 0) {
1001 VideoModes[VideoModesCount-1].modes12[num_modes] = NULL;
1003 ptr = (VideoModeList *) SDL20_realloc(VideoModes, sizeof (VideoModeList) * (VideoModesCount+1));
1005 return SDL20_OutOfMemory();
1007 VideoModes = (VideoModeList *) ptr;
1008 vmode = &VideoModes[VideoModesCount];
1009 vmode->format = mode.format;
1010 vmode->modeslist12 = NULL;
1011 vmode->modes12 = NULL;
1016 /* make sure we don't have this one already (with a different refresh rate, etc). */
1017 for (j = 0; j < num_modes; j++) {
1018 if ((vmode->modeslist12[j].w == mode.w) && (vmode->modeslist12[j].h == mode.h)) {
1023 if (j < num_modes) {
1024 continue; /* already have this one. */
1027 FIXME("Make sure mode dimensions fit in 16-bits for SDL12_Rect");
1029 ptr = SDL20_realloc(vmode->modes12, sizeof (SDL12_Rect *) * (num_modes + 2));
1031 return SDL20_OutOfMemory();
1033 vmode->modes12 = (SDL12_Rect **) ptr;
1035 ptr = SDL20_realloc(vmode->modeslist12, sizeof (SDL12_Rect) * (num_modes + 1));
1037 return SDL20_OutOfMemory();
1039 vmode->modeslist12 = (SDL12_Rect *) ptr;
1041 vmode->modeslist12[num_modes].x = 0;
1042 vmode->modeslist12[num_modes].y = 0;
1043 vmode->modeslist12[num_modes].w = mode.w;
1044 vmode->modeslist12[num_modes].h = mode.h;
1046 vmode->modes12[num_modes] = &vmode->modeslist12[num_modes];
1051 if (VideoModesCount > 0) {
1052 VideoModes[VideoModesCount-1].modes12[num_modes] = NULL;
1063 for (i = 0; i < SDL12_MAXEVENTS-1; i++)
1064 EventQueuePool[i].next = &EventQueuePool[i+1];
1065 EventQueuePool[SDL12_MAXEVENTS-1].next = NULL;
1067 EventQueueHead = EventQueueTail = NULL;
1068 EventQueueAvailable = EventQueuePool;
1070 SDL_memset(EventStates, SDL_ENABLE, sizeof (EventStates)); /* on by default */
1071 EventStates[SDL12_SYSWMEVENT] = SDL_IGNORE; /* off by default. */
1073 SDL20_SetEventFilter(EventFilter20to12, NULL);
1075 VideoDisplayIndex = GetVideoDisplay();
1078 if (Init12VidModes() == -1) {
1086 DECLSPEC int SDLCALL
1087 SDL_InitSubSystem(Uint32 sdl12flags)
1089 FIXME("there is never a parachute in SDL2, should we catch segfaults ourselves?");
1091 FIXME("support event thread where it makes sense to do so?");
1093 if ( (sdl12flags & SDL12_INIT_EVENTTHREAD) == SDL12_INIT_EVENTTHREAD ) {
1094 return SDL20_SetError("OS doesn't support threaded events");
1097 Uint32 sdl20flags = 0;
1104 extern void sdl12_compat_macos_init(void);
1105 sdl12_compat_macos_init();
1108 #define SETFLAG(flag) if (sdl12flags & SDL12_INIT_##flag) sdl20flags |= SDL_INIT_##flag
1113 SETFLAG(NOPARACHUTE);
1116 // There's no CDROM in 2.0, but we'll just pretend it succeeded.
1117 if (sdl12flags & SDL12_INIT_CDROM)
1120 FIXME("do something about SDL12_INIT_EVENTTHREAD");
1122 rc = SDL20_Init(sdl20flags);
1123 if ((rc == 0) && (sdl20flags & SDL_INIT_VIDEO)) {
1124 if (Init12Video() == -1) {
1125 FIXME("should we deinit other subsystems?");
1133 DECLSPEC int SDLCALL
1134 SDL_Init(Uint32 sdl12flags)
1136 FIXME("what was different in 1.2?");
1137 return SDL_InitSubSystem(sdl12flags); /* there's no difference betwee Init and InitSubSystem in SDL2. */
1142 InitFlags12To20(const Uint32 flags12, Uint32 *_flags20, Uint32 *_extraflags)
1145 Uint32 extraflags = 0;
1147 #define SETFLAG(flag) if (flags12 & SDL12_INIT_##flag) flags20 |= SDL_INIT_##flag
1152 SETFLAG(NOPARACHUTE);
1155 if ((flags12 & SDL12_INIT_CDROM) && (CDRomInit)) {
1156 extraflags |= SDL12_INIT_CDROM;
1159 FIXME("do something about SDL12_INIT_EVENTTHREAD");
1161 *_flags20 = flags20;
1162 *_extraflags = extraflags;
1166 InitFlags20to12(const Uint32 flags20)
1170 #define SETFLAG(flag) if (flags20 & SDL_INIT_##flag) flags12 |= SDL12_INIT_##flag
1175 SETFLAG(NOPARACHUTE);
1182 DECLSPEC Uint32 SDLCALL
1183 SDL_WasInit(Uint32 sdl12flags)
1185 Uint32 sdl20flags, extraflags;
1186 InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
1188 return InitFlags20to12(SDL20_WasInit(sdl20flags)) | extraflags;
1196 for (i = 0; i < VideoModesCount; i++) {
1197 SDL20_free(VideoModes[i].modeslist12);
1198 SDL20_free(VideoModes[i].modes12);
1200 SDL20_free(VideoModes);
1202 SDL20_FreeFormat(VideoInfo12.vfmt);
1203 SDL20_zero(VideoInfo12);
1205 EventFilter12 = NULL;
1206 EventQueueAvailable = EventQueueHead = EventQueueTail = NULL;
1207 CurrentCursor12 = NULL;
1209 VideoModesCount = 0;
1212 DECLSPEC void SDLCALL
1213 SDL_QuitSubSystem(Uint32 sdl12flags)
1215 Uint32 sdl20flags, extraflags;
1216 InitFlags12To20(sdl12flags, &sdl20flags, &extraflags);
1218 if (extraflags & SDL12_INIT_CDROM) {
1222 FIXME("reset a bunch of other global variables too.");
1223 if (sdl12flags & SDL12_INIT_VIDEO) {
1227 FIXME("do something about SDL12_INIT_EVENTTHREAD");
1228 SDL20_QuitSubSystem(sdl20flags);
1230 if ((SDL20_WasInit(0) == 0) && (!CDRomInit)) {
1236 DECLSPEC void SDLCALL
1239 SDL_QuitSubSystem(SDL_WasInit(0) | SDL12_INIT_CDROM);
1242 DECLSPEC void SDLCALL
1243 SDL_SetError(const char *fmt, ...)
1250 if (!LoadSDL20()) { /* SDL_SetError gets called before init sometimes. */
1255 len = SDL20_vsnprintf(&ch, 1, fmt, ap);
1258 str = (char *) SDL20_malloc(len + 1);
1260 SDL20_OutOfMemory();
1264 SDL20_vsnprintf(str, len + 1, fmt, ap);
1266 SDL20_SetError("%s", str);
1271 DECLSPEC const char * SDLCALL
1274 if (SDL20_GetError == NULL)
1276 static const char noload_errstr[] = "The SDL 2.0 library that the 1.2 compatibility layer needs isn't loaded";
1277 return noload_errstr;
1279 return SDL20_GetError();
1284 GetDriverName(const char *name, char *namebuf, int maxlen)
1288 SDL20_strlcpy(namebuf, name, maxlen);
1297 DECLSPEC const char * SDLCALL
1298 SDL_AudioDriverName(char *namebuf, int maxlen)
1300 return GetDriverName(SDL20_GetCurrentAudioDriver(), namebuf, maxlen);
1303 DECLSPEC const char * SDLCALL
1304 SDL_VideoDriverName(char *namebuf, int maxlen)
1306 return GetDriverName(SDL20_GetCurrentVideoDriver(), namebuf, maxlen);
1309 DECLSPEC int SDLCALL
1310 SDL_PollEvent(SDL12_Event *event12)
1312 EventQueueType *next;
1314 SDL20_PumpEvents(); /* this will run our filter and build our 1.2 queue. */
1316 if (EventQueueHead == NULL)
1317 return 0; /* no events at the moment. */
1319 SDL_memcpy(event12, &EventQueueHead->event12, sizeof (SDL12_Event));
1320 next = EventQueueHead->next;
1321 EventQueueHead->next = EventQueueAvailable;
1322 EventQueueAvailable = EventQueueHead;
1323 EventQueueHead = next;
1325 EventQueueTail = NULL;
1331 DECLSPEC int SDLCALL
1332 SDL_PushEvent(SDL12_Event *event12)
1334 EventQueueType *item = EventQueueAvailable;
1336 return -1; /* no space available at the moment. */
1338 EventQueueAvailable = item->next;
1340 EventQueueTail->next = item;
1342 EventQueueHead = EventQueueTail = item;
1345 SDL_memcpy(&item->event12, event12, sizeof (SDL12_Event));
1349 DECLSPEC int SDLCALL
1350 SDL_PeepEvents(SDL12_Event *events12, int numevents, SDL_eventaction action, Uint32 mask)
1352 if (action == SDL_ADDEVENT)
1355 for (i = 0; i < numevents; i++)
1357 if (SDL_PushEvent(&events12[i]) == -1)
1358 break; /* out of space for more events. */
1362 else if ((action == SDL_PEEKEVENT) || (action == SDL_GETEVENT))
1364 const SDL_bool isGet = (action == SDL_GETEVENT);
1365 EventQueueType *prev = NULL;
1366 EventQueueType *item = EventQueueHead;
1367 EventQueueType *next = NULL;
1369 while (chosen < numevents)
1371 EventQueueType *nextPrev = item;
1373 break; /* no more events at the moment. */
1375 next = item->next; /* copy, since we might overwrite item->next */
1377 if (mask & (1<<item->event12.type))
1379 SDL_memcpy(&events12[chosen++], &item->event12, sizeof (SDL12_Event));
1380 if (isGet) /* remove from list? */
1384 if (item == EventQueueHead)
1385 EventQueueHead = next;
1386 if (item == EventQueueTail)
1387 EventQueueTail = prev;
1389 /* put it back in the free pool. */
1390 item->next = EventQueueAvailable;
1391 EventQueueAvailable = item;
1392 nextPrev = prev; /* previous item doesn't change. */
1405 DECLSPEC int SDLCALL
1406 SDL_WaitEvent(SDL12_Event *event12)
1408 FIXME("In 1.2, this only fails (-1) if you haven't SDL_Init()'d.");
1409 while (!SDL_PollEvent(event12))
1415 PushEventIfNotFiltered(SDL12_Event *event12)
1417 if (event12->type != SDL12_NOEVENT)
1419 if (EventStates[event12->type] != SDL_IGNORE)
1421 if ((!EventFilter12) || (EventFilter12(event12)))
1422 return (SDL_PushEvent(event12) == 0);
1428 DECLSPEC Uint8 SDLCALL
1429 SDL_EventState(Uint8 type, int state)
1431 /* the values of "state" match between 1.2 and 2.0 */
1432 const Uint8 retval = EventStates[type];
1435 if (state != SDL_QUERY)
1436 EventStates[type] = state;
1437 if (state == SDL_IGNORE) /* drop existing events of this type. */
1438 while (SDL_PeepEvents(&e, 1, SDL_GETEVENT, (1<<type))) {}
1443 DECLSPEC Uint8 SDLCALL
1444 SDL_GetMouseState(int *x, int *y)
1446 const Uint32 state20 = SDL20_GetMouseState(x, y);
1447 Uint8 retval = (state20 & 0x7); /* left, right, and middle will match. */
1449 /* the X[12] buttons are different in 1.2; mousewheel was in the way. */
1450 if (state20 & SDL_BUTTON(SDL_BUTTON_X1))
1452 if (state20 & SDL_BUTTON(SDL_BUTTON_X2))
1458 DECLSPEC char * SDLCALL
1459 SDL_GetKeyName(SDL12Key key)
1462 #define CASESDLK12TONAME(k, n) case k: return (char *) n
1463 CASESDLK12TONAME(SDLK12_BACKSPACE, "backspace");
1464 CASESDLK12TONAME(SDLK12_TAB, "tab");
1465 CASESDLK12TONAME(SDLK12_CLEAR, "clear");
1466 CASESDLK12TONAME(SDLK12_RETURN, "return");
1467 CASESDLK12TONAME(SDLK12_PAUSE, "pause");
1468 CASESDLK12TONAME(SDLK12_ESCAPE, "escape");
1469 CASESDLK12TONAME(SDLK12_SPACE, "space");
1470 CASESDLK12TONAME(SDLK12_EXCLAIM, "!");
1471 CASESDLK12TONAME(SDLK12_QUOTEDBL, "\"");
1472 CASESDLK12TONAME(SDLK12_HASH, "#");
1473 CASESDLK12TONAME(SDLK12_DOLLAR, "$");
1474 CASESDLK12TONAME(SDLK12_AMPERSAND, "&");
1475 CASESDLK12TONAME(SDLK12_QUOTE, "'");
1476 CASESDLK12TONAME(SDLK12_LEFTPAREN, "(");
1477 CASESDLK12TONAME(SDLK12_RIGHTPAREN, ")");
1478 CASESDLK12TONAME(SDLK12_ASTERISK, "*");
1479 CASESDLK12TONAME(SDLK12_PLUS, "+");
1480 CASESDLK12TONAME(SDLK12_COMMA, ",");
1481 CASESDLK12TONAME(SDLK12_MINUS, "-");
1482 CASESDLK12TONAME(SDLK12_PERIOD, ".");
1483 CASESDLK12TONAME(SDLK12_SLASH, "/");
1484 CASESDLK12TONAME(SDLK12_0, "0");
1485 CASESDLK12TONAME(SDLK12_1, "1");
1486 CASESDLK12TONAME(SDLK12_2, "2");
1487 CASESDLK12TONAME(SDLK12_3, "3");
1488 CASESDLK12TONAME(SDLK12_4, "4");
1489 CASESDLK12TONAME(SDLK12_5, "5");
1490 CASESDLK12TONAME(SDLK12_6, "6");
1491 CASESDLK12TONAME(SDLK12_7, "7");
1492 CASESDLK12TONAME(SDLK12_8, "8");
1493 CASESDLK12TONAME(SDLK12_9, "9");
1494 CASESDLK12TONAME(SDLK12_COLON, ":");
1495 CASESDLK12TONAME(SDLK12_SEMICOLON, ");");
1496 CASESDLK12TONAME(SDLK12_LESS, "<");
1497 CASESDLK12TONAME(SDLK12_EQUALS, "=");
1498 CASESDLK12TONAME(SDLK12_GREATER, ">");
1499 CASESDLK12TONAME(SDLK12_QUESTION, "?");
1500 CASESDLK12TONAME(SDLK12_AT, "@");
1501 CASESDLK12TONAME(SDLK12_LEFTBRACKET, "[");
1502 CASESDLK12TONAME(SDLK12_BACKSLASH, "\\");
1503 CASESDLK12TONAME(SDLK12_RIGHTBRACKET, "]");
1504 CASESDLK12TONAME(SDLK12_CARET, "^");
1505 CASESDLK12TONAME(SDLK12_UNDERSCORE, "_");
1506 CASESDLK12TONAME(SDLK12_BACKQUOTE, "`");
1507 CASESDLK12TONAME(SDLK12_a, "a");
1508 CASESDLK12TONAME(SDLK12_b, "b");
1509 CASESDLK12TONAME(SDLK12_c, "c");
1510 CASESDLK12TONAME(SDLK12_d, "d");
1511 CASESDLK12TONAME(SDLK12_e, "e");
1512 CASESDLK12TONAME(SDLK12_f, "f");
1513 CASESDLK12TONAME(SDLK12_g, "g");
1514 CASESDLK12TONAME(SDLK12_h, "h");
1515 CASESDLK12TONAME(SDLK12_i, "i");
1516 CASESDLK12TONAME(SDLK12_j, "j");
1517 CASESDLK12TONAME(SDLK12_k, "k");
1518 CASESDLK12TONAME(SDLK12_l, "l");
1519 CASESDLK12TONAME(SDLK12_m, "m");
1520 CASESDLK12TONAME(SDLK12_n, "n");
1521 CASESDLK12TONAME(SDLK12_o, "o");
1522 CASESDLK12TONAME(SDLK12_p, "p");
1523 CASESDLK12TONAME(SDLK12_q, "q");
1524 CASESDLK12TONAME(SDLK12_r, "r");
1525 CASESDLK12TONAME(SDLK12_s, "s");
1526 CASESDLK12TONAME(SDLK12_t, "t");
1527 CASESDLK12TONAME(SDLK12_u, "u");
1528 CASESDLK12TONAME(SDLK12_v, "v");
1529 CASESDLK12TONAME(SDLK12_w, "w");
1530 CASESDLK12TONAME(SDLK12_x, "x");
1531 CASESDLK12TONAME(SDLK12_y, "y");
1532 CASESDLK12TONAME(SDLK12_z, "z");
1533 CASESDLK12TONAME(SDLK12_DELETE, "delete");
1535 CASESDLK12TONAME(SDLK12_WORLD_0, "world 0");
1536 CASESDLK12TONAME(SDLK12_WORLD_1, "world 1");
1537 CASESDLK12TONAME(SDLK12_WORLD_2, "world 2");
1538 CASESDLK12TONAME(SDLK12_WORLD_3, "world 3");
1539 CASESDLK12TONAME(SDLK12_WORLD_4, "world 4");
1540 CASESDLK12TONAME(SDLK12_WORLD_5, "world 5");
1541 CASESDLK12TONAME(SDLK12_WORLD_6, "world 6");
1542 CASESDLK12TONAME(SDLK12_WORLD_7, "world 7");
1543 CASESDLK12TONAME(SDLK12_WORLD_8, "world 8");
1544 CASESDLK12TONAME(SDLK12_WORLD_9, "world 9");
1545 CASESDLK12TONAME(SDLK12_WORLD_10, "world 10");
1546 CASESDLK12TONAME(SDLK12_WORLD_11, "world 11");
1547 CASESDLK12TONAME(SDLK12_WORLD_12, "world 12");
1548 CASESDLK12TONAME(SDLK12_WORLD_13, "world 13");
1549 CASESDLK12TONAME(SDLK12_WORLD_14, "world 14");
1550 CASESDLK12TONAME(SDLK12_WORLD_15, "world 15");
1551 CASESDLK12TONAME(SDLK12_WORLD_16, "world 16");
1552 CASESDLK12TONAME(SDLK12_WORLD_17, "world 17");
1553 CASESDLK12TONAME(SDLK12_WORLD_18, "world 18");
1554 CASESDLK12TONAME(SDLK12_WORLD_19, "world 19");
1555 CASESDLK12TONAME(SDLK12_WORLD_20, "world 20");
1556 CASESDLK12TONAME(SDLK12_WORLD_21, "world 21");
1557 CASESDLK12TONAME(SDLK12_WORLD_22, "world 22");
1558 CASESDLK12TONAME(SDLK12_WORLD_23, "world 23");
1559 CASESDLK12TONAME(SDLK12_WORLD_24, "world 24");
1560 CASESDLK12TONAME(SDLK12_WORLD_25, "world 25");
1561 CASESDLK12TONAME(SDLK12_WORLD_26, "world 26");
1562 CASESDLK12TONAME(SDLK12_WORLD_27, "world 27");
1563 CASESDLK12TONAME(SDLK12_WORLD_28, "world 28");
1564 CASESDLK12TONAME(SDLK12_WORLD_29, "world 29");
1565 CASESDLK12TONAME(SDLK12_WORLD_30, "world 30");
1566 CASESDLK12TONAME(SDLK12_WORLD_31, "world 31");
1567 CASESDLK12TONAME(SDLK12_WORLD_32, "world 32");
1568 CASESDLK12TONAME(SDLK12_WORLD_33, "world 33");
1569 CASESDLK12TONAME(SDLK12_WORLD_34, "world 34");
1570 CASESDLK12TONAME(SDLK12_WORLD_35, "world 35");
1571 CASESDLK12TONAME(SDLK12_WORLD_36, "world 36");
1572 CASESDLK12TONAME(SDLK12_WORLD_37, "world 37");
1573 CASESDLK12TONAME(SDLK12_WORLD_38, "world 38");
1574 CASESDLK12TONAME(SDLK12_WORLD_39, "world 39");
1575 CASESDLK12TONAME(SDLK12_WORLD_40, "world 40");
1576 CASESDLK12TONAME(SDLK12_WORLD_41, "world 41");
1577 CASESDLK12TONAME(SDLK12_WORLD_42, "world 42");
1578 CASESDLK12TONAME(SDLK12_WORLD_43, "world 43");
1579 CASESDLK12TONAME(SDLK12_WORLD_44, "world 44");
1580 CASESDLK12TONAME(SDLK12_WORLD_45, "world 45");
1581 CASESDLK12TONAME(SDLK12_WORLD_46, "world 46");
1582 CASESDLK12TONAME(SDLK12_WORLD_47, "world 47");
1583 CASESDLK12TONAME(SDLK12_WORLD_48, "world 48");
1584 CASESDLK12TONAME(SDLK12_WORLD_49, "world 49");
1585 CASESDLK12TONAME(SDLK12_WORLD_50, "world 50");
1586 CASESDLK12TONAME(SDLK12_WORLD_51, "world 51");
1587 CASESDLK12TONAME(SDLK12_WORLD_52, "world 52");
1588 CASESDLK12TONAME(SDLK12_WORLD_53, "world 53");
1589 CASESDLK12TONAME(SDLK12_WORLD_54, "world 54");
1590 CASESDLK12TONAME(SDLK12_WORLD_55, "world 55");
1591 CASESDLK12TONAME(SDLK12_WORLD_56, "world 56");
1592 CASESDLK12TONAME(SDLK12_WORLD_57, "world 57");
1593 CASESDLK12TONAME(SDLK12_WORLD_58, "world 58");
1594 CASESDLK12TONAME(SDLK12_WORLD_59, "world 59");
1595 CASESDLK12TONAME(SDLK12_WORLD_60, "world 60");
1596 CASESDLK12TONAME(SDLK12_WORLD_61, "world 61");
1597 CASESDLK12TONAME(SDLK12_WORLD_62, "world 62");
1598 CASESDLK12TONAME(SDLK12_WORLD_63, "world 63");
1599 CASESDLK12TONAME(SDLK12_WORLD_64, "world 64");
1600 CASESDLK12TONAME(SDLK12_WORLD_65, "world 65");
1601 CASESDLK12TONAME(SDLK12_WORLD_66, "world 66");
1602 CASESDLK12TONAME(SDLK12_WORLD_67, "world 67");
1603 CASESDLK12TONAME(SDLK12_WORLD_68, "world 68");
1604 CASESDLK12TONAME(SDLK12_WORLD_69, "world 69");
1605 CASESDLK12TONAME(SDLK12_WORLD_70, "world 70");
1606 CASESDLK12TONAME(SDLK12_WORLD_71, "world 71");
1607 CASESDLK12TONAME(SDLK12_WORLD_72, "world 72");
1608 CASESDLK12TONAME(SDLK12_WORLD_73, "world 73");
1609 CASESDLK12TONAME(SDLK12_WORLD_74, "world 74");
1610 CASESDLK12TONAME(SDLK12_WORLD_75, "world 75");
1611 CASESDLK12TONAME(SDLK12_WORLD_76, "world 76");
1612 CASESDLK12TONAME(SDLK12_WORLD_77, "world 77");
1613 CASESDLK12TONAME(SDLK12_WORLD_78, "world 78");
1614 CASESDLK12TONAME(SDLK12_WORLD_79, "world 79");
1615 CASESDLK12TONAME(SDLK12_WORLD_80, "world 80");
1616 CASESDLK12TONAME(SDLK12_WORLD_81, "world 81");
1617 CASESDLK12TONAME(SDLK12_WORLD_82, "world 82");
1618 CASESDLK12TONAME(SDLK12_WORLD_83, "world 83");
1619 CASESDLK12TONAME(SDLK12_WORLD_84, "world 84");
1620 CASESDLK12TONAME(SDLK12_WORLD_85, "world 85");
1621 CASESDLK12TONAME(SDLK12_WORLD_86, "world 86");
1622 CASESDLK12TONAME(SDLK12_WORLD_87, "world 87");
1623 CASESDLK12TONAME(SDLK12_WORLD_88, "world 88");
1624 CASESDLK12TONAME(SDLK12_WORLD_89, "world 89");
1625 CASESDLK12TONAME(SDLK12_WORLD_90, "world 90");
1626 CASESDLK12TONAME(SDLK12_WORLD_91, "world 91");
1627 CASESDLK12TONAME(SDLK12_WORLD_92, "world 92");
1628 CASESDLK12TONAME(SDLK12_WORLD_93, "world 93");
1629 CASESDLK12TONAME(SDLK12_WORLD_94, "world 94");
1630 CASESDLK12TONAME(SDLK12_WORLD_95, "world 95");
1632 CASESDLK12TONAME(SDLK12_KP0, "[0]");
1633 CASESDLK12TONAME(SDLK12_KP1, "[1]");
1634 CASESDLK12TONAME(SDLK12_KP2, "[2]");
1635 CASESDLK12TONAME(SDLK12_KP3, "[3]");
1636 CASESDLK12TONAME(SDLK12_KP4, "[4]");
1637 CASESDLK12TONAME(SDLK12_KP5, "[5]");
1638 CASESDLK12TONAME(SDLK12_KP6, "[6]");
1639 CASESDLK12TONAME(SDLK12_KP7, "[7]");
1640 CASESDLK12TONAME(SDLK12_KP8, "[8]");
1641 CASESDLK12TONAME(SDLK12_KP9, "[9]");
1642 CASESDLK12TONAME(SDLK12_KP_PERIOD, "[.]");
1643 CASESDLK12TONAME(SDLK12_KP_DIVIDE, "[/]");
1644 CASESDLK12TONAME(SDLK12_KP_MULTIPLY, "[*]");
1645 CASESDLK12TONAME(SDLK12_KP_MINUS, "[-]");
1646 CASESDLK12TONAME(SDLK12_KP_PLUS, "[+]");
1647 CASESDLK12TONAME(SDLK12_KP_ENTER, "enter");
1648 CASESDLK12TONAME(SDLK12_KP_EQUALS, "equals");
1650 CASESDLK12TONAME(SDLK12_UP, "up");
1651 CASESDLK12TONAME(SDLK12_DOWN, "down");
1652 CASESDLK12TONAME(SDLK12_RIGHT, "right");
1653 CASESDLK12TONAME(SDLK12_LEFT, "left");
1654 CASESDLK12TONAME(SDLK12_INSERT, "insert");
1655 CASESDLK12TONAME(SDLK12_HOME, "home");
1656 CASESDLK12TONAME(SDLK12_END, "end");
1657 CASESDLK12TONAME(SDLK12_PAGEUP, "page up");
1658 CASESDLK12TONAME(SDLK12_PAGEDOWN, "page down");
1660 CASESDLK12TONAME(SDLK12_F1, "f1");
1661 CASESDLK12TONAME(SDLK12_F2, "f2");
1662 CASESDLK12TONAME(SDLK12_F3, "f3");
1663 CASESDLK12TONAME(SDLK12_F4, "f4");
1664 CASESDLK12TONAME(SDLK12_F5, "f5");
1665 CASESDLK12TONAME(SDLK12_F6, "f6");
1666 CASESDLK12TONAME(SDLK12_F7, "f7");
1667 CASESDLK12TONAME(SDLK12_F8, "f8");
1668 CASESDLK12TONAME(SDLK12_F9, "f9");
1669 CASESDLK12TONAME(SDLK12_F10, "f10");
1670 CASESDLK12TONAME(SDLK12_F11, "f11");
1671 CASESDLK12TONAME(SDLK12_F12, "f12");
1672 CASESDLK12TONAME(SDLK12_F13, "f13");
1673 CASESDLK12TONAME(SDLK12_F14, "f14");
1674 CASESDLK12TONAME(SDLK12_F15, "f15");
1676 CASESDLK12TONAME(SDLK12_NUMLOCK, "numlock");
1677 CASESDLK12TONAME(SDLK12_CAPSLOCK, "caps lock");
1678 CASESDLK12TONAME(SDLK12_SCROLLOCK, "scroll lock");
1679 CASESDLK12TONAME(SDLK12_RSHIFT, "right shift");
1680 CASESDLK12TONAME(SDLK12_LSHIFT, "left shift");
1681 CASESDLK12TONAME(SDLK12_RCTRL, "right ctrl");
1682 CASESDLK12TONAME(SDLK12_LCTRL, "left ctrl");
1683 CASESDLK12TONAME(SDLK12_RALT, "right alt");
1684 CASESDLK12TONAME(SDLK12_LALT, "left alt");
1685 CASESDLK12TONAME(SDLK12_RMETA, "right meta");
1686 CASESDLK12TONAME(SDLK12_LMETA, "left meta");
1687 CASESDLK12TONAME(SDLK12_LSUPER, "left super"); /* "Windows" keys */
1688 CASESDLK12TONAME(SDLK12_RSUPER, "right super");
1689 CASESDLK12TONAME(SDLK12_MODE, "alt gr");
1690 CASESDLK12TONAME(SDLK12_COMPOSE, "compose");
1692 CASESDLK12TONAME(SDLK12_HELP, "help");
1693 CASESDLK12TONAME(SDLK12_PRINT, "print screen");
1694 CASESDLK12TONAME(SDLK12_SYSREQ, "sys req");
1695 CASESDLK12TONAME(SDLK12_BREAK, "break");
1696 CASESDLK12TONAME(SDLK12_MENU, "menu");
1697 CASESDLK12TONAME(SDLK12_POWER, "power");
1698 CASESDLK12TONAME(SDLK12_EURO, "euro");
1699 CASESDLK12TONAME(SDLK12_UNDO, "undo");
1700 #undef CASESDLK12TONAME
1704 return (char *) "unknown key";
1708 Keysym20to12(const SDL_Keycode keysym20)
1710 if ( ((int) keysym20) < 127 ) { /* (most of) low-ASCII maps directly */
1711 if (keysym20 == SDLK_PAUSE) {
1712 return SDLK12_PAUSE;
1713 } else if (keysym20 == SDLK_CLEAR) {
1714 return SDLK12_CLEAR;
1716 return (SDL12Key) keysym20;
1720 #define CASEKEYSYM20TO12(k20, k12) case SDLK_##k20: return SDLK12_##k12
1721 CASEKEYSYM20TO12(KP_0, KP0);
1722 CASEKEYSYM20TO12(KP_1, KP1);
1723 CASEKEYSYM20TO12(KP_2, KP2);
1724 CASEKEYSYM20TO12(KP_3, KP3);
1725 CASEKEYSYM20TO12(KP_4, KP4);
1726 CASEKEYSYM20TO12(KP_5, KP5);
1727 CASEKEYSYM20TO12(KP_6, KP6);
1728 CASEKEYSYM20TO12(KP_7, KP7);
1729 CASEKEYSYM20TO12(KP_8, KP8);
1730 CASEKEYSYM20TO12(KP_9, KP9);
1731 CASEKEYSYM20TO12(NUMLOCKCLEAR, NUMLOCK);
1732 CASEKEYSYM20TO12(SCROLLLOCK, SCROLLOCK);
1733 CASEKEYSYM20TO12(RGUI, RMETA);
1734 CASEKEYSYM20TO12(LGUI, LMETA);
1735 CASEKEYSYM20TO12(PRINTSCREEN, PRINT);
1736 #undef CASEKEYSYM20TO12
1738 #define CASEKEYSYM20TO12(k) case SDLK_##k: return SDLK12_##k
1739 CASEKEYSYM20TO12(CLEAR);
1740 CASEKEYSYM20TO12(PAUSE);
1741 CASEKEYSYM20TO12(KP_PERIOD);
1742 CASEKEYSYM20TO12(KP_DIVIDE);
1743 CASEKEYSYM20TO12(KP_MULTIPLY);
1744 CASEKEYSYM20TO12(KP_MINUS);
1745 CASEKEYSYM20TO12(KP_PLUS);
1746 CASEKEYSYM20TO12(KP_ENTER);
1747 CASEKEYSYM20TO12(KP_EQUALS);
1748 CASEKEYSYM20TO12(UP);
1749 CASEKEYSYM20TO12(DOWN);
1750 CASEKEYSYM20TO12(RIGHT);
1751 CASEKEYSYM20TO12(LEFT);
1752 CASEKEYSYM20TO12(INSERT);
1753 CASEKEYSYM20TO12(HOME);
1754 CASEKEYSYM20TO12(END);
1755 CASEKEYSYM20TO12(PAGEUP);
1756 CASEKEYSYM20TO12(PAGEDOWN);
1757 CASEKEYSYM20TO12(F1);
1758 CASEKEYSYM20TO12(F2);
1759 CASEKEYSYM20TO12(F3);
1760 CASEKEYSYM20TO12(F4);
1761 CASEKEYSYM20TO12(F5);
1762 CASEKEYSYM20TO12(F6);
1763 CASEKEYSYM20TO12(F7);
1764 CASEKEYSYM20TO12(F8);
1765 CASEKEYSYM20TO12(F9);
1766 CASEKEYSYM20TO12(F10);
1767 CASEKEYSYM20TO12(F11);
1768 CASEKEYSYM20TO12(F12);
1769 CASEKEYSYM20TO12(F13);
1770 CASEKEYSYM20TO12(F14);
1771 CASEKEYSYM20TO12(F15);
1772 CASEKEYSYM20TO12(CAPSLOCK);
1773 CASEKEYSYM20TO12(RSHIFT);
1774 CASEKEYSYM20TO12(LSHIFT);
1775 CASEKEYSYM20TO12(RCTRL);
1776 CASEKEYSYM20TO12(LCTRL);
1777 CASEKEYSYM20TO12(RALT);
1778 CASEKEYSYM20TO12(LALT);
1779 CASEKEYSYM20TO12(MODE);
1780 CASEKEYSYM20TO12(HELP);
1781 CASEKEYSYM20TO12(SYSREQ);;
1782 CASEKEYSYM20TO12(MENU);
1783 CASEKEYSYM20TO12(POWER);
1784 CASEKEYSYM20TO12(UNDO);
1785 #undef CASEKEYSYM20TO12
1789 FIXME("nothing maps to SDLK12_COMPOSE, SDLK12_BREAK, or SDLK12_EURO ...?");
1790 FIXME("map some of the SDLK12_WORLD keys");
1791 return SDLK12_UNKNOWN;
1795 EventFilter20to12(void *data, SDL_Event *event20)
1797 //const int maxUserEvents12 = SDL12_NUMEVENTS - SDL12_USEREVENT;
1798 SDL12_Event event12;
1801 SDL_assert(data == NULL); /* currently unused. */
1803 SDL20_zero(event12);
1805 switch (event20->type)
1808 event12.type = SDL12_QUIT;
1811 case SDL_WINDOWEVENT:
1812 switch (event20->window.event)
1814 case SDL_WINDOWEVENT_CLOSE:
1815 event12.type = SDL12_QUIT;
1818 case SDL_WINDOWEVENT_SHOWN:
1819 case SDL_WINDOWEVENT_EXPOSED:
1820 event12.type = SDL12_VIDEOEXPOSE;
1823 case SDL_WINDOWEVENT_RESIZED:
1824 case SDL_WINDOWEVENT_SIZE_CHANGED:
1825 FIXME("what's the difference between RESIZED and SIZE_CHANGED?");
1826 event12.type = SDL12_VIDEORESIZE;
1827 event12.resize.w = event20->window.data1;
1828 event12.resize.h = event20->window.data2;
1831 case SDL_WINDOWEVENT_MINIMIZED:
1832 event12.type = SDL12_ACTIVEEVENT;
1833 event12.active.gain = 0;
1834 event12.active.state = SDL12_APPACTIVE;
1837 case SDL_WINDOWEVENT_RESTORED:
1838 event12.type = SDL12_ACTIVEEVENT;
1839 event12.active.gain = 1;
1840 event12.active.state = SDL12_APPACTIVE;
1843 case SDL_WINDOWEVENT_ENTER:
1844 event12.type = SDL12_ACTIVEEVENT;
1845 event12.active.gain = 1;
1846 event12.active.state = SDL12_APPMOUSEFOCUS;
1849 case SDL_WINDOWEVENT_LEAVE:
1850 event12.type = SDL12_ACTIVEEVENT;
1851 event12.active.gain = 0;
1852 event12.active.state = SDL12_APPMOUSEFOCUS;
1855 case SDL_WINDOWEVENT_FOCUS_GAINED:
1856 event12.type = SDL12_ACTIVEEVENT;
1857 event12.active.gain = 1;
1858 event12.active.state = SDL12_APPINPUTFOCUS;
1861 case SDL_WINDOWEVENT_FOCUS_LOST:
1862 event12.type = SDL12_ACTIVEEVENT;
1863 event12.active.gain = 0;
1864 event12.active.state = SDL12_APPINPUTFOCUS;
1869 // !!! FIXME: this is sort of a mess to convert.
1870 case SDL_SYSWMEVENT: FIXME("write me"); return 0;
1874 if (event20->key.repeat) {
1875 return 0; /* ignore 2.0-style key repeat events */
1877 event12.key.keysym.sym = Keysym20to12(event20->key.keysym.sym);
1878 if (event12.key.keysym.sym == SDLK12_UNKNOWN) {
1879 return 0; /* drop it if we can't map it */
1881 event12.type = (event20->type == SDL_KEYDOWN) ? SDL12_KEYDOWN : SDL12_KEYUP;
1882 event12.key.which = 0;
1883 event12.key.state = event20->key.state;
1884 event12.key.keysym.scancode = (event20->key.keysym.scancode < 256) ? (Uint8) event20->key.keysym.scancode : 0;
1885 event12.key.keysym.mod = event20->key.keysym.mod; /* these match up between 1.2 and 2.0! */
1886 event12.key.keysym.unicode = 0; FIXME("unicode");
1889 case SDL_TEXTEDITING: FIXME("write me"); return 0;
1890 case SDL_TEXTINPUT: FIXME("write me"); return 0;
1892 case SDL_MOUSEMOTION:
1893 event12.type = SDL12_MOUSEMOTION;
1894 event12.motion.which = (Uint8) event20->motion.which;
1895 event12.motion.state = event20->motion.state;
1896 event12.motion.x = (Uint16) event20->motion.x;
1897 event12.motion.y = (Uint16) event20->motion.y;
1898 event12.motion.xrel = (Sint16) event20->motion.xrel;
1899 event12.motion.yrel = (Sint16) event20->motion.yrel;
1902 case SDL_MOUSEBUTTONDOWN:
1903 event12.type = SDL12_MOUSEBUTTONDOWN;
1904 event12.button.which = (Uint8) event20->button.which;
1905 event12.button.button = event20->button.button;
1906 event12.button.state = event20->button.state;
1907 event12.button.x = (Uint16) event20->button.x;
1908 event12.button.y = (Uint16) event20->button.y;
1911 case SDL_MOUSEBUTTONUP:
1912 event12.type = SDL12_MOUSEBUTTONUP;
1913 event12.button.which = (Uint8) event20->button.which;
1914 event12.button.button = event20->button.button;
1915 event12.button.state = event20->button.state;
1916 event12.button.x = (Uint16) event20->button.x;
1917 event12.button.y = (Uint16) event20->button.y;
1920 case SDL_MOUSEWHEEL:
1921 if (event20->wheel.y == 0)
1922 break; /* don't support horizontal wheels in 1.2. */
1924 event12.type = SDL12_MOUSEBUTTONDOWN;
1925 event12.button.which = (Uint8) event20->wheel.which;
1926 event12.button.button = (event20->wheel.y > 0) ? 4 : 5; /* wheelup is 4, down is 5. */
1927 event12.button.state = SDL_GetMouseState(&x, &y);
1928 event12.button.x = (Uint16) x;
1929 event12.button.y = (Uint16) y;
1930 PushEventIfNotFiltered(&event12);
1932 event12.type = SDL12_MOUSEBUTTONUP; /* immediately release mouse "button" at the end of this switch. */
1935 case SDL_JOYAXISMOTION:
1936 event12.type = SDL12_JOYAXISMOTION;
1937 event12.jaxis.which = (Uint8) event20->jaxis.which;
1938 event12.jaxis.axis = event20->jaxis.axis;
1939 event12.jaxis.value = event20->jaxis.value;
1942 case SDL_JOYBALLMOTION:
1943 event12.type = SDL12_JOYBALLMOTION;
1944 event12.jball.which = (Uint8) event20->jball.which;
1945 event12.jball.ball = event20->jball.ball;
1946 event12.jball.xrel = event20->jball.xrel;
1947 event12.jball.yrel = event20->jball.yrel;
1950 case SDL_JOYHATMOTION:
1951 event12.type = SDL12_JOYHATMOTION;
1952 event12.jhat.which = (Uint8) event20->jhat.which;
1953 event12.jhat.hat = event20->jhat.hat;
1954 event12.jhat.value = event20->jhat.value;
1957 case SDL_JOYBUTTONDOWN:
1958 event12.type = SDL12_JOYBUTTONDOWN;
1959 event12.jbutton.which = (Uint8) event20->jbutton.which;
1960 event12.jbutton.button = event20->jbutton.button;
1961 event12.jbutton.state = event20->jbutton.state;
1964 case SDL_JOYBUTTONUP:
1965 event12.type = SDL12_JOYBUTTONUP;
1966 event12.jbutton.which = (Uint8) event20->jbutton.which;
1967 event12.jbutton.button = event20->jbutton.button;
1968 event12.jbutton.state = event20->jbutton.state;
1971 //case SDL_JOYDEVICEADDED:
1972 //case SDL_JOYDEVICEREMOVED:
1973 //case SDL_CONTROLLERAXISMOTION:
1974 //case SDL_CONTROLLERBUTTONDOWN:
1975 //case SDL_CONTROLLERBUTTONUP:
1976 //case SDL_CONTROLLERDEVICEADDED:
1977 //case SDL_CONTROLLERDEVICEREMOVED:
1978 //case SDL_CONTROLLERDEVICEREMAPPED:
1979 //case SDL_FINGERDOWN:
1980 //case SDL_FINGERUP:
1981 //case SDL_FINGERMOTION:
1982 //case SDL_DOLLARGESTURE:
1983 //case SDL_DOLLARRECORD:
1984 //case SDL_MULTIGESTURE:
1985 //case SDL_CLIPBOARDUPDATE:
1986 //case SDL_DROPFILE:
1989 return 0; /* drop everything else. */
1992 PushEventIfNotFiltered(&event12);
1994 return 0; /* always drop it from the 2.0 event queue. */
1997 DECLSPEC void SDLCALL
1998 SDL_SetEventFilter(SDL12_EventFilter filter12)
2000 /* We always have a filter installed, but will call the app's too. */
2001 EventFilter12 = filter12;
2004 DECLSPEC SDL12_EventFilter SDLCALL
2005 SDL_GetEventFilter(void)
2007 return EventFilter12;
2012 Rect20to12(const SDL_Rect *rect20, SDL12_Rect *rect12)
2014 rect12->x = (Sint16) rect20->x;
2015 rect12->y = (Sint16) rect20->y;
2016 rect12->w = (Uint16) rect20->w;
2017 rect12->h = (Uint16) rect20->h;
2022 Rect12to20(const SDL12_Rect *rect12, SDL_Rect *rect20)
2024 rect20->x = (int) rect12->x;
2025 rect20->y = (int) rect12->y;
2026 rect20->w = (int) rect12->w;
2027 rect20->h = (int) rect12->h;
2031 static SDL12_Surface *
2032 Surface20to12(SDL_Surface *surface20)
2034 SDL12_Surface *surface12 = NULL;
2035 SDL12_Palette *palette12 = NULL;
2036 SDL12_PixelFormat *format12 = NULL;
2042 surface12 = (SDL12_Surface *) SDL20_malloc(sizeof (SDL12_Surface));
2046 if (surface20->format->palette) {
2047 palette12 = (SDL12_Palette *) SDL20_malloc(sizeof (SDL12_Palette));
2052 format12 = (SDL12_PixelFormat *) SDL20_malloc(sizeof (SDL12_PixelFormat));
2057 SDL20_zerop(palette12);
2058 SDL_assert(surface20->format->palette);
2059 palette12->ncolors = surface20->format->palette->ncolors;
2060 palette12->colors = surface20->format->palette->colors;
2063 SDL20_zerop(format12);
2064 format12->palette = palette12;
2065 format12->BitsPerPixel = surface20->format->BitsPerPixel;
2066 format12->BytesPerPixel = surface20->format->BytesPerPixel;
2067 format12->Rloss = surface20->format->Rloss;
2068 format12->Gloss = surface20->format->Gloss;
2069 format12->Bloss = surface20->format->Bloss;
2070 format12->Aloss = surface20->format->Aloss;
2071 format12->Rshift = surface20->format->Rshift;
2072 format12->Gshift = surface20->format->Gshift;
2073 format12->Bshift = surface20->format->Bshift;
2074 format12->Ashift = surface20->format->Ashift;
2075 format12->Rmask = surface20->format->Rmask;
2076 format12->Gmask = surface20->format->Gmask;
2077 format12->Bmask = surface20->format->Bmask;
2078 format12->Amask = surface20->format->Amask;
2079 FIXME("format12->colorkey");
2080 FIXME("format12->alpha");
2082 SDL20_zerop(surface12);
2083 flags = surface20->flags;
2084 #ifdef SDL_SIMD_ALIGNED
2085 flags &= ~SDL_SIMD_ALIGNED; /* we don't need to map this to 1.2 */
2087 #define MAPSURFACEFLAGS(fl) { if (surface20->flags & SDL_##fl) { surface12->flags |= SDL12_##fl; flags &= ~SDL_##fl; } }
2088 MAPSURFACEFLAGS(PREALLOC);
2089 MAPSURFACEFLAGS(RLEACCEL);
2090 /*MAPSURFACEFLAGS(DONTFREE);*/
2091 #undef MAPSURFACEFLAGS
2092 SDL_assert(flags == 0); /* non-zero if there's a flag we didn't map. */
2094 surface12->format = format12;
2095 surface12->w = surface20->w;
2096 surface12->h = surface20->h;
2097 surface12->pitch = (Uint16) surface20->pitch; FIXME("make sure this fits in a Uint16");
2098 surface12->pixels = surface20->pixels;
2099 surface12->offset = 0;
2100 surface12->surface20 = surface20;
2101 Rect20to12(&surface20->clip_rect, &surface12->clip_rect);
2102 surface12->refcount = surface20->refcount;
2107 SDL20_free(surface12);
2108 SDL20_free(palette12);
2109 SDL20_free(format12);
2113 DECLSPEC SDL12_Surface * SDLCALL
2114 SDL_CreateRGBSurface(Uint32 sdl12flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
2116 SDL_Surface *surface20 = SDL20_CreateRGBSurface(0, width, height, depth, Rmask, Gmask, Bmask, Amask);
2117 SDL12_Surface *surface12 = Surface20to12(surface20);
2119 SDL20_FreeSurface(surface20);
2123 SDL_assert(surface12->flags == 0); // shouldn't have prealloc, rleaccel, or dontfree.
2127 DECLSPEC SDL12_Surface * SDLCALL
2128 SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
2130 SDL_Surface *surface20 = SDL20_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
2131 SDL12_Surface *surface12 = Surface20to12(surface20);
2133 SDL20_FreeSurface(surface20);
2137 SDL_assert(surface12->flags == SDL12_PREALLOC); // should _only_ have prealloc.
2141 DECLSPEC void SDLCALL
2142 SDL_FreeSurface(SDL12_Surface *surface12)
2145 SDL20_FreeSurface(surface12->surface20);
2146 if (surface12->format) {
2147 SDL20_free(surface12->format->palette);
2148 SDL20_free(surface12->format);
2150 SDL20_free(surface12);
2154 DECLSPEC void SDLCALL
2155 SDL_GetClipRect(SDL12_Surface *surface12, SDL12_Rect *rect)
2157 if (surface12 && rect) {
2158 SDL_memcpy(rect, &surface12->clip_rect, sizeof (SDL12_Rect));
2162 DECLSPEC SDL_bool SDLCALL
2163 SDL_SetClipRect(SDL12_Surface *surface12, const SDL12_Rect *rect12)
2165 SDL_bool retval = SDL_FALSE;
2169 retval = SDL20_SetClipRect(surface12->surface20, rect12 ? Rect12to20(rect12, &rect20) : NULL);
2170 SDL20_GetClipRect(surface12->surface20, &rect20);
2171 Rect20to12(&rect20, &surface12->clip_rect);
2176 DECLSPEC int SDLCALL
2177 SDL_FillRect(SDL12_Surface *dst, SDL12_Rect *dstrect12, Uint32 color)
2180 const int retval = SDL20_FillRect(dst->surface20, dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL, color);
2183 if (dstrect12) { /* 1.2 stores the clip intersection in dstrect */
2184 SDL_Rect intersected20;
2185 SDL20_IntersectRect(&dstrect20, &dst->surface20->clip_rect, &intersected20);
2186 Rect20to12(&intersected20, dstrect12);
2193 static SDL_PixelFormat *
2194 PixelFormat12to20(SDL_PixelFormat *format20, SDL_Palette *palette20, const SDL12_PixelFormat *format12)
2196 if (format12->palette) {
2197 palette20->ncolors = format12->palette->ncolors;
2198 palette20->colors = format12->palette->colors;
2199 palette20->version = 1;
2200 palette20->refcount = 1;
2201 format20->palette = palette20;
2203 format20->palette = NULL;
2206 format20->format = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
2207 format20->BitsPerPixel = format12->BitsPerPixel;
2208 format20->BytesPerPixel = format12->BytesPerPixel;
2209 format20->Rmask = format12->Rmask;
2210 format20->Gmask = format12->Gmask;
2211 format20->Bmask = format12->Bmask;
2212 format20->Amask = format12->Amask;
2213 format20->Rloss = format12->Rloss;
2214 format20->Gloss = format12->Gloss;
2215 format20->Bloss = format12->Bloss;
2216 format20->Aloss = format12->Aloss;
2217 format20->Rshift = format12->Rshift;
2218 format20->Gshift = format12->Gshift;
2219 format20->Bshift = format12->Bshift;
2220 format20->Ashift = format12->Ashift;
2221 format20->refcount = 1;
2222 format20->next = NULL;
2226 DECLSPEC Uint32 SDLCALL
2227 SDL_MapRGB(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b)
2229 /* This is probably way slower than apps expect. */
2230 SDL_PixelFormat format20;
2231 SDL_Palette palette20;
2232 return SDL20_MapRGB(PixelFormat12to20(&format20, &palette20, format12), r, g, b);
2235 DECLSPEC Uint32 SDLCALL
2236 SDL_MapRGBA(const SDL12_PixelFormat *format12, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2238 /* This is probably way slower than apps expect. */
2239 SDL_PixelFormat format20;
2240 SDL_Palette palette20;
2241 return SDL20_MapRGBA(PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
2244 DECLSPEC void SDLCALL
2245 SDL_GetRGB(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b)
2247 /* This is probably way slower than apps expect. */
2248 SDL_PixelFormat format20;
2249 SDL_Palette palette20;
2250 return SDL20_GetRGB(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b);
2253 DECLSPEC void SDLCALL
2254 SDL_GetRGBA(Uint32 pixel, const SDL12_PixelFormat *format12, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
2256 /* This is probably way slower than apps expect. */
2257 SDL_PixelFormat format20;
2258 SDL_Palette palette20;
2259 return SDL20_GetRGBA(pixel, PixelFormat12to20(&format20, &palette20, format12), r, g, b, a);
2262 DECLSPEC const SDL12_VideoInfo * SDLCALL
2263 SDL_GetVideoInfo(void)
2265 SDL_DisplayMode mode;
2267 FIXME("calculate this in Init12Video(), then this just does: return VideoInfo.vfmt ? &VideoInfo : NULL;");
2269 if (!VideoInfo12.vfmt && SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode) == 0) {
2270 VideoInfo12.vfmt = SDL20_AllocFormat(mode.format);
2271 VideoInfo12.current_w = mode.w;
2272 VideoInfo12.current_h = mode.h;
2273 FIXME("vidinfo details commented out");
2274 //VideoInfo12.wm_available = 1;
2275 //VideoInfo12.video_mem = 1024 * 256;
2277 return &VideoInfo12;
2280 DECLSPEC int SDLCALL
2281 SDL_VideoModeOK(int width, int height, int bpp, Uint32 sdl12flags)
2283 int i, nummodes, actual_bpp = 0;
2285 if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
2289 if (!(sdl12flags & SDL12_FULLSCREEN)) {
2290 SDL_DisplayMode mode;
2291 SDL20_GetDesktopDisplayMode(VideoDisplayIndex, &mode);
2292 return SDL_BITSPERPIXEL(mode.format);
2295 nummodes = SDL20_GetNumDisplayModes(VideoDisplayIndex);
2296 for (i = 0; i < nummodes; ++i) {
2297 SDL_DisplayMode mode;
2298 SDL20_GetDisplayMode(VideoDisplayIndex, i, &mode);
2299 if (!mode.w || !mode.h || (width == mode.w && height == mode.h)) {
2303 if (SDL_BITSPERPIXEL(mode.format) >= (Uint32) bpp) {
2304 actual_bpp = SDL_BITSPERPIXEL(mode.format);
2311 DECLSPEC SDL12_Rect ** SDLCALL
2312 SDL_ListModes(const SDL12_PixelFormat *format12, Uint32 flags)
2317 if (!SDL20_WasInit(SDL_INIT_VIDEO)) {
2321 if ((!format12) && (!VideoInfo12.vfmt)) {
2322 SDL20_SetError("No pixel format specified");
2326 if (!(flags & SDL12_FULLSCREEN)) {
2327 return (SDL12_Rect **) (-1); /* any resolution is fine. */
2331 fmt = SDL20_MasksToPixelFormatEnum(format12->BitsPerPixel, format12->Rmask, format12->Gmask, format12->Bmask, format12->Amask);
2333 fmt = VideoInfo12.vfmt->format;
2336 for (i = 0; i < VideoModesCount; i++) {
2337 VideoModeList *modes = &VideoModes[i];
2338 if (modes->format == fmt) {
2339 return modes->modes12;
2343 SDL20_SetError("No modes support requested pixel format");
2347 DECLSPEC void SDLCALL
2348 SDL_FreeCursor(SDL12_Cursor *cursor12)
2351 if (cursor12->wm_cursor)
2352 SDL20_FreeCursor(cursor12->wm_cursor);
2353 SDL20_free(cursor12->data);
2354 SDL20_free(cursor12->mask);
2355 SDL20_free(cursor12);
2359 DECLSPEC SDL12_Cursor * SDLCALL
2360 SDL_CreateCursor(Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y)
2362 const size_t datasize = h * (w / 8);
2363 SDL_Cursor *cursor20 = NULL;
2364 SDL12_Cursor *retval = NULL;
2366 retval = (SDL12_Cursor *) SDL20_malloc(sizeof (SDL12_Cursor));
2370 SDL20_zerop(retval);
2372 retval->data = (Uint8 *) SDL20_malloc(datasize);
2376 retval->mask = (Uint8 *) SDL20_malloc(datasize);
2380 cursor20 = SDL20_CreateCursor(data, mask, w, h, hot_x, hot_y);
2386 retval->hot_x = hot_x;
2387 retval->hot_y = hot_y;
2388 retval->wm_cursor = cursor20;
2389 /* we always leave retval->save as null pointers. */
2391 SDL20_memcpy(retval->data, data, datasize);
2392 SDL20_memcpy(retval->mask, mask, datasize);
2397 SDL20_OutOfMemory();
2400 SDL_FreeCursor(retval);
2404 DECLSPEC void SDLCALL
2405 SDL_SetCursor(SDL12_Cursor *cursor)
2407 CurrentCursor12 = cursor;
2408 SDL20_SetCursor(cursor ? cursor->wm_cursor : NULL);
2411 DECLSPEC SDL12_Cursor * SDLCALL
2414 return CurrentCursor12;
2418 GetEnvironmentWindowPosition(int *x, int *y)
2420 int display = VideoDisplayIndex;
2421 const char *window = SDL20_getenv("SDL_VIDEO_WINDOW_POS");
2422 const char *center = SDL20_getenv("SDL_VIDEO_CENTERED");
2424 if (SDL20_strcmp(window, "center") == 0) {
2426 } else if (SDL20_sscanf(window, "%d,%d", x, y) == 2) {
2432 *x = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
2433 *y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
2438 SetupScreenSaver(const int flags12)
2441 SDL_bool allow_screensaver;
2443 /* Allow environment override of screensaver disable */
2444 env = SDL20_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
2446 allow_screensaver = SDL20_atoi(env) ? SDL_TRUE : SDL_FALSE;
2447 } else if (flags12 & SDL12_FULLSCREEN) {
2448 allow_screensaver = SDL_FALSE;
2450 allow_screensaver = SDL_TRUE;
2452 if (allow_screensaver) {
2453 SDL20_EnableScreenSaver();
2455 SDL20_DisableScreenSaver();
2460 static SDL12_Surface *
2461 EndVidModeCreate(void)
2463 if (VideoTexture20) {
2464 SDL20_DestroyTexture(VideoTexture20);
2465 VideoTexture20 = NULL;
2467 if (VideoRenderer20) {
2468 SDL20_DestroyRenderer(VideoRenderer20);
2469 VideoRenderer20 = NULL;
2471 if (VideoGLContext20) {
2472 SDL20_GL_MakeCurrent(NULL, NULL);
2473 SDL20_GL_DeleteContext(VideoGLContext20);
2474 VideoGLContext20 = NULL;
2476 if (VideoWindow20) {
2477 SDL20_DestroyWindow(VideoWindow20);
2478 VideoWindow20 = NULL;
2480 if (VideoSurface12) {
2481 SDL20_free(VideoSurface12->pixels);
2482 VideoSurface12->pixels = NULL;
2483 SDL_FreeSurface(VideoSurface12);
2484 VideoSurface12 = NULL;
2486 if (VideoConvertSurface20) {
2487 SDL20_FreeSurface(VideoConvertSurface20);
2488 VideoConvertSurface20 = NULL;
2494 static SDL12_Surface *
2495 CreateSurface12WithFormat(const int w, const int h, const Uint32 fmt)
2497 Uint32 rmask, gmask, bmask, amask;
2499 if (!SDL20_PixelFormatEnumToMasks(fmt, &bpp, &rmask, &gmask, &bmask, &amask)) {
2502 return SDL_CreateRGBSurface(0, w, h, bpp, rmask, gmask, bmask, amask);
2505 static SDL_Surface *
2506 CreateNullPixelSurface20(const int width, const int height, const Uint32 fmt)
2508 SDL_Surface *surface20 = SDL20_CreateRGBSurfaceWithFormat(0, 0, 0, SDL_BITSPERPIXEL(fmt), fmt);
2510 surface20->flags |= SDL_PREALLOC;
2511 surface20->pixels = NULL;
2512 surface20->w = width;
2513 surface20->h = height;
2514 surface20->pitch = 0;
2515 SDL20_SetClipRect(surface20, NULL);
2521 DECLSPEC SDL12_Surface * SDLCALL
2522 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
2524 FIXME("currently ignores SDL_WINDOWID, which we could use with SDL_CreateWindowFrom ...?");
2525 SDL_DisplayMode dmode;
2526 Uint32 fullscreen_flags20 = 0;
2529 /* SDL_SetVideoMode() implicitly inits if necessary. */
2530 if (SDL20_WasInit(SDL_INIT_VIDEO) == 0) {
2531 if (SDL20_Init(SDL_INIT_VIDEO) < 0) {
2536 if ((flags12 & SDL12_OPENGLBLIT) == SDL12_OPENGLBLIT) {
2537 FIXME("No OPENGLBLIT support at the moment");
2538 SDL20_SetError("SDL_OPENGLBLIT is (currently) unsupported");
2542 FIXME("handle SDL_ANYFORMAT");
2544 if ((width < 0) || (height < 0)) {
2545 SDL20_SetError("Invalid width or height");
2549 FIXME("There's an environment variable to choose a display");
2550 if (SDL20_GetCurrentDisplayMode(0, &dmode) < 0) {
2563 bpp = SDL_BITSPERPIXEL(dmode.format);
2567 case 8: appfmt = SDL_PIXELFORMAT_INDEX8; break;
2568 case 16: appfmt = SDL_PIXELFORMAT_RGB565; FIXME("bgr instead of rgb?"); break;
2569 case 24: appfmt = SDL_PIXELFORMAT_RGB24; FIXME("bgr instead of rgb?"); break;
2570 case 32: appfmt = SDL_PIXELFORMAT_ARGB8888; FIXME("bgr instead of rgb?"); break;
2571 default: SDL20_SetError("Unsupported bits-per-pixel"); return NULL;
2574 SDL_assert((VideoSurface12 != NULL) == (VideoWindow20 != NULL));
2576 FIXME("don't do anything if the window's dimensions, etc haven't changed.");
2577 FIXME("we need to preserve VideoSurface12 (but not its pixels), I think...");
2579 if ( VideoSurface12 && ((VideoSurface12->flags & SDL12_OPENGL) != (flags12 & SDL12_OPENGL)) ) {
2580 EndVidModeCreate(); /* rebuild the window if moving to/from a GL context */
2581 } else if ( VideoSurface12 && (VideoSurface12->surface20->format->format != appfmt)) {
2582 EndVidModeCreate(); /* rebuild the window if changing pixel format */
2583 } else if (VideoGLContext20) {
2584 /* SDL 1.2 (infuriatingly!) destroys the GL context on each resize, so we will too */
2585 SDL20_GL_MakeCurrent(NULL, NULL);
2586 SDL20_GL_DeleteContext(VideoGLContext20);
2587 VideoGLContext20 = NULL;
2590 if (flags12 & SDL12_FULLSCREEN) {
2591 // OpenGL tries to force the real resolution requested, but for
2592 // software rendering, we're just going to push it off onto the
2593 // GPU, so use FULLSCREEN_DESKTOP and logical scaling there.
2594 FIXME("OpenGL will still expect letterboxing and centering if it didn't get an exact resolution match.");
2595 if (flags12 & SDL12_OPENGL) {
2596 fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN;
2598 fullscreen_flags20 |= SDL_WINDOW_FULLSCREEN_DESKTOP;
2602 if (!VideoWindow20) { /* create it */
2603 int x = SDL_WINDOWPOS_UNDEFINED, y = SDL_WINDOWPOS_UNDEFINED;
2604 Uint32 flags20 = fullscreen_flags20;
2605 if (flags12 & SDL12_OPENGL) { flags20 |= SDL_WINDOW_OPENGL; }
2606 if (flags12 & SDL12_RESIZABLE) { flags20 |= SDL_WINDOW_RESIZABLE; }
2607 if (flags12 & SDL12_NOFRAME) { flags20 |= SDL_WINDOW_BORDERLESS; }
2609 /* most platforms didn't check these environment variables, but the major
2610 ones did (x11, windib, quartz), so we'll just offer it everywhere. */
2611 GetEnvironmentWindowPosition(&x, &y);
2613 VideoWindow20 = SDL20_CreateWindow(WindowTitle, x, y, width, height, flags20);
2614 if (!VideoWindow20) {
2615 return EndVidModeCreate();
2617 } else { /* resize it */
2618 SDL20_SetWindowSize(VideoWindow20, width, height);
2619 SDL20_SetWindowFullscreen(VideoWindow20, fullscreen_flags20);
2620 SDL20_SetWindowBordered(VideoWindow20, (flags12 & SDL12_NOFRAME) ? SDL_FALSE : SDL_TRUE);
2621 SDL20_SetWindowResizable(VideoWindow20, (flags12 & SDL12_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
2624 if (VideoSurface12) {
2625 SDL20_free(VideoSurface12->pixels);
2627 VideoSurface12 = CreateSurface12WithFormat(0, 0, appfmt);
2628 if (!VideoSurface12) {
2629 return EndVidModeCreate();
2633 VideoSurface12->surface20->flags |= SDL_PREALLOC;
2634 VideoSurface12->flags |= SDL12_PREALLOC;
2635 VideoSurface12->pixels = VideoSurface12->surface20->pixels = NULL;
2636 VideoSurface12->w = VideoSurface12->surface20->w = width;
2637 VideoSurface12->h = VideoSurface12->surface20->h = height;
2638 VideoSurface12->pitch = VideoSurface12->surface20->pitch = width * SDL_BYTESPERPIXEL(appfmt);
2639 SDL_SetClipRect(VideoSurface12, NULL);
2641 if (flags12 & SDL12_OPENGL) {
2642 SDL_assert(!VideoTexture20); /* either a new window or we destroyed all this */
2643 SDL_assert(!VideoRenderer20);
2644 VideoGLContext20 = SDL20_GL_CreateContext(VideoWindow20);
2645 if (!VideoGLContext20) {
2646 return EndVidModeCreate();
2649 VideoSurface12->flags |= SDL12_OPENGL;
2651 /* always use a renderer for non-OpenGL windows. */
2652 SDL_RendererInfo rinfo;
2653 SDL_assert(!VideoGLContext20); /* either a new window or we destroyed all this */
2654 if (!VideoRenderer20) {
2655 VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);
2657 if (!VideoRenderer20) {
2658 VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, SDL_RENDERER_PRESENTVSYNC);
2660 if (!VideoRenderer20) {
2661 VideoRenderer20 = SDL20_CreateRenderer(VideoWindow20, -1, 0);
2663 if (!VideoRenderer20) {
2664 return EndVidModeCreate();
2667 SDL20_RenderSetLogicalSize(VideoRenderer20, width, height);
2668 SDL20_SetRenderDrawColor(VideoRenderer20, 0, 0, 0, 255);
2669 SDL20_RenderClear(VideoRenderer20);
2670 SDL20_RenderPresent(VideoRenderer20);
2671 SDL20_SetRenderDrawColor(VideoRenderer20, 255, 255, 255, 255);
2673 if (SDL20_GetRendererInfo(VideoRenderer20, &rinfo) < 0) {
2674 return EndVidModeCreate();
2677 if (VideoTexture20) {
2678 SDL20_DestroyTexture(VideoTexture20);
2681 if (VideoConvertSurface20) {
2682 SDL20_FreeSurface(VideoConvertSurface20);
2683 VideoConvertSurface20 = NULL;
2686 VideoTexture20 = SDL20_CreateTexture(VideoRenderer20, rinfo.texture_formats[0], SDL_TEXTUREACCESS_STREAMING, width, height);
2687 if (!VideoTexture20) {
2688 return EndVidModeCreate();
2691 if (rinfo.texture_formats[0] != appfmt) {
2692 /* need to convert between app's format and texture format */
2693 VideoConvertSurface20 = CreateNullPixelSurface20(width, height, rinfo.texture_formats[0]);
2694 if (!VideoConvertSurface20) {
2695 return EndVidModeCreate();
2699 VideoSurface12->flags &= ~SDL12_OPENGL;
2700 VideoSurface12->flags |= SDL12_DOUBLEBUF;
2701 VideoSurface12->surface20->pixels = SDL20_malloc(height * VideoSurface12->pitch);
2702 VideoSurface12->pixels = VideoSurface12->surface20->pixels;
2703 if (!VideoSurface12->pixels) {
2704 SDL20_OutOfMemory();
2705 return EndVidModeCreate();
2708 /* fill in the same default palette that SDL 1.2 does... */
2709 if (VideoSurface12->format->BitsPerPixel == 8) {
2711 SDL_Color *color = VideoSurface12->format->palette->colors;
2712 for (i = 0; i < 256; i++, color++) {
2713 { const int x = i & 0xe0; color->r = x | x >> 3 | x >> 6; }
2714 { const int x = (i << 3) & 0xe0; color->g = x | x >> 3 | x >> 6; }
2715 { const int x = (i & 0x3) | ((i & 0x3) << 2); color->b = x | x << 4; }
2721 SDL20_RaiseWindow(VideoWindow20);
2723 FIXME("setup screen saver");
2725 return VideoSurface12;
2728 DECLSPEC SDL12_Surface * SDLCALL
2729 SDL_GetVideoSurface(void)
2731 return VideoSurface12;
2734 DECLSPEC int SDLCALL
2735 SDL_UpperBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
2737 SDL_Rect srcrect20, dstrect20;
2738 const int retval = SDL20_UpperBlit(src->surface20,
2739 srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
2741 dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
2744 Rect20to12(&srcrect20, srcrect12);
2748 Rect20to12(&dstrect20, dstrect12);
2754 DECLSPEC int SDLCALL
2755 SDL_LowerBlit(SDL12_Surface *src, SDL12_Rect *srcrect12, SDL12_Surface *dst, SDL12_Rect *dstrect12)
2757 SDL_Rect srcrect20, dstrect20;
2758 const int retval = SDL20_LowerBlit(src->surface20,
2759 srcrect12 ? Rect12to20(srcrect12, &srcrect20) : NULL,
2761 dstrect12 ? Rect12to20(dstrect12, &dstrect20) : NULL);
2764 Rect20to12(&srcrect20, srcrect12);
2768 Rect20to12(&dstrect20, dstrect12);
2774 DECLSPEC int SDLCALL
2775 SDL_SetAlpha(SDL12_Surface * surface, Uint32 flag, Uint8 value)
2778 return SDL20_Unsupported();
2781 DECLSPEC int SDLCALL
2782 SDL_LockSurface(SDL12_Surface *surface12)
2784 const int retval = SDL20_LockSurface(surface12->surface20);
2785 surface12->pixels = surface12->surface20->pixels;
2786 surface12->pitch = surface12->surface20->pitch;
2790 DECLSPEC void SDLCALL
2791 SDL_UnlockSurface(SDL12_Surface *surface12)
2793 SDL20_UnlockSurface(surface12->surface20);
2794 surface12->pixels = surface12->surface20->pixels;
2795 surface12->pitch = surface12->surface20->pitch;
2798 DECLSPEC SDL12_Surface * SDLCALL
2799 SDL_ConvertSurface(SDL12_Surface *src12, const SDL12_PixelFormat *format12, Uint32 flags12)
2802 SDL_PixelFormat format20;
2803 SDL_Palette palette20;
2804 SDL_Surface *surface20;
2805 SDL12_Surface *retval = NULL;
2807 if (flags12 & SDL12_PREALLOC) flags20 |= SDL_PREALLOC;
2808 if (flags12 & SDL12_RLEACCEL) flags20 |= SDL_RLEACCEL;
2810 surface20 = SDL20_ConvertSurface(src12->surface20, PixelFormat12to20(&format20, &palette20, format12), flags20);
2812 retval = Surface20to12(surface20);
2814 SDL20_FreeSurface(surface20);
2820 DECLSPEC SDL12_Surface * SDLCALL
2821 SDL_DisplayFormat(SDL12_Surface *surface12)
2823 const Uint32 flags = surface12->flags & (SDL12_SRCCOLORKEY|SDL12_SRCALPHA|SDL12_RLEACCELOK);
2824 return SDL_ConvertSurface(surface12, VideoSurface12->format, flags);
2827 DECLSPEC SDL12_Surface * SDLCALL
2828 SDL_DisplayFormatAlpha(SDL12_Surface *surface)
2831 SDL20_Unsupported();
2838 void *pixels = NULL;
2841 SDL_assert(VideoSurface12 != NULL);
2843 if (SDL20_LockTexture(VideoTexture20, NULL, &pixels, &pitch) < 0) {
2844 return; /* oh well */
2847 FIXME("Maybe lock texture always, until present, if no conversion needed?");
2848 VideoConvertSurface20->pixels = pixels;
2849 VideoConvertSurface20->pitch = pitch;
2850 SDL20_UpperBlit(VideoSurface12->surface20, NULL, VideoConvertSurface20, NULL);
2851 VideoConvertSurface20->pixels = NULL;
2852 VideoConvertSurface20->pitch = 0;
2854 SDL20_UnlockTexture(VideoTexture20);
2855 SDL20_RenderCopy(VideoRenderer20, VideoTexture20, NULL, NULL);
2856 SDL20_RenderPresent(VideoRenderer20);
2859 DECLSPEC void SDLCALL
2860 SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
2862 /* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
2863 /* (UpdateRect, singular, does...) */
2864 if (surface12->flags & SDL12_OPENGL) {
2865 SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
2869 /* everything else is marked SDL12_DOUBLEBUF and is a no-op here. */
2872 DECLSPEC void SDLCALL
2873 SDL_UpdateRect(SDL12_Surface *screen12, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
2877 rect12.x = (Sint16) x;
2878 rect12.y = (Sint16) y;
2879 rect12.w = (Uint16) (w ? w : screen12->w);
2880 rect12.h = (Uint16) (h ? h : screen12->h);
2881 SDL_UpdateRects(screen12, 1, &rect12);
2885 DECLSPEC int SDLCALL
2886 SDL_Flip(SDL12_Surface *surface12)
2888 if (surface12->flags & SDL12_OPENGL) {
2889 return SDL20_SetError("Use SDL_GL_SwapBuffers() on OpenGL surfaces");
2892 if (surface12 == VideoSurface12) {
2899 DECLSPEC void SDLCALL
2900 SDL_WM_SetCaption(const char *title, const char *icon)
2903 SDL20_free(WindowTitle);
2905 if (WindowIconTitle) {
2906 SDL20_free(WindowIconTitle);
2908 WindowTitle = title ? SDL_strdup(title) : NULL;
2909 WindowIconTitle = icon ? SDL_strdup(icon) : NULL;
2910 if (VideoWindow20) {
2911 SDL20_SetWindowTitle(VideoWindow20, WindowTitle);
2915 DECLSPEC void SDLCALL
2916 SDL_WM_GetCaption(const char **title, const char **icon)
2919 *title = WindowTitle;
2922 *icon = WindowIconTitle;
2926 DECLSPEC void SDLCALL
2927 SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask)
2930 SDL20_Unsupported();
2933 DECLSPEC int SDLCALL
2934 SDL_WM_IconifyWindow(void)
2936 SDL20_MinimizeWindow(VideoWindow20);
2940 DECLSPEC int SDLCALL
2941 SDL_WM_ToggleFullScreen(SDL12_Surface *surface)
2944 return SDL20_Unsupported();
2949 SDL12_GRAB_QUERY = -1,
2954 DECLSPEC SDL12_GrabMode SDLCALL
2955 SDL_WM_GrabInput(SDL12_GrabMode mode)
2957 if (mode != SDL12_GRAB_QUERY) {
2958 SDL20_SetWindowGrab(VideoWindow20, (mode == SDL12_GRAB_ON));
2960 return SDL20_GetWindowGrab(VideoWindow20) ? SDL12_GRAB_ON : SDL12_GRAB_OFF;
2963 DECLSPEC void SDLCALL
2964 SDL_WarpMouse(Uint16 x, Uint16 y)
2966 SDL20_WarpMouseInWindow(VideoWindow20, x, y);
2969 DECLSPEC Uint8 SDLCALL
2970 SDL_GetAppState(void)
2975 flags20 = SDL20_GetWindowFlags(VideoWindow20);
2976 if ((flags20 & SDL_WINDOW_SHOWN) && !(flags20 & SDL_WINDOW_MINIMIZED)) {
2977 state12 |= SDL12_APPACTIVE;
2979 if (flags20 & SDL_WINDOW_INPUT_FOCUS) {
2980 state12 |= SDL12_APPINPUTFOCUS;
2982 if (flags20 & SDL_WINDOW_MOUSE_FOCUS) {
2983 state12 |= SDL12_APPMOUSEFOCUS;
2988 DECLSPEC int SDLCALL
2989 SDL_SetColorKey(SDL12_Surface *surface12, Uint32 flag12, Uint32 key)
2991 const SDL_bool addkey = (flag12 & SDL12_SRCCOLORKEY) ? SDL_TRUE : SDL_FALSE;
2992 const int retval = SDL20_SetColorKey(surface12->surface20, addkey, key);
2993 if (SDL20_GetColorKey(surface12->surface20, &surface12->format->colorkey) < 0) {
2994 surface12->format->colorkey = 0;
2999 DECLSPEC int SDLCALL
3000 SDL_SetPalette(SDL12_Surface *surface12, int flags, const SDL_Color *colors,
3001 int firstcolor, int ncolors)
3004 return SDL20_Unsupported();
3007 DECLSPEC int SDLCALL
3008 SDL_SetColors(SDL12_Surface *surface12, const SDL_Color * colors, int firstcolor,
3012 return SDL20_Unsupported();
3015 DECLSPEC int SDLCALL
3016 SDL_GetWMInfo(SDL_SysWMinfo * info)
3019 //return SDL20_GetWindowWMInfo(VideoWindow20, info);
3020 return SDL20_Unsupported();
3023 DECLSPEC SDL12_Overlay * SDLCALL
3024 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL12_Surface *display)
3027 SDL20_Unsupported();
3031 DECLSPEC int SDLCALL
3032 SDL_LockYUVOverlay(SDL12_Overlay * overlay)
3035 return SDL20_Unsupported();
3038 DECLSPEC void SDLCALL
3039 SDL_UnlockYUVOverlay(SDL12_Overlay * overlay)
3044 DECLSPEC int SDLCALL
3045 SDL_DisplayYUVOverlay(SDL12_Overlay * overlay, SDL12_Rect * dstrect12)
3048 return SDL20_Unsupported();
3051 DECLSPEC void SDLCALL
3052 SDL_FreeYUVOverlay(SDL12_Overlay * overlay)
3057 DECLSPEC int SDLCALL
3058 SDL_GL_LoadLibrary(const char *libname)
3060 /* SDL 1.2 would unload the previous library if one was loaded. SDL2
3061 reports an error if one is already loaded, and sometimes loads it
3062 internally for some video targets, so unloading it probably isn't safe.
3063 There really isn't a good reason to be using anything other than the
3064 system OpenGL in 2019, so we ignore the error in this case to match 1.2
3065 behavior, even if you were going to load a different library this time.
3067 const int rc = SDL20_GL_LoadLibrary(libname);
3069 const char *err = SDL20_GetError();
3070 if (SDL20_strcmp(err, "OpenGL library already loaded") == 0) {
3074 /* reset the actual error. */
3075 char *dup = SDL_strdup(err);
3077 SDL20_SetError("Out of memory");
3079 SDL20_SetError(dup);
3087 DECLSPEC int SDLCALL
3088 SDL_GL_SetAttribute(SDL12_GLattr attr, int value)
3090 if (attr >= SDL12_GL_MAX_ATTRIBUTE)
3091 return SDL20_SetError("Unknown GL attribute");
3093 /* swap control was moved out of this API, everything else lines up. */
3094 if (attr == SDL12_GL_SWAP_CONTROL)
3096 SwapInterval = value;
3097 FIXME("Actually set swap interval somewhere");
3101 return SDL20_GL_SetAttribute((SDL_GLattr) attr, value);
3104 DECLSPEC int SDLCALL
3105 SDL_GL_GetAttribute(SDL12_GLattr attr, int* value)
3107 if (attr >= SDL12_GL_MAX_ATTRIBUTE)
3108 return SDL20_SetError("Unknown GL attribute");
3110 /* swap control was moved out of this API, everything else lines up. */
3111 if (attr == SDL12_GL_SWAP_CONTROL)
3113 *value = SDL20_GL_GetSwapInterval();
3117 return SDL20_GL_GetAttribute((SDL_GLattr) attr, value);
3121 DECLSPEC void SDLCALL
3122 SDL_GL_SwapBuffers(void)
3125 SDL20_GL_SwapWindow(VideoWindow20);
3128 DECLSPEC int SDLCALL
3129 SDL_SetGamma(float red, float green, float blue)
3131 Uint16 red_ramp[256];
3132 Uint16 green_ramp[256];
3133 Uint16 blue_ramp[256];
3135 SDL20_CalculateGammaRamp(red, red_ramp);
3137 SDL20_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
3139 SDL20_CalculateGammaRamp(green, green_ramp);
3142 SDL20_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
3143 } else if (blue == green) {
3144 SDL20_memcpy(blue_ramp, green_ramp, sizeof(green_ramp));
3146 SDL20_CalculateGammaRamp(blue, blue_ramp);
3148 return SDL20_SetWindowGammaRamp(VideoWindow20, red_ramp, green_ramp, blue_ramp);
3151 DECLSPEC int SDLCALL
3152 SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
3154 return SDL20_SetWindowGammaRamp(VideoWindow20, red, green, blue);
3157 DECLSPEC int SDLCALL
3158 SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
3160 return SDL20_GetWindowGammaRamp(VideoWindow20, red, green, blue);
3163 DECLSPEC int SDLCALL
3164 SDL_EnableKeyRepeat(int delay, int interval)
3170 DECLSPEC void SDLCALL
3171 SDL_GetKeyRepeat(int *delay, int *interval)
3175 *delay = SDL12_DEFAULT_REPEAT_DELAY;
3178 *interval = SDL12_DEFAULT_REPEAT_INTERVAL;
3182 DECLSPEC int SDLCALL
3183 SDL_EnableUNICODE(int enable)
3186 return SDL20_Unsupported();
3190 SetTimerOld_Callback(Uint32 interval, void* param)
3192 return ((SDL12_TimerCallback)param)(interval);
3195 DECLSPEC int SDLCALL
3196 SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
3198 static SDL_TimerID compat_timer;
3201 SDL20_RemoveTimer(compat_timer);
3205 if (interval && callback) {
3206 compat_timer = SDL20_AddTimer(interval, SetTimerOld_Callback, callback);
3207 if (!compat_timer) {
3214 DECLSPEC int SDLCALL
3215 SDL_putenv(const char *_var)
3218 char *var = SDL20_strdup(_var);
3220 return -1; /* we don't set errno. */
3223 ptr = SDL20_strchr(var, '=');
3229 *ptr = '\0'; /* split the string into name and value. */
3230 SDL20_setenv(var, ptr + 1, 1);
3237 /* CD-ROM support is gone from SDL 2.0, so just have stubs that fail. */
3239 typedef void *SDL12_CD; /* close enough. :) */
3240 typedef int SDL12_CDstatus; /* close enough. :) */
3242 DECLSPEC int SDLCALL
3243 SDL_CDNumDrives(void)
3245 FIXME("should return -1 without SDL_INIT_CDROM");
3249 DECLSPEC const char *SDLCALL SDL_CDName(int drive) { SDL20_Unsupported(); return NULL; }
3250 DECLSPEC SDL12_CD *SDLCALL SDL_CDOpen(int drive) { SDL20_Unsupported(); return NULL; }
3251 DECLSPEC SDL12_CDstatus SDLCALL SDL_CDStatus(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
3252 DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL12_CD *cdrom, int start_track, int start_frame, int ntracks, int nframes) { return SDL20_Unsupported(); }
3253 DECLSPEC int SDLCALL SDL_CDPlay(SDL12_CD *cdrom, int start, int length) { return SDL20_Unsupported(); }
3254 DECLSPEC int SDLCALL SDL_CDPause(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
3255 DECLSPEC int SDLCALL SDL_CDResume(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
3256 DECLSPEC int SDLCALL SDL_CDStop(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
3257 DECLSPEC int SDLCALL SDL_CDEject(SDL12_CD *cdrom) { return SDL20_Unsupported(); }
3258 DECLSPEC void SDLCALL SDL_CDClose(SDL12_CD *cdrom) {}
3261 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
3262 DECLSPEC SDL_Thread * SDLCALL
3263 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
3265 return SDL20_CreateThread(fn, NULL, data, pfnBeginThread, pfnEndThread);
3268 DECLSPEC SDL_Thread * SDLCALL
3269 SDL_CreateThread(int (SDLCALL *fn)(void *), void *data)
3271 return SDL20_CreateThread(fn, NULL, data);
3275 DECLSPEC int SDLCALL
3276 SDL_mutexP(SDL_mutex *mutex)
3278 return SDL20_LockMutex(mutex);
3281 DECLSPEC int SDLCALL
3282 SDL_mutexV(SDL_mutex *mutex)
3284 return SDL20_UnlockMutex(mutex);
3287 DECLSPEC void SDLCALL SDL_KillThread(SDL_Thread *thread)
3289 FIXME("Removed from 2.0; do nothing. We can't even report failure.");
3291 "WARNING: this app used SDL_KillThread(), an unforgivable curse.\n"
3292 "This program should be fixed. No thread was actually harmed.\n");
3295 /* This changed from an opaque pointer to an int in 2.0. */
3296 typedef struct _SDL12_TimerID *SDL12_TimerID;
3297 SDL_COMPILE_TIME_ASSERT(timer, sizeof(SDL12_TimerID) >= sizeof(SDL_TimerID));
3300 DECLSPEC SDL12_TimerID SDLCALL
3301 SDL_AddTimer(Uint32 interval, SDL12_NewTimerCallback callback, void *param)
3303 return (SDL12_TimerID) ((size_t) SDL20_AddTimer(interval, callback, param));
3306 DECLSPEC SDL_bool SDLCALL
3307 SDL_RemoveTimer(SDL12_TimerID id)
3309 return SDL20_RemoveTimer((SDL_TimerID) ((size_t)id));
3313 typedef struct SDL12_RWops {
3314 int (SDLCALL *seek)(struct SDL12_RWops *context, int offset, int whence);
3315 int (SDLCALL *read)(struct SDL12_RWops *context, void *ptr, int size, int maxnum);
3316 int (SDLCALL *write)(struct SDL12_RWops *context, const void *ptr, int size, int num);
3317 int (SDLCALL *close)(struct SDL12_RWops *context);
3324 DECLSPEC SDL12_RWops * SDLCALL
3327 SDL12_RWops *rwops = (SDL12_RWops *) SDL20_malloc(sizeof (SDL12_RWops));
3329 SDL20_OutOfMemory();
3333 DECLSPEC void SDLCALL
3334 SDL_FreeRW(SDL12_RWops *rwops12)
3336 SDL20_free(rwops12);
3340 RWops20to12_seek(struct SDL12_RWops *rwops12, int offset, int whence)
3342 return rwops12->rwops20->seek(rwops12->rwops20, offset, whence);
3346 RWops20to12_read(struct SDL12_RWops *rwops12, void *ptr, int size, int maxnum)
3348 return rwops12->rwops20->read(rwops12->rwops20, ptr, size, maxnum);
3352 RWops20to12_write(struct SDL12_RWops *rwops12, const void *ptr, int size, int num)
3354 return rwops12->rwops20->write(rwops12->rwops20, ptr, size, num);
3358 RWops20to12_close(struct SDL12_RWops *rwops12)
3363 rc = rwops12->rwops20->close(rwops12->rwops20);
3365 SDL_FreeRW(rwops12);
3370 static SDL12_RWops *
3371 RWops20to12(SDL_RWops *rwops20)
3373 SDL12_RWops *rwops12;
3378 rwops12 = SDL_AllocRW();
3382 SDL20_zerop(rwops12);
3383 rwops12->type = rwops20->type;
3384 rwops12->rwops20 = rwops20;
3385 rwops12->seek = RWops20to12_seek;
3386 rwops12->read = RWops20to12_read;
3387 rwops12->write = RWops20to12_write;
3388 rwops12->close = RWops20to12_close;
3393 DECLSPEC SDL12_RWops * SDLCALL
3394 SDL_RWFromFile(const char *file, const char *mode)
3396 if ( !file || !*file || !mode || !*mode ) {
3397 SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
3400 return RWops20to12(SDL20_RWFromFile(file, mode));
3403 DECLSPEC SDL12_RWops * SDLCALL
3404 SDL_RWFromFP(FILE *io, int autoclose)
3406 return RWops20to12(SDL20_RWFromFP(io, autoclose));
3409 DECLSPEC SDL12_RWops * SDLCALL
3410 SDL_RWFromMem(void *mem, int size)
3412 return RWops20to12(SDL20_RWFromMem(mem, size));
3415 DECLSPEC SDL12_RWops * SDLCALL
3416 SDL_RWFromConstMem(const void *mem, int size)
3418 return RWops20to12(SDL20_RWFromConstMem(mem, size));
3421 #define READ_AND_BYTESWAP(endian, bits) \
3422 DECLSPEC Uint##bits SDLCALL SDL_Read##endian##bits(SDL12_RWops *rwops12) { \
3423 Uint##bits val; rwops12->read(rwops12, &val, sizeof (val), 1); \
3424 return SDL_Swap##endian##bits(val); \
3427 READ_AND_BYTESWAP(LE,16)
3428 READ_AND_BYTESWAP(BE,16)
3429 READ_AND_BYTESWAP(LE,32)
3430 READ_AND_BYTESWAP(BE,32)
3431 READ_AND_BYTESWAP(LE,64)
3432 READ_AND_BYTESWAP(BE,64)
3433 #undef READ_AND_BYTESWAP
3435 #define BYTESWAP_AND_WRITE(endian, bits) \
3436 DECLSPEC int SDLCALL SDL_Write##endian##bits(SDL12_RWops *rwops12, Uint##bits val) { \
3437 val = SDL_Swap##endian##bits(val); \
3438 return rwops12->write(rwops12, &val, sizeof (val), 1); \
3440 BYTESWAP_AND_WRITE(LE,16)
3441 BYTESWAP_AND_WRITE(BE,16)
3442 BYTESWAP_AND_WRITE(LE,32)
3443 BYTESWAP_AND_WRITE(BE,32)
3444 BYTESWAP_AND_WRITE(LE,64)
3445 BYTESWAP_AND_WRITE(BE,64)
3446 #undef BYTESWAP_AND_WRITE
3449 static Sint64 SDLCALL
3450 RWops12to20_size(struct SDL_RWops *rwops20)
3452 SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
3453 int size = (int) ((size_t) rwops20->hidden.unknown.data2);
3459 pos = rwops12->seek(rwops12, 0, SEEK_CUR);
3463 size = (Sint64) rwops12->seek(rwops12, 0, SEEK_END);
3467 rwops12->seek(rwops12, pos, SEEK_SET); FIXME("...and if this fails?");
3468 rwops20->hidden.unknown.data2 = (void *) ((size_t) size);
3472 static Sint64 SDLCALL
3473 RWops12to20_seek(struct SDL_RWops *rwops20, Sint64 offset, int whence)
3475 FIXME("fail if (offset) is too big");
3476 SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
3477 return (Sint64) rwops12->seek(rwops12, (int) offset, whence);
3480 static size_t SDLCALL
3481 RWops12to20_read(struct SDL_RWops *rwops20, void *ptr, size_t size, size_t maxnum)
3483 FIXME("fail if (size) or (maxnum) is too big");
3484 SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
3485 return (size_t) rwops12->read(rwops12, ptr, (int) size, (int) maxnum);
3488 static size_t SDLCALL
3489 RWops12to20_write(struct SDL_RWops *rwops20, const void *ptr, size_t size, size_t num)
3491 FIXME("fail if (size) or (maxnum) is too big");
3492 SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
3493 return (size_t) rwops12->write(rwops12, ptr, (int) size, (int) num);
3497 RWops12to20_close(struct SDL_RWops *rwops20)
3502 SDL12_RWops *rwops12 = (SDL12_RWops *) rwops20->hidden.unknown.data1;
3503 rc = rwops12->close(rwops12);
3505 SDL20_FreeRW(rwops20);
3511 RWops12to20(SDL12_RWops *rwops12)
3518 rwops20 = SDL20_AllocRW();
3522 SDL20_zerop(rwops20);
3523 rwops20->type = rwops12->type;
3524 rwops20->hidden.unknown.data1 = rwops12;
3525 rwops20->hidden.unknown.data2 = (void *) ((size_t) -1); /* cached size of stream */
3526 rwops20->size = RWops12to20_size;
3527 rwops20->seek = RWops12to20_seek;
3528 rwops20->read = RWops12to20_read;
3529 rwops20->write = RWops12to20_write;
3530 rwops20->close = RWops12to20_close;
3534 DECLSPEC SDL12_Surface * SDLCALL
3535 SDL_LoadBMP_RW(SDL12_RWops *rwops12, int freerwops12)
3537 SDL_RWops *rwops20 = RWops12to20(rwops12);
3538 SDL_Surface *surface20 = SDL20_LoadBMP_RW(rwops20, freerwops12);
3539 SDL12_Surface *surface12 = Surface20to12(surface20);
3540 if (!freerwops12) /* free our wrapper if SDL2 didn't close it. */
3541 SDL20_FreeRW(rwops20);
3542 if ((!surface12) && (surface20))
3543 SDL20_FreeSurface(surface20);
3547 DECLSPEC int SDLCALL
3548 SDL_SaveBMP_RW(SDL12_Surface *surface12, SDL12_RWops *rwops12, int freerwops12)
3550 FIXME("wrap surface");
3551 SDL_RWops *rwops20 = RWops12to20(rwops12);
3552 const int retval = SDL20_SaveBMP_RW(surface12->surface20, rwops20, freerwops12);
3553 if (!freerwops12) /* free our wrapper if SDL2 didn't close it. */
3554 SDL20_FreeRW(rwops20);
3558 DECLSPEC SDL_AudioSpec * SDLCALL
3559 SDL_LoadWAV_RW(SDL12_RWops *rwops12, int freerwops12,
3560 SDL_AudioSpec *spec, Uint8 **buf, Uint32 *len)
3562 SDL_RWops *rwops20 = RWops12to20(rwops12);
3563 SDL_AudioSpec *retval = SDL20_LoadWAV_RW(rwops20, freerwops12, spec, buf, len);
3564 FIXME("deal with non-1.2 formats, like float32");
3565 if (!freerwops12) /* free our wrapper if SDL2 didn't close it. */
3566 SDL20_FreeRW(rwops20);
3570 /* vi: set ts=4 sw=4 expandtab: */