1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // http://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
19 #if defined(TARGET_SDL)
21 /* ========================================================================= */
23 /* ========================================================================= */
25 /* SDL internal variables */
26 #if defined(TARGET_SDL2)
27 static SDL_Window *sdl_window = NULL;
28 static SDL_Renderer *sdl_renderer = NULL;
29 static SDL_Texture *sdl_texture = NULL;
31 #define USE_RENDERER TRUE
34 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
35 static int fullscreen_width;
36 static int fullscreen_height;
37 static int fullscreen_xoffset;
38 static int fullscreen_yoffset;
39 static int video_xoffset;
40 static int video_yoffset;
41 static boolean limit_screen_updates = FALSE;
44 /* functions from SGE library */
45 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
47 void SDLLimitScreenUpdates(boolean enable)
49 limit_screen_updates = enable;
52 static void UpdateScreen(SDL_Rect *rect)
54 static unsigned int update_screen_delay = 0;
55 unsigned int update_screen_delay_value = 20; /* (milliseconds) */
58 if (limit_screen_updates &&
59 !DelayReached(&update_screen_delay, update_screen_delay_value))
62 LimitScreenUpdates(FALSE);
65 #if defined(TARGET_SDL2)
67 SDL_Surface *screen = backbuffer->surface;
72 int bytes_x = screen->pitch / video.width;
73 int bytes_y = screen->pitch;
75 if (video.fullscreen_enabled)
76 bytes_x = screen->pitch / fullscreen_width;
78 SDL_UpdateTexture(sdl_texture, rect,
79 screen->pixels + rect->x * bytes_x + rect->y * bytes_y,
84 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
87 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
89 SDL_RenderClear(sdl_renderer);
90 SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
91 SDL_RenderPresent(sdl_renderer);
94 SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
96 SDL_UpdateWindowSurface(sdl_window);
101 SDL_UpdateRects(backbuffer->surface, 1, rect);
103 SDL_UpdateRect(backbuffer->surface, 0, 0, 0, 0);
107 static void setFullscreenParameters(char *fullscreen_mode_string)
109 #if defined(TARGET_SDL2)
110 fullscreen_width = video.width;
111 fullscreen_height = video.height;
112 fullscreen_xoffset = 0;
113 fullscreen_yoffset = 0;
117 struct ScreenModeInfo *fullscreen_mode;
120 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
122 if (fullscreen_mode == NULL)
125 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
127 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
128 fullscreen_mode->height == video.fullscreen_modes[i].height)
130 fullscreen_width = fullscreen_mode->width;
131 fullscreen_height = fullscreen_mode->height;
133 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
134 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
142 static void SDLSetWindowIcon(char *basename)
144 /* (setting the window icon on Mac OS X would replace the high-quality
145 dock icon with the currently smaller (and uglier) icon from file) */
147 #if !defined(PLATFORM_MACOSX)
148 char *filename = getCustomImageFilename(basename);
149 SDL_Surface *surface;
151 if (filename == NULL)
153 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
158 if ((surface = IMG_Load(filename)) == NULL)
160 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
165 /* set transparent color */
166 SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
167 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
169 #if defined(TARGET_SDL2)
170 SDL_SetWindowIcon(sdl_window, surface);
172 SDL_WM_SetIcon(surface, NULL);
177 #if defined(TARGET_SDL2)
179 static boolean equalSDLPixelFormat(SDL_PixelFormat *format1,
180 SDL_PixelFormat *format2)
182 return (format1->format == format2->format &&
183 format1->BitsPerPixel == format2->BitsPerPixel &&
184 format1->BytesPerPixel == format2->BytesPerPixel &&
185 format1->Rmask == format2->Rmask &&
186 format1->Gmask == format2->Gmask &&
187 format1->Bmask == format2->Bmask &&
188 format1->Amask == format2->Amask);
191 boolean SDLSetNativeSurface(SDL_Surface **surface)
193 SDL_Surface *new_surface;
195 if (surface == NULL ||
197 backbuffer == NULL ||
198 backbuffer->surface == NULL)
201 // if pixel format already optimized for destination surface, do nothing
202 if (equalSDLPixelFormat((*surface)->format, backbuffer->surface->format))
205 new_surface = SDL_ConvertSurface(*surface, backbuffer->surface->format, 0);
207 SDL_FreeSurface(*surface);
209 *surface = new_surface;
214 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
216 if (surface == NULL ||
217 backbuffer == NULL ||
218 backbuffer->surface == NULL)
221 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
224 SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface)
226 if (surface == NULL ||
227 backbuffer == NULL ||
228 backbuffer->surface == NULL)
232 boolean same_pixel_format =
233 equalSDLPixelFormat(surface->format, backbuffer->surface->format);
235 printf("::: SDL_DisplayFormat: %08x -> %08x [%08x, %08x, %08x -> %08x, %08x, %08x] [%d, %d -> %d, %d] => %s\n",
236 surface->format->format,
237 backbuffer->surface->format->format,
238 surface->format->Rmask,
239 surface->format->Gmask,
240 surface->format->Bmask,
241 backbuffer->surface->format->Rmask,
242 backbuffer->surface->format->Gmask,
243 backbuffer->surface->format->Bmask,
244 surface->format->BitsPerPixel,
245 surface->format->BytesPerPixel,
246 backbuffer->surface->format->BitsPerPixel,
247 backbuffer->surface->format->BytesPerPixel,
248 (same_pixel_format ? "SAME" : "DIFF"));
251 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
256 boolean SDLSetNativeSurface(SDL_Surface **surface)
258 SDL_Surface *new_surface;
263 new_surface = SDL_DisplayFormat(*surface);
265 if (new_surface == NULL)
266 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
268 SDL_FreeSurface(*surface);
270 *surface = new_surface;
275 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
277 SDL_Surface *new_surface = SDL_DisplayFormat(surface);
279 if (new_surface == NULL)
280 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
287 void SDLInitVideoDisplay(void)
289 #if !defined(TARGET_SDL2)
290 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
291 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
293 SDL_putenv("SDL_VIDEO_CENTERED=1");
296 /* initialize SDL video */
297 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
298 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
300 /* set default SDL depth */
301 #if !defined(TARGET_SDL2)
302 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
304 video.default_depth = 32; // (how to determine video depth in SDL2?)
308 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
311 #if !defined(TARGET_SDL2)
312 static int screen_xy[][2] =
320 SDL_Rect **modes = NULL;
321 boolean hardware_fullscreen_available = TRUE;
324 /* default: normal game window size */
325 fullscreen_width = video.width;
326 fullscreen_height = video.height;
327 fullscreen_xoffset = 0;
328 fullscreen_yoffset = 0;
330 #if !defined(TARGET_SDL2)
331 /* determine required standard fullscreen mode for game screen size */
332 for (i = 0; screen_xy[i][0] != -1; i++)
334 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
336 fullscreen_width = screen_xy[i][0];
337 fullscreen_height = screen_xy[i][1];
343 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
344 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
348 checked_free(video.fullscreen_modes);
350 video.fullscreen_modes = NULL;
351 video.fullscreen_mode_current = NULL;
354 video.window_scaling_percent = setup.window_scaling_percent;
355 video.window_scaling_quality = setup.window_scaling_quality;
357 #if defined(TARGET_SDL2)
358 int num_displays = SDL_GetNumVideoDisplays();
360 if (num_displays > 0)
362 // currently only display modes of first display supported
363 int num_modes = SDL_GetNumDisplayModes(0);
367 modes = checked_calloc((num_modes + 1) * sizeof(SDL_Rect *));
369 for (i = 0; i < num_modes; i++)
371 SDL_DisplayMode mode;
373 if (SDL_GetDisplayMode(0, i, &mode) < 0)
376 modes[i] = checked_calloc(sizeof(SDL_Rect));
378 modes[i]->w = mode.w;
379 modes[i]->h = mode.h;
384 /* get available hardware supported fullscreen modes */
385 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
390 /* no hardware screen modes available => no fullscreen mode support */
391 // video.fullscreen_available = FALSE;
392 hardware_fullscreen_available = FALSE;
394 else if (modes == (SDL_Rect **)-1)
396 /* fullscreen resolution is not restricted -- all resolutions available */
397 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
399 /* use native video buffer size for fullscreen mode */
400 video.fullscreen_modes[0].width = video.width;
401 video.fullscreen_modes[0].height = video.height;
403 video.fullscreen_modes[1].width = -1;
404 video.fullscreen_modes[1].height = -1;
408 /* in this case, a certain number of screen modes is available */
411 for (i = 0; modes[i] != NULL; i++)
413 boolean found_mode = FALSE;
415 /* screen mode is smaller than video buffer size -- skip it */
416 if (modes[i]->w < video.width || modes[i]->h < video.height)
419 if (video.fullscreen_modes != NULL)
420 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
421 if (modes[i]->w == video.fullscreen_modes[j].width &&
422 modes[i]->h == video.fullscreen_modes[j].height)
425 if (found_mode) /* screen mode already stored -- skip it */
428 /* new mode found; add it to list of available fullscreen modes */
432 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
434 sizeof(struct ScreenModeInfo));
436 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
437 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
439 video.fullscreen_modes[num_modes].width = -1;
440 video.fullscreen_modes[num_modes].height = -1;
445 /* no appropriate screen modes available => no fullscreen mode support */
446 // video.fullscreen_available = FALSE;
447 hardware_fullscreen_available = FALSE;
451 video.fullscreen_available = hardware_fullscreen_available;
453 #if USE_DESKTOP_FULLSCREEN
454 // in SDL 2.0, there is always support for desktop fullscreen mode
455 // (in SDL 1.2, there is only support for "real" fullscreen mode)
456 video.fullscreen_available = TRUE;
459 #if defined(TARGET_SDL2)
462 for (i = 0; modes[i] != NULL; i++)
463 checked_free(modes[i]);
470 /* set window icon */
471 SDLSetWindowIcon(program.sdl_icon_filename);
474 /* open SDL video output device (window or fullscreen mode) */
475 if (!SDLSetVideoMode(backbuffer, fullscreen))
476 Error(ERR_EXIT, "setting video mode failed");
479 /* !!! SDL2 can only set the window icon if the window already exists !!! */
480 /* set window icon */
481 SDLSetWindowIcon(program.sdl_icon_filename);
484 /* set window and icon title */
485 #if defined(TARGET_SDL2)
486 SDL_SetWindowTitle(sdl_window, program.window_title);
488 SDL_WM_SetCaption(program.window_title, program.window_title);
491 /* SDL cannot directly draw to the visible video framebuffer like X11,
492 but always uses a backbuffer, which is then blitted to the visible
493 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
494 visible video framebuffer with 'SDL_Flip', if the hardware supports
495 this). Therefore do not use an additional backbuffer for drawing, but
496 use a symbolic buffer (distinguishable from the SDL backbuffer) called
497 'window', which indicates that the SDL backbuffer should be updated to
498 the visible video framebuffer when attempting to blit to it.
500 For convenience, it seems to be a good idea to create this symbolic
501 buffer 'window' at the same size as the SDL backbuffer. Although it
502 should never be drawn to directly, it would do no harm nevertheless. */
504 /* create additional (symbolic) buffer for double-buffering */
506 ReCreateBitmap(window, video.width, video.height, video.depth);
508 *window = CreateBitmap(video.width, video.height, video.depth);
512 static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
515 SDL_Surface *new_surface = NULL;
517 #if defined(TARGET_SDL2)
518 static boolean fullscreen_enabled = FALSE;
519 int surface_flags_window = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE;
520 #if USE_DESKTOP_FULLSCREEN
521 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
523 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
527 int surface_flags_window = SURFACE_FLAGS;
528 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
531 int width = (fullscreen ? fullscreen_width : video.width);
532 int height = (fullscreen ? fullscreen_height : video.height);
533 int surface_flags = (fullscreen ? surface_flags_fullscreen :
534 surface_flags_window);
536 // default window size is unscaled
537 video.window_width = video.width;
538 video.window_height = video.height;
540 #if defined(TARGET_SDL2)
542 // store if initial screen mode on game start is fullscreen mode
543 if (sdl_window == NULL)
546 printf("::: GAME STARTS WITH FULLSCREEN %d\n", fullscreen);
549 video.fullscreen_initial = fullscreen;
553 float window_scaling_factor = (float)setup.window_scaling_percent / 100;
554 #if !USE_DESKTOP_FULLSCREEN
555 float screen_scaling_factor = (fullscreen ? 1 : window_scaling_factor);
558 video.window_width = window_scaling_factor * width;
559 video.window_height = window_scaling_factor * height;
562 printf("::: use window scaling factor %f\n", screen_scaling_factor);
565 if ((*backbuffer)->surface)
567 SDL_FreeSurface((*backbuffer)->surface);
568 (*backbuffer)->surface = NULL;
573 SDL_DestroyTexture(sdl_texture);
577 if (!(fullscreen && fullscreen_enabled))
581 SDL_DestroyRenderer(sdl_renderer);
587 SDL_DestroyWindow(sdl_window);
593 Error(ERR_INFO, "::: checking 'sdl_window' ...");
595 if (sdl_window == NULL)
596 Error(ERR_INFO, "::: calling SDL_CreateWindow() [%d, %d, %d] ...",
597 setup.fullscreen, fullscreen, fullscreen_enabled);
600 if (sdl_window == NULL)
601 sdl_window = SDL_CreateWindow(program.window_title,
602 SDL_WINDOWPOS_CENTERED,
603 SDL_WINDOWPOS_CENTERED,
604 #if USE_DESKTOP_FULLSCREEN
608 (int)(screen_scaling_factor * width),
609 (int)(screen_scaling_factor * height),
613 if (sdl_window != NULL)
616 /* if SDL_CreateRenderer() is called from within a VirtualBox Windows VM
617 *without* enabling 2D/3D acceleration and/or guest additions installed,
618 it will crash if flags are *not* set to SDL_RENDERER_SOFTWARE (because
619 it will try to use accelerated graphics and apparently fails miserably) */
620 if (sdl_renderer == NULL)
621 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_SOFTWARE);
623 if (sdl_renderer == NULL)
624 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
627 if (sdl_renderer != NULL)
629 SDL_RenderSetLogicalSize(sdl_renderer, width, height);
630 // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
631 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality);
633 sdl_texture = SDL_CreateTexture(sdl_renderer,
634 SDL_PIXELFORMAT_ARGB8888,
635 SDL_TEXTUREACCESS_STREAMING,
638 if (sdl_texture != NULL)
641 // use SDL default values for RGB masks and no alpha channel
642 new_surface = SDL_CreateRGBSurface(0, width, height, 32, 0,0,0, 0);
646 // (do not use alpha channel)
647 new_surface = SDL_CreateRGBSurface(0, width, height, 32,
653 // (this uses an alpha channel, which we don't want here)
654 new_surface = SDL_CreateRGBSurface(0, width, height, 32,
663 if (new_surface == NULL)
664 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
669 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
674 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
679 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
685 SDL_DestroyWindow(sdl_window);
687 sdl_window = SDL_CreateWindow(program.window_title,
688 SDL_WINDOWPOS_CENTERED,
689 SDL_WINDOWPOS_CENTERED,
693 if (sdl_window != NULL)
694 new_surface = SDL_GetWindowSurface(sdl_window);
698 new_surface = SDL_SetVideoMode(width, height, video.depth, surface_flags);
701 #if defined(TARGET_SDL2)
702 // store fullscreen state ("video.fullscreen_enabled" may not reflect this!)
703 if (new_surface != NULL)
704 fullscreen_enabled = fullscreen;
710 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
712 boolean success = TRUE;
715 #if defined(TARGET_SDL2)
716 // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
717 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
718 int surface_flags_window = SURFACE_FLAGS;
720 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
721 int surface_flags_window = SURFACE_FLAGS;
724 SDL_Surface *new_surface = NULL;
728 if (*backbuffer == NULL)
729 *backbuffer = CreateBitmapStruct();
731 /* (real bitmap might be larger in fullscreen mode with video offsets) */
732 (*backbuffer)->width = video.width;
733 (*backbuffer)->height = video.height;
735 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
737 setFullscreenParameters(setup.fullscreen_mode);
739 video_xoffset = fullscreen_xoffset;
740 video_yoffset = fullscreen_yoffset;
742 /* switch display to fullscreen mode, if available */
744 new_surface = SDLCreateScreen(backbuffer, TRUE);
747 #if defined(TARGET_SDL2)
748 sdl_window = SDL_CreateWindow(program.window_title,
749 SDL_WINDOWPOS_CENTERED,
750 SDL_WINDOWPOS_CENTERED,
751 fullscreen_width, fullscreen_height,
752 surface_flags_fullscreen);
753 if (sdl_window != NULL)
755 new_surface = SDL_GetWindowSurface(sdl_window);
757 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
758 // UpdateScreen(NULL); // immediately map window
761 new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
762 video.depth, surface_flags_fullscreen);
766 if (new_surface == NULL)
768 /* switching display to fullscreen mode failed */
769 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
771 /* do not try it again */
772 video.fullscreen_available = FALSE;
778 (*backbuffer)->surface = new_surface;
780 video.fullscreen_enabled = TRUE;
781 video.fullscreen_mode_current = setup.fullscreen_mode;
787 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
792 /* switch display to window mode */
794 new_surface = SDLCreateScreen(backbuffer, FALSE);
797 #if defined(TARGET_SDL2)
800 float screen_scaling_factor = 1.2;
801 int test_fullscreen = 0;
802 int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
803 surface_flags_window);
805 if ((*backbuffer)->surface)
806 SDL_FreeSurface((*backbuffer)->surface);
809 SDL_DestroyTexture(sdl_texture);
812 SDL_DestroyRenderer(sdl_renderer);
815 SDL_DestroyWindow(sdl_window);
817 sdl_window = SDL_CreateWindow(program.window_title,
818 SDL_WINDOWPOS_CENTERED,
819 SDL_WINDOWPOS_CENTERED,
820 (int)(screen_scaling_factor * video.width),
821 (int)(screen_scaling_factor * video.height),
824 if (sdl_window != NULL)
826 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
828 if (sdl_renderer != NULL)
830 SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height);
831 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
833 sdl_texture = SDL_CreateTexture(sdl_renderer,
834 SDL_PIXELFORMAT_ARGB8888,
835 SDL_TEXTUREACCESS_STREAMING,
836 video.width, video.height);
838 if (sdl_texture != NULL)
841 // (do not use alpha channel)
842 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
848 // (this uses an alpha channel, which we don't want here)
849 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
856 if (new_surface == NULL)
857 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
862 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
867 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
872 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
878 SDL_DestroyWindow(sdl_window);
880 sdl_window = SDL_CreateWindow(program.window_title,
881 SDL_WINDOWPOS_CENTERED,
882 SDL_WINDOWPOS_CENTERED,
883 video.width, video.height,
884 surface_flags_window);
886 if (sdl_window != NULL)
888 new_surface = SDL_GetWindowSurface(sdl_window);
890 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
891 // UpdateScreen(NULL); // immediately map window
896 new_surface = SDL_SetVideoMode(video.width, video.height,
897 video.depth, surface_flags_window);
901 if (new_surface == NULL)
903 /* switching display to window mode failed -- should not happen */
904 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
910 (*backbuffer)->surface = new_surface;
912 video.fullscreen_enabled = FALSE;
913 video.window_scaling_percent = setup.window_scaling_percent;
914 video.window_scaling_quality = setup.window_scaling_quality;
920 #if defined(TARGET_SDL2)
921 SDLRedrawWindow(); // map window
922 // UpdateScreen(NULL); // map window
926 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
928 #if defined(PLATFORM_WIN32)
930 SDL_SysWMinfo wminfo;
932 boolean wminfo_success = FALSE;
934 SDL_VERSION(&wminfo.version);
935 #if defined(TARGET_SDL2)
937 wminfo_success = SDL_GetWindowWMInfo(sdl_window, &wminfo);
939 wminfo_success = (SDL_GetWMInfo(&wminfo) == 1);
944 #if defined(TARGET_SDL2)
945 hwnd = wminfo.info.win.window;
947 hwnd = wminfo.window;
950 DragAcceptFiles(hwnd, TRUE);
959 void SDLSetWindowTitle()
961 #if defined(TARGET_SDL2)
962 SDL_SetWindowTitle(sdl_window, program.window_title);
964 SDL_WM_SetCaption(program.window_title, program.window_title);
968 #if defined(TARGET_SDL2)
969 void SDLSetWindowScaling(int window_scaling_percent)
971 if (sdl_window == NULL)
974 float window_scaling_factor = (float)window_scaling_percent / 100;
975 int new_window_width = (int)(window_scaling_factor * video.width);
976 int new_window_height = (int)(window_scaling_factor * video.height);
979 Error(ERR_DEBUG, "::: SDLSetWindowScaling(%d) ...", window_scaling_percent);
982 SDL_SetWindowSize(sdl_window, new_window_width, new_window_height);
984 video.window_scaling_percent = window_scaling_percent;
985 video.window_width = new_window_width;
986 video.window_height = new_window_height;
991 void SDLSetWindowScalingQuality(char *window_scaling_quality)
993 if (sdl_texture == NULL)
996 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, window_scaling_quality);
998 SDL_Texture *new_texture = SDL_CreateTexture(sdl_renderer,
999 SDL_PIXELFORMAT_ARGB8888,
1000 SDL_TEXTUREACCESS_STREAMING,
1001 video.width, video.height);
1003 if (new_texture != NULL)
1005 SDL_DestroyTexture(sdl_texture);
1007 sdl_texture = new_texture;
1012 video.window_scaling_quality = window_scaling_quality;
1015 void SDLSetWindowFullscreen(boolean fullscreen)
1017 if (sdl_window == NULL)
1020 #if USE_DESKTOP_FULLSCREEN
1021 int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
1023 int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
1027 Error(ERR_DEBUG, "::: SDL_SetWindowFullscreen(%d) ...", fullscreen);
1030 if (SDL_SetWindowFullscreen(sdl_window, flags) == 0)
1031 video.fullscreen_enabled = fullscreen;
1034 printf("::: SDLSetWindowFullscreen: %d, %d\n",
1035 fullscreen, video.fullscreen_initial);
1039 // if game started in fullscreen mode, window will also get fullscreen size
1040 if (!fullscreen && video.fullscreen_initial)
1042 SDLSetWindowScaling(setup.window_scaling_percent);
1043 SDL_SetWindowPosition(sdl_window,
1044 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
1046 video.fullscreen_initial = FALSE;
1051 void SDLRedrawWindow()
1057 void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height,
1061 SDL_Surface *surface =
1062 SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
1064 if (surface == NULL)
1065 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1067 SDLSetNativeSurface(&surface);
1069 bitmap->surface = surface;
1073 SDL_Surface *surface_tmp, *surface_native;
1075 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
1078 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1080 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
1081 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
1083 SDL_FreeSurface(surface_tmp);
1085 new_bitmap->surface = surface_native;
1089 void SDLFreeBitmapPointers(Bitmap *bitmap)
1091 if (bitmap->surface)
1092 SDL_FreeSurface(bitmap->surface);
1093 if (bitmap->surface_masked)
1094 SDL_FreeSurface(bitmap->surface_masked);
1095 bitmap->surface = NULL;
1096 bitmap->surface_masked = NULL;
1099 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1100 int src_x, int src_y, int width, int height,
1101 int dst_x, int dst_y, int mask_mode)
1103 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
1104 SDL_Rect src_rect, dst_rect;
1106 if (src_bitmap == backbuffer)
1108 src_x += video_xoffset;
1109 src_y += video_yoffset;
1115 src_rect.h = height;
1117 if (dst_bitmap == backbuffer || dst_bitmap == window)
1119 dst_x += video_xoffset;
1120 dst_y += video_yoffset;
1126 dst_rect.h = height;
1128 // if (src_bitmap != backbuffer || dst_bitmap != window)
1129 if (!(src_bitmap == backbuffer && dst_bitmap == window))
1130 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
1131 src_bitmap->surface_masked : src_bitmap->surface),
1132 &src_rect, real_dst_bitmap->surface, &dst_rect);
1134 #if defined(TARGET_SDL2)
1135 if (dst_bitmap == window)
1137 // SDL_UpdateWindowSurface(sdl_window);
1138 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
1139 UpdateScreen(&dst_rect);
1142 if (dst_bitmap == window)
1144 // SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
1145 UpdateScreen(&dst_rect);
1150 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
1153 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
1156 if (dst_bitmap == backbuffer || dst_bitmap == window)
1167 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
1169 #if defined(TARGET_SDL2)
1170 if (dst_bitmap == window)
1172 // SDL_UpdateWindowSurface(sdl_window);
1173 // SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
1174 UpdateScreen(&rect);
1177 if (dst_bitmap == window)
1179 // SDL_UpdateRect(backbuffer->surface, x, y, width, height);
1180 UpdateScreen(&rect);
1185 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
1186 int fade_mode, int fade_delay, int post_delay,
1187 void (*draw_border_function)(void))
1189 static boolean initialization_needed = TRUE;
1190 static SDL_Surface *surface_source = NULL;
1191 static SDL_Surface *surface_target = NULL;
1192 static SDL_Surface *surface_black = NULL;
1193 SDL_Surface *surface_screen = backbuffer->surface;
1194 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
1195 SDL_Rect src_rect, dst_rect;
1197 int src_x = x, src_y = y;
1198 int dst_x = x, dst_y = y;
1199 unsigned int time_last, time_current;
1201 /* check if screen size has changed */
1202 if (surface_source != NULL && (video.width != surface_source->w ||
1203 video.height != surface_source->h))
1205 SDL_FreeSurface(surface_source);
1206 SDL_FreeSurface(surface_target);
1207 SDL_FreeSurface(surface_black);
1209 initialization_needed = TRUE;
1215 src_rect.h = height;
1217 dst_x += video_xoffset;
1218 dst_y += video_yoffset;
1222 dst_rect.w = width; /* (ignored) */
1223 dst_rect.h = height; /* (ignored) */
1225 dst_rect2 = dst_rect;
1227 if (initialization_needed)
1229 #if defined(TARGET_SDL2)
1230 unsigned int flags = 0;
1232 unsigned int flags = SDL_SRCALPHA;
1234 /* use same surface type as screen surface */
1235 if ((surface_screen->flags & SDL_HWSURFACE))
1236 flags |= SDL_HWSURFACE;
1238 flags |= SDL_SWSURFACE;
1241 /* create surface for temporary copy of screen buffer (source) */
1242 if ((surface_source =
1243 SDL_CreateRGBSurface(flags,
1246 surface_screen->format->BitsPerPixel,
1247 surface_screen->format->Rmask,
1248 surface_screen->format->Gmask,
1249 surface_screen->format->Bmask,
1250 surface_screen->format->Amask)) == NULL)
1251 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1253 /* create surface for cross-fading screen buffer (target) */
1254 if ((surface_target =
1255 SDL_CreateRGBSurface(flags,
1258 surface_screen->format->BitsPerPixel,
1259 surface_screen->format->Rmask,
1260 surface_screen->format->Gmask,
1261 surface_screen->format->Bmask,
1262 surface_screen->format->Amask)) == NULL)
1263 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1265 /* create black surface for fading from/to black */
1266 if ((surface_black =
1267 SDL_CreateRGBSurface(flags,
1270 surface_screen->format->BitsPerPixel,
1271 surface_screen->format->Rmask,
1272 surface_screen->format->Gmask,
1273 surface_screen->format->Bmask,
1274 surface_screen->format->Amask)) == NULL)
1275 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1277 /* completely fill the surface with black color pixels */
1278 SDL_FillRect(surface_black, NULL,
1279 SDL_MapRGB(surface_screen->format, 0, 0, 0));
1281 initialization_needed = FALSE;
1284 /* copy source and target surfaces to temporary surfaces for fading */
1285 if (fade_mode & FADE_TYPE_TRANSFORM)
1287 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
1288 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
1290 else if (fade_mode & FADE_TYPE_FADE_IN)
1292 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
1293 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
1295 else /* FADE_TYPE_FADE_OUT */
1297 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
1298 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
1301 time_current = SDL_GetTicks();
1303 if (fade_mode == FADE_MODE_MELT)
1305 boolean done = FALSE;
1306 int melt_pixels = 2;
1307 int melt_columns = width / melt_pixels;
1308 int ypos[melt_columns];
1309 int max_steps = height / 8 + 32;
1314 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
1315 #if defined(TARGET_SDL2)
1316 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
1318 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
1321 ypos[0] = -GetSimpleRandom(16);
1323 for (i = 1 ; i < melt_columns; i++)
1325 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
1327 ypos[i] = ypos[i - 1] + r;
1340 time_last = time_current;
1341 time_current = SDL_GetTicks();
1342 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
1343 steps_final = MIN(MAX(0, steps), max_steps);
1347 done = (steps_done >= steps_final);
1349 for (i = 0 ; i < melt_columns; i++)
1357 else if (ypos[i] < height)
1362 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
1364 if (ypos[i] + dy >= height)
1365 dy = height - ypos[i];
1367 /* copy part of (appearing) target surface to upper area */
1368 src_rect.x = src_x + i * melt_pixels;
1369 // src_rect.y = src_y + ypos[i];
1371 src_rect.w = melt_pixels;
1373 src_rect.h = ypos[i] + dy;
1375 dst_rect.x = dst_x + i * melt_pixels;
1376 // dst_rect.y = dst_y + ypos[i];
1379 if (steps_done >= steps_final)
1380 SDL_BlitSurface(surface_target, &src_rect,
1381 surface_screen, &dst_rect);
1385 /* copy part of (disappearing) source surface to lower area */
1386 src_rect.x = src_x + i * melt_pixels;
1388 src_rect.w = melt_pixels;
1389 src_rect.h = height - ypos[i];
1391 dst_rect.x = dst_x + i * melt_pixels;
1392 dst_rect.y = dst_y + ypos[i];
1394 if (steps_done >= steps_final)
1395 SDL_BlitSurface(surface_source, &src_rect,
1396 surface_screen, &dst_rect);
1402 src_rect.x = src_x + i * melt_pixels;
1404 src_rect.w = melt_pixels;
1405 src_rect.h = height;
1407 dst_rect.x = dst_x + i * melt_pixels;
1410 if (steps_done >= steps_final)
1411 SDL_BlitSurface(surface_target, &src_rect,
1412 surface_screen, &dst_rect);
1416 if (steps_done >= steps_final)
1418 if (draw_border_function != NULL)
1419 draw_border_function();
1421 #if defined(TARGET_SDL2)
1422 // SDL_UpdateWindowSurface(sdl_window);
1423 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
1424 UpdateScreen(&dst_rect2);
1426 // SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
1427 UpdateScreen(&dst_rect2);
1437 for (alpha = 0.0; alpha < 255.0;)
1439 time_last = time_current;
1440 time_current = SDL_GetTicks();
1441 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
1442 alpha_final = MIN(MAX(0, alpha), 255);
1444 /* draw existing (source) image to screen buffer */
1445 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
1447 /* draw new (target) image to screen buffer using alpha blending */
1448 #if defined(TARGET_SDL2)
1449 SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
1450 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
1452 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
1454 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
1456 if (draw_border_function != NULL)
1457 draw_border_function();
1460 /* only update the region of the screen that is affected from fading */
1461 #if defined(TARGET_SDL2)
1462 // SDL_UpdateWindowSurface(sdl_window);
1463 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
1464 UpdateScreen(&dst_rect);
1466 // SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
1467 UpdateScreen(&dst_rect);
1470 SDL_Flip(surface_screen);
1478 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
1479 int to_x, int to_y, Uint32 color)
1481 SDL_Surface *surface = dst_bitmap->surface;
1485 swap_numbers(&from_x, &to_x);
1488 swap_numbers(&from_y, &to_y);
1492 rect.w = (to_x - from_x + 1);
1493 rect.h = (to_y - from_y + 1);
1495 if (dst_bitmap == backbuffer || dst_bitmap == window)
1497 rect.x += video_xoffset;
1498 rect.y += video_yoffset;
1501 SDL_FillRect(surface, &rect, color);
1504 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
1505 int to_x, int to_y, Uint32 color)
1507 if (dst_bitmap == backbuffer || dst_bitmap == window)
1509 from_x += video_xoffset;
1510 from_y += video_yoffset;
1511 to_x += video_xoffset;
1512 to_y += video_yoffset;
1515 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
1519 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
1520 int num_points, Uint32 color)
1525 for (i = 0; i < num_points - 1; i++)
1527 for (x = 0; x < line_width; x++)
1529 for (y = 0; y < line_width; y++)
1531 int dx = x - line_width / 2;
1532 int dy = y - line_width / 2;
1534 if ((x == 0 && y == 0) ||
1535 (x == 0 && y == line_width - 1) ||
1536 (x == line_width - 1 && y == 0) ||
1537 (x == line_width - 1 && y == line_width - 1))
1540 sge_Line(surface, points[i].x + dx, points[i].y + dy,
1541 points[i+1].x + dx, points[i+1].y + dy, color);
1548 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
1550 SDL_Surface *surface = src_bitmap->surface;
1552 if (src_bitmap == backbuffer || src_bitmap == window)
1558 switch (surface->format->BytesPerPixel)
1560 case 1: /* assuming 8-bpp */
1562 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
1566 case 2: /* probably 15-bpp or 16-bpp */
1568 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
1572 case 3: /* slow 24-bpp mode; usually not used */
1574 /* does this work? */
1575 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
1579 shift = surface->format->Rshift;
1580 color |= *(pix + shift / 8) >> shift;
1581 shift = surface->format->Gshift;
1582 color |= *(pix + shift / 8) >> shift;
1583 shift = surface->format->Bshift;
1584 color |= *(pix + shift / 8) >> shift;
1590 case 4: /* probably 32-bpp */
1592 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
1601 /* ========================================================================= */
1602 /* The following functions were taken from the SGE library */
1603 /* (SDL Graphics Extension Library) by Anders Lindström */
1604 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
1605 /* ========================================================================= */
1607 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1609 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
1611 switch (surface->format->BytesPerPixel)
1615 /* Assuming 8-bpp */
1616 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1622 /* Probably 15-bpp or 16-bpp */
1623 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1629 /* Slow 24-bpp mode, usually not used */
1633 /* Gack - slow, but endian correct */
1634 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1635 shift = surface->format->Rshift;
1636 *(pix+shift/8) = color>>shift;
1637 shift = surface->format->Gshift;
1638 *(pix+shift/8) = color>>shift;
1639 shift = surface->format->Bshift;
1640 *(pix+shift/8) = color>>shift;
1646 /* Probably 32-bpp */
1647 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1654 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1655 Uint8 R, Uint8 G, Uint8 B)
1657 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
1660 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1662 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1665 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1667 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1670 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1675 /* Gack - slow, but endian correct */
1676 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1677 shift = surface->format->Rshift;
1678 *(pix+shift/8) = color>>shift;
1679 shift = surface->format->Gshift;
1680 *(pix+shift/8) = color>>shift;
1681 shift = surface->format->Bshift;
1682 *(pix+shift/8) = color>>shift;
1685 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1687 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1690 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
1692 switch (dest->format->BytesPerPixel)
1695 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
1699 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
1703 _PutPixel24(dest,x,y,color);
1707 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
1712 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1714 if (SDL_MUSTLOCK(surface))
1716 if (SDL_LockSurface(surface) < 0)
1722 _PutPixel(surface, x, y, color);
1724 if (SDL_MUSTLOCK(surface))
1726 SDL_UnlockSurface(surface);
1730 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1731 Uint8 r, Uint8 g, Uint8 b)
1733 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
1736 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
1738 if (y >= 0 && y <= dest->h - 1)
1740 switch (dest->format->BytesPerPixel)
1743 return y*dest->pitch;
1747 return y*dest->pitch/2;
1751 return y*dest->pitch;
1755 return y*dest->pitch/4;
1763 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
1765 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
1767 switch (surface->format->BytesPerPixel)
1771 /* Assuming 8-bpp */
1772 *((Uint8 *)surface->pixels + ypitch + x) = color;
1778 /* Probably 15-bpp or 16-bpp */
1779 *((Uint16 *)surface->pixels + ypitch + x) = color;
1785 /* Slow 24-bpp mode, usually not used */
1789 /* Gack - slow, but endian correct */
1790 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1791 shift = surface->format->Rshift;
1792 *(pix+shift/8) = color>>shift;
1793 shift = surface->format->Gshift;
1794 *(pix+shift/8) = color>>shift;
1795 shift = surface->format->Bshift;
1796 *(pix+shift/8) = color>>shift;
1802 /* Probably 32-bpp */
1803 *((Uint32 *)surface->pixels + ypitch + x) = color;
1810 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1815 if (SDL_MUSTLOCK(Surface))
1817 if (SDL_LockSurface(Surface) < 0)
1830 /* Do the clipping */
1831 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1835 if (x2 > Surface->w - 1)
1836 x2 = Surface->w - 1;
1843 SDL_FillRect(Surface, &l, Color);
1845 if (SDL_MUSTLOCK(Surface))
1847 SDL_UnlockSurface(Surface);
1851 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1852 Uint8 R, Uint8 G, Uint8 B)
1854 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1857 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1868 /* Do the clipping */
1869 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1873 if (x2 > Surface->w - 1)
1874 x2 = Surface->w - 1;
1881 SDL_FillRect(Surface, &l, Color);
1884 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1889 if (SDL_MUSTLOCK(Surface))
1891 if (SDL_LockSurface(Surface) < 0)
1904 /* Do the clipping */
1905 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1909 if (y2 > Surface->h - 1)
1910 y2 = Surface->h - 1;
1917 SDL_FillRect(Surface, &l, Color);
1919 if (SDL_MUSTLOCK(Surface))
1921 SDL_UnlockSurface(Surface);
1925 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1926 Uint8 R, Uint8 G, Uint8 B)
1928 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1931 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1942 /* Do the clipping */
1943 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1947 if (y2 > Surface->h - 1)
1948 y2 = Surface->h - 1;
1955 SDL_FillRect(Surface, &l, Color);
1958 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1959 Sint16 x2, Sint16 y2, Uint32 Color,
1960 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1963 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1968 sdx = (dx < 0) ? -1 : 1;
1969 sdy = (dy < 0) ? -1 : 1;
1981 for (x = 0; x < dx; x++)
1983 Callback(Surface, px, py, Color);
1997 for (y = 0; y < dy; y++)
1999 Callback(Surface, px, py, Color);
2013 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
2014 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
2015 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
2018 sge_DoLine(Surface, X1, Y1, X2, Y2,
2019 SDL_MapRGB(Surface->format, R, G, B), Callback);
2022 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
2025 if (SDL_MUSTLOCK(Surface))
2027 if (SDL_LockSurface(Surface) < 0)
2032 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
2034 /* unlock the display */
2035 if (SDL_MUSTLOCK(Surface))
2037 SDL_UnlockSurface(Surface);
2041 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
2042 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
2044 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
2047 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
2049 if (dst_bitmap == backbuffer || dst_bitmap == window)
2055 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
2060 -----------------------------------------------------------------------------
2061 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
2062 -----------------------------------------------------------------------------
2065 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
2066 int width, int height, Uint32 color)
2070 for (y = src_y; y < src_y + height; y++)
2072 for (x = src_x; x < src_x + width; x++)
2074 Uint32 pixel = SDLGetPixel(bitmap, x, y);
2076 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
2081 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
2082 int src_x, int src_y, int width, int height,
2083 int dst_x, int dst_y)
2087 for (y = 0; y < height; y++)
2089 for (x = 0; x < width; x++)
2091 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
2093 if (pixel != BLACK_PIXEL)
2094 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
2100 /* ========================================================================= */
2101 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
2102 /* (Rotozoomer) by Andreas Schiffler */
2103 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
2104 /* ========================================================================= */
2107 -----------------------------------------------------------------------------
2110 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
2111 -----------------------------------------------------------------------------
2122 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
2125 tColorRGBA *sp, *csp, *dp;
2132 sp = csp = (tColorRGBA *) src->pixels;
2133 dp = (tColorRGBA *) dst->pixels;
2135 sgap = src->pitch - src->w * 4;
2137 dgap = dst->pitch - dst->w * 4;
2139 for (y = 0; y < dst->h; y++)
2143 for (x = 0; x < dst->w; x++)
2145 tColorRGBA *sp0 = sp;
2146 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
2147 tColorRGBA *sp00 = &sp0[0];
2148 tColorRGBA *sp01 = &sp0[1];
2149 tColorRGBA *sp10 = &sp1[0];
2150 tColorRGBA *sp11 = &sp1[1];
2153 /* create new color pixel from all four source color pixels */
2154 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
2155 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
2156 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
2157 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
2162 /* advance source pointers */
2165 /* advance destination pointer */
2169 /* advance source pointer */
2170 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
2172 /* advance destination pointers */
2173 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
2181 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
2183 int x, y, *sax, *say, *csax, *csay;
2185 tColorRGBA *sp, *csp, *csp0, *dp;
2188 /* use specialized zoom function when scaling down to exactly half size */
2189 if (src->w == 2 * dst->w &&
2190 src->h == 2 * dst->h)
2191 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
2194 printf("::: zoomSurfaceRGBA: %d, %d -> %d, %d\n",
2195 src->w, src->h, dst->w, dst->h);
2198 /* variable setup */
2199 sx = (float) src->w / (float) dst->w;
2200 sy = (float) src->h / (float) dst->h;
2202 /* allocate memory for row increments */
2203 csax = sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
2204 csay = say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
2206 /* precalculate row increments */
2207 for (x = 0; x <= dst->w; x++)
2208 *csax++ = (int)(sx * x);
2210 for (y = 0; y <= dst->h; y++)
2211 *csay++ = (int)(sy * y);
2214 sp = csp = csp0 = (tColorRGBA *) src->pixels;
2215 dp = (tColorRGBA *) dst->pixels;
2216 dgap = dst->pitch - dst->w * 4;
2219 for (y = 0; y < dst->h; y++)
2224 for (x = 0; x < dst->w; x++)
2229 /* advance source pointers */
2233 /* advance destination pointer */
2237 /* advance source pointer */
2239 csp = (tColorRGBA *) ((Uint8 *) csp0 + *csay * src->pitch);
2241 /* advance destination pointers */
2242 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
2253 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
2255 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
2256 tColorRGBA *sp, *csp, *dp;
2262 /* use specialized zoom function when scaling down to exactly half size */
2263 if (src->w == 2 * dst->w &&
2264 src->h == 2 * dst->h)
2265 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
2267 /* variable setup */
2268 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
2269 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
2271 /* allocate memory for row increments */
2272 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
2273 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
2275 /* precalculate row increments */
2278 for (x = 0; x <= dst->w; x++)
2288 for (y = 0; y <= dst->h; y++)
2297 sp = csp = (tColorRGBA *) src->pixels;
2298 dp = (tColorRGBA *) dst->pixels;
2300 sgap = src->pitch - src->w * 4;
2302 dgap = dst->pitch - dst->w * 4;
2305 for (y = 0; y < dst->h; y++)
2310 for (x = 0; x < dst->w; x++)
2315 /* advance source pointers */
2317 sp += (*csax >> 16);
2319 /* advance destination pointer */
2323 /* advance source pointer */
2325 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
2327 /* advance destination pointers */
2328 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
2340 -----------------------------------------------------------------------------
2343 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
2344 -----------------------------------------------------------------------------
2347 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
2349 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
2350 Uint8 *sp, *dp, *csp;
2353 /* variable setup */
2354 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
2355 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
2357 /* allocate memory for row increments */
2358 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
2359 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
2361 /* precalculate row increments */
2364 for (x = 0; x < dst->w; x++)
2367 *csax = (csx >> 16);
2374 for (y = 0; y < dst->h; y++)
2377 *csay = (csy >> 16);
2384 for (x = 0; x < dst->w; x++)
2392 for (y = 0; y < dst->h; y++)
2399 sp = csp = (Uint8 *) src->pixels;
2400 dp = (Uint8 *) dst->pixels;
2401 dgap = dst->pitch - dst->w;
2405 for (y = 0; y < dst->h; y++)
2409 for (x = 0; x < dst->w; x++)
2414 /* advance source pointers */
2418 /* advance destination pointer */
2422 /* advance source pointer (for row) */
2423 csp += ((*csay) * src->pitch);
2426 /* advance destination pointers */
2437 -----------------------------------------------------------------------------
2440 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
2441 'zoomx' and 'zoomy' are scaling factors for width and height.
2442 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
2443 into a 32bit RGBA format on the fly.
2444 -----------------------------------------------------------------------------
2447 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
2449 SDL_Surface *zoom_src = NULL;
2450 SDL_Surface *zoom_dst = NULL;
2451 boolean is_converted = FALSE;
2458 /* determine if source surface is 32 bit or 8 bit */
2459 is_32bit = (src->format->BitsPerPixel == 32);
2461 if (is_32bit || src->format->BitsPerPixel == 8)
2463 /* use source surface 'as is' */
2468 /* new source surface is 32 bit with a defined RGB ordering */
2469 zoom_src = SDL_CreateRGBSurface(SURFACE_FLAGS, src->w, src->h, 32,
2470 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
2471 SDL_BlitSurface(src, NULL, zoom_src, NULL);
2473 is_converted = TRUE;
2476 /* allocate surface to completely contain the zoomed surface */
2479 /* target surface is 32 bit with source RGBA/ABGR ordering */
2480 zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 32,
2481 zoom_src->format->Rmask,
2482 zoom_src->format->Gmask,
2483 zoom_src->format->Bmask, 0);
2487 /* target surface is 8 bit */
2488 zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 8,
2492 /* lock source surface */
2493 SDL_LockSurface(zoom_src);
2495 /* check which kind of surface we have */
2498 /* call the 32 bit transformation routine to do the zooming */
2499 zoomSurfaceRGBA(zoom_src, zoom_dst);
2504 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
2505 zoom_dst->format->palette->colors[i] =
2506 zoom_src->format->palette->colors[i];
2507 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
2509 /* call the 8 bit transformation routine to do the zooming */
2510 zoomSurfaceY(zoom_src, zoom_dst);
2513 /* unlock source surface */
2514 SDL_UnlockSurface(zoom_src);
2516 /* free temporary surface */
2518 SDL_FreeSurface(zoom_src);
2520 /* return destination surface */
2526 Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
2530 Bitmap *dst_bitmap = CreateBitmapStruct();
2531 SDL_Surface **dst_surface = &dst_bitmap->surface;
2533 dst_width = MAX(1, dst_width); /* prevent zero bitmap width */
2534 dst_height = MAX(1, dst_height); /* prevent zero bitmap height */
2536 dst_bitmap->width = dst_width;
2537 dst_bitmap->height = dst_height;
2539 /* create zoomed temporary surface from source surface */
2540 *dst_surface = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2542 /* create native format destination surface from zoomed temporary surface */
2543 SDLSetNativeSurface(dst_surface);
2549 Bitmap *dst_bitmap = CreateBitmapStruct();
2550 SDL_Surface *sdl_surface_tmp;
2552 dst_width = MAX(1, dst_width); /* prevent zero bitmap width */
2553 dst_height = MAX(1, dst_height); /* prevent zero bitmap height */
2555 dst_bitmap->width = dst_width;
2556 dst_bitmap->height = dst_height;
2558 print_timestamp_init("SDLZoomBitmap");
2560 /* create zoomed temporary surface from source surface */
2561 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2562 print_timestamp_time("zoomSurface");
2564 /* create native format destination surface from zoomed temporary surface */
2565 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
2566 print_timestamp_time("SDL_DisplayFormat");
2568 /* free temporary surface */
2569 SDL_FreeSurface(sdl_surface_tmp);
2570 print_timestamp_time("SDL_FreeSurface");
2572 print_timestamp_done("SDLZoomBitmap");
2581 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
2583 SDL_Surface *sdl_surface_tmp;
2584 int dst_width = dst_bitmap->width;
2585 int dst_height = dst_bitmap->height;
2587 print_timestamp_init("SDLZoomBitmap");
2589 /* throw away old destination surface */
2590 SDL_FreeSurface(dst_bitmap->surface);
2591 print_timestamp_time("SDL_FreeSurface");
2593 /* create zoomed temporary surface from source surface */
2594 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2595 print_timestamp_time("zoomSurface");
2597 /* create native format destination surface from zoomed temporary surface */
2598 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
2599 print_timestamp_time("SDL_DisplayFormat");
2601 /* free temporary surface */
2602 SDL_FreeSurface(sdl_surface_tmp);
2603 print_timestamp_time("SDL_FreeSurface");
2605 print_timestamp_done("SDLZoomBitmap");
2611 /* ========================================================================= */
2612 /* load image to bitmap */
2613 /* ========================================================================= */
2615 Bitmap *SDLLoadImage(char *filename)
2617 Bitmap *new_bitmap = CreateBitmapStruct();
2618 SDL_Surface *sdl_image_tmp;
2620 print_timestamp_init("SDLLoadImage");
2622 print_timestamp_time(getBaseNamePtr(filename));
2624 /* load image to temporary surface */
2625 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
2627 SetError("IMG_Load(): %s", SDL_GetError());
2632 print_timestamp_time("IMG_Load");
2634 UPDATE_BUSY_STATE();
2636 /* create native non-transparent surface for current image */
2638 if ((new_bitmap->surface = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
2640 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2645 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
2647 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2653 print_timestamp_time("SDL_DisplayFormat (opaque)");
2655 UPDATE_BUSY_STATE();
2657 /* create native transparent surface for current image */
2658 SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
2659 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
2661 if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
2663 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2668 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
2670 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2676 print_timestamp_time("SDL_DisplayFormat (masked)");
2678 UPDATE_BUSY_STATE();
2680 /* free temporary surface */
2681 SDL_FreeSurface(sdl_image_tmp);
2683 new_bitmap->width = new_bitmap->surface->w;
2684 new_bitmap->height = new_bitmap->surface->h;
2686 print_timestamp_done("SDLLoadImage");
2692 /* ------------------------------------------------------------------------- */
2693 /* custom cursor fuctions */
2694 /* ------------------------------------------------------------------------- */
2696 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
2698 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
2699 cursor_info->width, cursor_info->height,
2700 cursor_info->hot_x, cursor_info->hot_y);
2703 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
2705 static struct MouseCursorInfo *last_cursor_info = NULL;
2706 static struct MouseCursorInfo *last_cursor_info2 = NULL;
2707 static SDL_Cursor *cursor_default = NULL;
2708 static SDL_Cursor *cursor_current = NULL;
2710 /* if invoked for the first time, store the SDL default cursor */
2711 if (cursor_default == NULL)
2712 cursor_default = SDL_GetCursor();
2714 /* only create new cursor if cursor info (custom only) has changed */
2715 if (cursor_info != NULL && cursor_info != last_cursor_info)
2717 cursor_current = create_cursor(cursor_info);
2718 last_cursor_info = cursor_info;
2721 /* only set new cursor if cursor info (custom or NULL) has changed */
2722 if (cursor_info != last_cursor_info2)
2723 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
2725 last_cursor_info2 = cursor_info;
2729 /* ========================================================================= */
2730 /* audio functions */
2731 /* ========================================================================= */
2733 void SDLOpenAudio(void)
2735 #if !defined(TARGET_SDL2)
2736 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
2737 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
2740 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
2742 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
2746 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
2747 AUDIO_NUM_CHANNELS_STEREO,
2748 setup.system.audio_fragment_size) < 0)
2750 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
2754 audio.sound_available = TRUE;
2755 audio.music_available = TRUE;
2756 audio.loops_available = TRUE;
2757 audio.sound_enabled = TRUE;
2759 /* set number of available mixer channels */
2760 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
2761 audio.music_channel = MUSIC_CHANNEL;
2762 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
2764 Mixer_InitChannels();
2767 void SDLCloseAudio(void)
2770 Mix_HaltChannel(-1);
2773 SDL_QuitSubSystem(SDL_INIT_AUDIO);
2777 /* ========================================================================= */
2778 /* event functions */
2779 /* ========================================================================= */
2781 void SDLNextEvent(Event *event)
2783 SDL_WaitEvent(event);
2785 if (event->type == EVENT_BUTTONPRESS ||
2786 event->type == EVENT_BUTTONRELEASE)
2788 if (((ButtonEvent *)event)->x > video_xoffset)
2789 ((ButtonEvent *)event)->x -= video_xoffset;
2791 ((ButtonEvent *)event)->x = 0;
2792 if (((ButtonEvent *)event)->y > video_yoffset)
2793 ((ButtonEvent *)event)->y -= video_yoffset;
2795 ((ButtonEvent *)event)->y = 0;
2797 else if (event->type == EVENT_MOTIONNOTIFY)
2799 if (((MotionEvent *)event)->x > video_xoffset)
2800 ((MotionEvent *)event)->x -= video_xoffset;
2802 ((MotionEvent *)event)->x = 0;
2803 if (((MotionEvent *)event)->y > video_yoffset)
2804 ((MotionEvent *)event)->y -= video_yoffset;
2806 ((MotionEvent *)event)->y = 0;
2810 void SDLHandleWindowManagerEvent(Event *event)
2812 #if defined(PLATFORM_WIN32)
2813 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
2814 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
2816 #if defined(TARGET_SDL2)
2817 if (syswmmsg->msg.win.msg == WM_DROPFILES)
2819 if (syswmmsg->msg == WM_DROPFILES)
2822 #if defined(TARGET_SDL2)
2823 HDROP hdrop = (HDROP)syswmmsg->msg.win.wParam;
2825 HDROP hdrop = (HDROP)syswmmsg->wParam;
2829 printf("::: SDL_SYSWMEVENT:\n");
2831 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
2833 for (i = 0; i < num_files; i++)
2835 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
2836 char buffer[buffer_len + 1];
2838 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
2840 printf("::: - '%s'\n", buffer);
2843 #if defined(TARGET_SDL2)
2844 DragFinish((HDROP)syswmmsg->msg.win.wParam);
2846 DragFinish((HDROP)syswmmsg->wParam);
2853 /* ========================================================================= */
2854 /* joystick functions */
2855 /* ========================================================================= */
2857 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
2858 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2859 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2861 static boolean SDLOpenJoystick(int nr)
2863 if (nr < 0 || nr > MAX_PLAYERS)
2866 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
2869 static void SDLCloseJoystick(int nr)
2871 if (nr < 0 || nr > MAX_PLAYERS)
2874 SDL_JoystickClose(sdl_joystick[nr]);
2876 sdl_joystick[nr] = NULL;
2879 static boolean SDLCheckJoystickOpened(int nr)
2881 if (nr < 0 || nr > MAX_PLAYERS)
2884 #if defined(TARGET_SDL2)
2885 return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
2887 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
2891 void HandleJoystickEvent(Event *event)
2895 case SDL_JOYAXISMOTION:
2896 if (event->jaxis.axis < 2)
2897 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
2900 case SDL_JOYBUTTONDOWN:
2901 if (event->jbutton.button < 2)
2902 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
2905 case SDL_JOYBUTTONUP:
2906 if (event->jbutton.button < 2)
2907 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
2915 void SDLInitJoysticks()
2917 static boolean sdl_joystick_subsystem_initialized = FALSE;
2918 boolean print_warning = !sdl_joystick_subsystem_initialized;
2921 if (!sdl_joystick_subsystem_initialized)
2923 sdl_joystick_subsystem_initialized = TRUE;
2925 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2927 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
2932 for (i = 0; i < MAX_PLAYERS; i++)
2934 /* get configured joystick for this player */
2935 char *device_name = setup.input[i].joy.device_name;
2936 int joystick_nr = getJoystickNrFromDeviceName(device_name);
2938 if (joystick_nr >= SDL_NumJoysticks())
2940 if (setup.input[i].use_joystick && print_warning)
2941 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
2946 /* misuse joystick file descriptor variable to store joystick number */
2947 joystick.fd[i] = joystick_nr;
2949 if (joystick_nr == -1)
2952 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
2953 if (SDLCheckJoystickOpened(joystick_nr))
2954 SDLCloseJoystick(joystick_nr);
2956 if (!setup.input[i].use_joystick)
2959 if (!SDLOpenJoystick(joystick_nr))
2962 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
2967 joystick.status = JOYSTICK_ACTIVATED;
2971 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
2973 if (nr < 0 || nr >= MAX_PLAYERS)
2977 *x = sdl_js_axis[nr][0];
2979 *y = sdl_js_axis[nr][1];
2982 *b1 = sdl_js_button[nr][0];
2984 *b2 = sdl_js_button[nr][1];
2989 #endif /* TARGET_SDL */