1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
21 #if defined(TARGET_SDL)
23 /* ========================================================================= */
25 /* ========================================================================= */
27 /* SDL internal variables */
28 #if defined(TARGET_SDL2)
29 static SDL_Window *sdl_window = NULL;
30 static SDL_Renderer *sdl_renderer = NULL;
31 static SDL_Texture *sdl_texture = NULL;
33 #define USE_RENDERER TRUE
36 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
37 static int fullscreen_width;
38 static int fullscreen_height;
39 static int fullscreen_xoffset;
40 static int fullscreen_yoffset;
41 static int video_xoffset;
42 static int video_yoffset;
43 static boolean limit_screen_updates = FALSE;
46 /* functions from SGE library */
47 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
49 void SDLLimitScreenUpdates(boolean enable)
51 limit_screen_updates = enable;
54 static void UpdateScreen(SDL_Rect *rect)
56 static unsigned int update_screen_delay = 0;
57 unsigned int update_screen_delay_value = 20; /* (milliseconds) */
60 if (limit_screen_updates &&
61 !DelayReached(&update_screen_delay, update_screen_delay_value))
64 LimitScreenUpdates(FALSE);
67 #if defined(TARGET_SDL2)
69 SDL_Surface *screen = backbuffer->surface;
74 int bytes_x = screen->pitch / video.width;
75 int bytes_y = screen->pitch;
77 if (video.fullscreen_enabled)
78 bytes_x = screen->pitch / fullscreen_width;
80 SDL_UpdateTexture(sdl_texture, rect,
81 screen->pixels + rect->x * bytes_x + rect->y * bytes_y,
86 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
89 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
91 SDL_RenderClear(sdl_renderer);
92 SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
93 SDL_RenderPresent(sdl_renderer);
96 SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
98 SDL_UpdateWindowSurface(sdl_window);
103 SDL_UpdateRects(backbuffer->surface, 1, rect);
105 SDL_UpdateRect(backbuffer->surface, 0, 0, 0, 0);
109 static void setFullscreenParameters(char *fullscreen_mode_string)
111 #if defined(TARGET_SDL2)
112 fullscreen_width = video.width;
113 fullscreen_height = video.height;
114 fullscreen_xoffset = 0;
115 fullscreen_yoffset = 0;
119 struct ScreenModeInfo *fullscreen_mode;
122 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
124 if (fullscreen_mode == NULL)
127 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
129 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
130 fullscreen_mode->height == video.fullscreen_modes[i].height)
132 fullscreen_width = fullscreen_mode->width;
133 fullscreen_height = fullscreen_mode->height;
135 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
136 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
144 static void SDLSetWindowIcon(char *basename)
146 /* (setting the window icon on Mac OS X would replace the high-quality
147 dock icon with the currently smaller (and uglier) icon from file) */
149 #if !defined(PLATFORM_MACOSX)
150 char *filename = getCustomImageFilename(basename);
151 SDL_Surface *surface;
153 if (filename == NULL)
155 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
160 if ((surface = IMG_Load(filename)) == NULL)
162 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
167 /* set transparent color */
168 SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
169 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
171 #if defined(TARGET_SDL2)
172 SDL_SetWindowIcon(sdl_window, surface);
174 SDL_WM_SetIcon(surface, NULL);
179 #if defined(TARGET_SDL2)
181 static boolean equalSDLPixelFormat(SDL_PixelFormat *format1,
182 SDL_PixelFormat *format2)
184 return (format1->format == format2->format &&
185 format1->BitsPerPixel == format2->BitsPerPixel &&
186 format1->BytesPerPixel == format2->BytesPerPixel &&
187 format1->Rmask == format2->Rmask &&
188 format1->Gmask == format2->Gmask &&
189 format1->Bmask == format2->Bmask &&
190 format1->Amask == format2->Amask);
193 boolean SDLSetNativeSurface(SDL_Surface **surface)
195 SDL_Surface *new_surface;
197 if (surface == NULL ||
199 backbuffer == NULL ||
200 backbuffer->surface == NULL)
203 // if pixel format already optimized for destination surface, do nothing
204 if (equalSDLPixelFormat((*surface)->format, backbuffer->surface->format))
207 new_surface = SDL_ConvertSurface(*surface, backbuffer->surface->format, 0);
209 SDL_FreeSurface(*surface);
211 *surface = new_surface;
216 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
218 if (surface == NULL ||
219 backbuffer == NULL ||
220 backbuffer->surface == NULL)
223 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
226 SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface)
228 if (surface == NULL ||
229 backbuffer == NULL ||
230 backbuffer->surface == NULL)
234 boolean same_pixel_format =
235 equalSDLPixelFormat(surface->format, backbuffer->surface->format);
237 printf("::: SDL_DisplayFormat: %08x -> %08x [%08x, %08x, %08x -> %08x, %08x, %08x] [%d, %d -> %d, %d] => %s\n",
238 surface->format->format,
239 backbuffer->surface->format->format,
240 surface->format->Rmask,
241 surface->format->Gmask,
242 surface->format->Bmask,
243 backbuffer->surface->format->Rmask,
244 backbuffer->surface->format->Gmask,
245 backbuffer->surface->format->Bmask,
246 surface->format->BitsPerPixel,
247 surface->format->BytesPerPixel,
248 backbuffer->surface->format->BitsPerPixel,
249 backbuffer->surface->format->BytesPerPixel,
250 (same_pixel_format ? "SAME" : "DIFF"));
253 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
258 boolean SDLSetNativeSurface(SDL_Surface **surface)
260 SDL_Surface *new_surface;
265 new_surface = SDL_DisplayFormat(*surface);
267 if (new_surface == NULL)
268 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
270 SDL_FreeSurface(*surface);
272 *surface = new_surface;
277 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
279 SDL_Surface *new_surface = SDL_DisplayFormat(surface);
281 if (new_surface == NULL)
282 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
289 void SDLInitVideoDisplay(void)
291 #if !defined(TARGET_SDL2)
292 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
293 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
295 SDL_putenv("SDL_VIDEO_CENTERED=1");
298 /* initialize SDL video */
299 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
300 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
302 /* set default SDL depth */
303 #if !defined(TARGET_SDL2)
304 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
306 video.default_depth = 32; // (how to determine video depth in SDL2?)
310 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
313 #if !defined(TARGET_SDL2)
314 static int screen_xy[][2] =
322 SDL_Rect **modes = NULL;
323 boolean hardware_fullscreen_available = TRUE;
326 /* default: normal game window size */
327 fullscreen_width = video.width;
328 fullscreen_height = video.height;
329 fullscreen_xoffset = 0;
330 fullscreen_yoffset = 0;
332 #if !defined(TARGET_SDL2)
333 /* determine required standard fullscreen mode for game screen size */
334 for (i = 0; screen_xy[i][0] != -1; i++)
336 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
338 fullscreen_width = screen_xy[i][0];
339 fullscreen_height = screen_xy[i][1];
345 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
346 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
350 checked_free(video.fullscreen_modes);
352 video.fullscreen_modes = NULL;
353 video.fullscreen_mode_current = NULL;
356 video.window_scaling_percent = setup.window_scaling_percent;
357 video.window_scaling_quality = setup.window_scaling_quality;
359 #if defined(TARGET_SDL2)
360 int num_displays = SDL_GetNumVideoDisplays();
362 if (num_displays > 0)
364 // currently only display modes of first display supported
365 int num_modes = SDL_GetNumDisplayModes(0);
369 modes = checked_calloc((num_modes + 1) * sizeof(SDL_Rect *));
371 for (i = 0; i < num_modes; i++)
373 SDL_DisplayMode mode;
375 if (SDL_GetDisplayMode(0, i, &mode) < 0)
378 modes[i] = checked_calloc(sizeof(SDL_Rect));
380 modes[i]->w = mode.w;
381 modes[i]->h = mode.h;
386 /* get available hardware supported fullscreen modes */
387 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
392 /* no hardware screen modes available => no fullscreen mode support */
393 // video.fullscreen_available = FALSE;
394 hardware_fullscreen_available = FALSE;
396 else if (modes == (SDL_Rect **)-1)
398 /* fullscreen resolution is not restricted -- all resolutions available */
399 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
401 /* use native video buffer size for fullscreen mode */
402 video.fullscreen_modes[0].width = video.width;
403 video.fullscreen_modes[0].height = video.height;
405 video.fullscreen_modes[1].width = -1;
406 video.fullscreen_modes[1].height = -1;
410 /* in this case, a certain number of screen modes is available */
413 for (i = 0; modes[i] != NULL; i++)
415 boolean found_mode = FALSE;
417 /* screen mode is smaller than video buffer size -- skip it */
418 if (modes[i]->w < video.width || modes[i]->h < video.height)
421 if (video.fullscreen_modes != NULL)
422 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
423 if (modes[i]->w == video.fullscreen_modes[j].width &&
424 modes[i]->h == video.fullscreen_modes[j].height)
427 if (found_mode) /* screen mode already stored -- skip it */
430 /* new mode found; add it to list of available fullscreen modes */
434 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
436 sizeof(struct ScreenModeInfo));
438 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
439 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
441 video.fullscreen_modes[num_modes].width = -1;
442 video.fullscreen_modes[num_modes].height = -1;
447 /* no appropriate screen modes available => no fullscreen mode support */
448 // video.fullscreen_available = FALSE;
449 hardware_fullscreen_available = FALSE;
453 video.fullscreen_available = hardware_fullscreen_available;
455 #if USE_DESKTOP_FULLSCREEN
456 // in SDL 2.0, there is always support for desktop fullscreen mode
457 // (in SDL 1.2, there is only support for "real" fullscreen mode)
458 video.fullscreen_available = TRUE;
461 #if defined(TARGET_SDL2)
464 for (i = 0; modes[i] != NULL; i++)
465 checked_free(modes[i]);
472 /* set window icon */
473 SDLSetWindowIcon(program.sdl_icon_filename);
476 /* open SDL video output device (window or fullscreen mode) */
477 if (!SDLSetVideoMode(backbuffer, fullscreen))
478 Error(ERR_EXIT, "setting video mode failed");
481 /* !!! SDL2 can only set the window icon if the window already exists !!! */
482 /* set window icon */
483 SDLSetWindowIcon(program.sdl_icon_filename);
486 /* set window and icon title */
487 #if defined(TARGET_SDL2)
488 SDL_SetWindowTitle(sdl_window, program.window_title);
490 SDL_WM_SetCaption(program.window_title, program.window_title);
493 /* SDL cannot directly draw to the visible video framebuffer like X11,
494 but always uses a backbuffer, which is then blitted to the visible
495 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
496 visible video framebuffer with 'SDL_Flip', if the hardware supports
497 this). Therefore do not use an additional backbuffer for drawing, but
498 use a symbolic buffer (distinguishable from the SDL backbuffer) called
499 'window', which indicates that the SDL backbuffer should be updated to
500 the visible video framebuffer when attempting to blit to it.
502 For convenience, it seems to be a good idea to create this symbolic
503 buffer 'window' at the same size as the SDL backbuffer. Although it
504 should never be drawn to directly, it would do no harm nevertheless. */
506 /* create additional (symbolic) buffer for double-buffering */
508 ReCreateBitmap(window, video.width, video.height, video.depth);
510 *window = CreateBitmap(video.width, video.height, video.depth);
514 static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
517 SDL_Surface *new_surface = NULL;
519 #if defined(TARGET_SDL2)
520 static boolean fullscreen_enabled = FALSE;
521 int surface_flags_window = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE;
522 #if USE_DESKTOP_FULLSCREEN
523 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
525 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
529 int surface_flags_window = SURFACE_FLAGS;
530 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
533 int width = (fullscreen ? fullscreen_width : video.width);
534 int height = (fullscreen ? fullscreen_height : video.height);
535 int surface_flags = (fullscreen ? surface_flags_fullscreen :
536 surface_flags_window);
538 // default window size is unscaled
539 video.window_width = video.width;
540 video.window_height = video.height;
542 #if defined(TARGET_SDL2)
544 // store if initial screen mode on game start is fullscreen mode
545 if (sdl_window == NULL)
548 printf("::: GAME STARTS WITH FULLSCREEN %d\n", fullscreen);
551 video.fullscreen_initial = fullscreen;
555 float window_scaling_factor = (float)setup.window_scaling_percent / 100;
556 #if !USE_DESKTOP_FULLSCREEN
557 float screen_scaling_factor = (fullscreen ? 1 : window_scaling_factor);
560 video.window_width = window_scaling_factor * width;
561 video.window_height = window_scaling_factor * height;
564 printf("::: use window scaling factor %f\n", screen_scaling_factor);
567 if ((*backbuffer)->surface)
569 SDL_FreeSurface((*backbuffer)->surface);
570 (*backbuffer)->surface = NULL;
575 SDL_DestroyTexture(sdl_texture);
579 if (!(fullscreen && fullscreen_enabled))
583 SDL_DestroyRenderer(sdl_renderer);
589 SDL_DestroyWindow(sdl_window);
595 Error(ERR_INFO, "::: checking 'sdl_window' ...");
597 if (sdl_window == NULL)
598 Error(ERR_INFO, "::: calling SDL_CreateWindow() [%d, %d, %d] ...",
599 setup.fullscreen, fullscreen, fullscreen_enabled);
602 if (sdl_window == NULL)
603 sdl_window = SDL_CreateWindow(program.window_title,
604 SDL_WINDOWPOS_CENTERED,
605 SDL_WINDOWPOS_CENTERED,
606 #if USE_DESKTOP_FULLSCREEN
610 (int)(screen_scaling_factor * width),
611 (int)(screen_scaling_factor * height),
615 if (sdl_window != NULL)
618 /* if SDL_CreateRenderer() is called from within a VirtualBox Windows VM
619 *without* enabling 2D/3D acceleration and/or guest additions installed,
620 it will crash if flags are *not* set to SDL_RENDERER_SOFTWARE (because
621 it will try to use accelerated graphics and apparently fails miserably) */
622 if (sdl_renderer == NULL)
623 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_SOFTWARE);
625 if (sdl_renderer == NULL)
626 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
629 if (sdl_renderer != NULL)
631 SDL_RenderSetLogicalSize(sdl_renderer, width, height);
632 // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
633 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality);
635 sdl_texture = SDL_CreateTexture(sdl_renderer,
636 SDL_PIXELFORMAT_ARGB8888,
637 SDL_TEXTUREACCESS_STREAMING,
640 if (sdl_texture != NULL)
643 // use SDL default values for RGB masks and no alpha channel
644 new_surface = SDL_CreateRGBSurface(0, width, height, 32, 0,0,0, 0);
648 // (do not use alpha channel)
649 new_surface = SDL_CreateRGBSurface(0, width, height, 32,
655 // (this uses an alpha channel, which we don't want here)
656 new_surface = SDL_CreateRGBSurface(0, width, height, 32,
665 if (new_surface == NULL)
666 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
671 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
676 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
681 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
687 SDL_DestroyWindow(sdl_window);
689 sdl_window = SDL_CreateWindow(program.window_title,
690 SDL_WINDOWPOS_CENTERED,
691 SDL_WINDOWPOS_CENTERED,
695 if (sdl_window != NULL)
696 new_surface = SDL_GetWindowSurface(sdl_window);
700 new_surface = SDL_SetVideoMode(width, height, video.depth, surface_flags);
703 #if defined(TARGET_SDL2)
704 // store fullscreen state ("video.fullscreen_enabled" may not reflect this!)
705 if (new_surface != NULL)
706 fullscreen_enabled = fullscreen;
712 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
714 boolean success = TRUE;
717 #if defined(TARGET_SDL2)
718 // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
719 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
720 int surface_flags_window = SURFACE_FLAGS;
722 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
723 int surface_flags_window = SURFACE_FLAGS;
726 SDL_Surface *new_surface = NULL;
730 if (*backbuffer == NULL)
731 *backbuffer = CreateBitmapStruct();
733 /* (real bitmap might be larger in fullscreen mode with video offsets) */
734 (*backbuffer)->width = video.width;
735 (*backbuffer)->height = video.height;
737 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
739 setFullscreenParameters(setup.fullscreen_mode);
741 video_xoffset = fullscreen_xoffset;
742 video_yoffset = fullscreen_yoffset;
744 /* switch display to fullscreen mode, if available */
746 new_surface = SDLCreateScreen(backbuffer, TRUE);
749 #if defined(TARGET_SDL2)
750 sdl_window = SDL_CreateWindow(program.window_title,
751 SDL_WINDOWPOS_CENTERED,
752 SDL_WINDOWPOS_CENTERED,
753 fullscreen_width, fullscreen_height,
754 surface_flags_fullscreen);
755 if (sdl_window != NULL)
757 new_surface = SDL_GetWindowSurface(sdl_window);
759 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
760 // UpdateScreen(NULL); // immediately map window
763 new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
764 video.depth, surface_flags_fullscreen);
768 if (new_surface == NULL)
770 /* switching display to fullscreen mode failed */
771 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
773 /* do not try it again */
774 video.fullscreen_available = FALSE;
780 (*backbuffer)->surface = new_surface;
782 video.fullscreen_enabled = TRUE;
783 video.fullscreen_mode_current = setup.fullscreen_mode;
789 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
794 /* switch display to window mode */
796 new_surface = SDLCreateScreen(backbuffer, FALSE);
799 #if defined(TARGET_SDL2)
802 float screen_scaling_factor = 1.2;
803 int test_fullscreen = 0;
804 int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
805 surface_flags_window);
807 if ((*backbuffer)->surface)
808 SDL_FreeSurface((*backbuffer)->surface);
811 SDL_DestroyTexture(sdl_texture);
814 SDL_DestroyRenderer(sdl_renderer);
817 SDL_DestroyWindow(sdl_window);
819 sdl_window = SDL_CreateWindow(program.window_title,
820 SDL_WINDOWPOS_CENTERED,
821 SDL_WINDOWPOS_CENTERED,
822 (int)(screen_scaling_factor * video.width),
823 (int)(screen_scaling_factor * video.height),
826 if (sdl_window != NULL)
828 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
830 if (sdl_renderer != NULL)
832 SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height);
833 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
835 sdl_texture = SDL_CreateTexture(sdl_renderer,
836 SDL_PIXELFORMAT_ARGB8888,
837 SDL_TEXTUREACCESS_STREAMING,
838 video.width, video.height);
840 if (sdl_texture != NULL)
843 // (do not use alpha channel)
844 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
850 // (this uses an alpha channel, which we don't want here)
851 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
858 if (new_surface == NULL)
859 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
864 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
869 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
874 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
880 SDL_DestroyWindow(sdl_window);
882 sdl_window = SDL_CreateWindow(program.window_title,
883 SDL_WINDOWPOS_CENTERED,
884 SDL_WINDOWPOS_CENTERED,
885 video.width, video.height,
886 surface_flags_window);
888 if (sdl_window != NULL)
890 new_surface = SDL_GetWindowSurface(sdl_window);
892 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
893 // UpdateScreen(NULL); // immediately map window
898 new_surface = SDL_SetVideoMode(video.width, video.height,
899 video.depth, surface_flags_window);
903 if (new_surface == NULL)
905 /* switching display to window mode failed -- should not happen */
906 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
912 (*backbuffer)->surface = new_surface;
914 video.fullscreen_enabled = FALSE;
915 video.window_scaling_percent = setup.window_scaling_percent;
916 video.window_scaling_quality = setup.window_scaling_quality;
922 #if defined(TARGET_SDL2)
923 SDLRedrawWindow(); // map window
924 // UpdateScreen(NULL); // map window
928 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
930 #if defined(PLATFORM_WIN32)
932 SDL_SysWMinfo wminfo;
934 boolean wminfo_success = FALSE;
936 SDL_VERSION(&wminfo.version);
937 #if defined(TARGET_SDL2)
939 wminfo_success = SDL_GetWindowWMInfo(sdl_window, &wminfo);
941 wminfo_success = (SDL_GetWMInfo(&wminfo) == 1);
946 #if defined(TARGET_SDL2)
947 hwnd = wminfo.info.win.window;
949 hwnd = wminfo.window;
952 DragAcceptFiles(hwnd, TRUE);
961 void SDLSetWindowTitle()
963 #if defined(TARGET_SDL2)
964 SDL_SetWindowTitle(sdl_window, program.window_title);
966 SDL_WM_SetCaption(program.window_title, program.window_title);
970 #if defined(TARGET_SDL2)
971 void SDLSetWindowScaling(int window_scaling_percent)
973 if (sdl_window == NULL)
976 float window_scaling_factor = (float)window_scaling_percent / 100;
977 int new_window_width = (int)(window_scaling_factor * video.width);
978 int new_window_height = (int)(window_scaling_factor * video.height);
981 Error(ERR_DEBUG, "::: SDLSetWindowScaling(%d) ...", window_scaling_percent);
984 SDL_SetWindowSize(sdl_window, new_window_width, new_window_height);
986 video.window_scaling_percent = window_scaling_percent;
987 video.window_width = new_window_width;
988 video.window_height = new_window_height;
993 void SDLSetWindowScalingQuality(char *window_scaling_quality)
995 if (sdl_texture == NULL)
998 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, window_scaling_quality);
1000 SDL_Texture *new_texture = SDL_CreateTexture(sdl_renderer,
1001 SDL_PIXELFORMAT_ARGB8888,
1002 SDL_TEXTUREACCESS_STREAMING,
1003 video.width, video.height);
1005 if (new_texture != NULL)
1007 SDL_DestroyTexture(sdl_texture);
1009 sdl_texture = new_texture;
1014 video.window_scaling_quality = window_scaling_quality;
1017 void SDLSetWindowFullscreen(boolean fullscreen)
1019 if (sdl_window == NULL)
1022 #if USE_DESKTOP_FULLSCREEN
1023 int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
1025 int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
1029 Error(ERR_DEBUG, "::: SDL_SetWindowFullscreen(%d) ...", fullscreen);
1032 if (SDL_SetWindowFullscreen(sdl_window, flags) == 0)
1033 video.fullscreen_enabled = fullscreen;
1036 printf("::: SDLSetWindowFullscreen: %d, %d\n",
1037 fullscreen, video.fullscreen_initial);
1041 // if game started in fullscreen mode, window will also get fullscreen size
1042 if (!fullscreen && video.fullscreen_initial)
1044 SDLSetWindowScaling(setup.window_scaling_percent);
1045 SDL_SetWindowPosition(sdl_window,
1046 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
1048 video.fullscreen_initial = FALSE;
1053 void SDLRedrawWindow()
1059 void SDLCreateBitmapContent(Bitmap *bitmap, int width, int height,
1063 SDL_Surface *surface =
1064 SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth, 0,0,0, 0);
1066 if (surface == NULL)
1067 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1069 SDLSetNativeSurface(&surface);
1071 bitmap->surface = surface;
1075 SDL_Surface *surface_tmp, *surface_native;
1077 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
1080 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1082 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
1083 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
1085 SDL_FreeSurface(surface_tmp);
1087 new_bitmap->surface = surface_native;
1091 void SDLFreeBitmapPointers(Bitmap *bitmap)
1093 if (bitmap->surface)
1094 SDL_FreeSurface(bitmap->surface);
1095 if (bitmap->surface_masked)
1096 SDL_FreeSurface(bitmap->surface_masked);
1097 bitmap->surface = NULL;
1098 bitmap->surface_masked = NULL;
1101 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1102 int src_x, int src_y, int width, int height,
1103 int dst_x, int dst_y, int mask_mode)
1105 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
1106 SDL_Rect src_rect, dst_rect;
1108 if (src_bitmap == backbuffer)
1110 src_x += video_xoffset;
1111 src_y += video_yoffset;
1117 src_rect.h = height;
1119 if (dst_bitmap == backbuffer || dst_bitmap == window)
1121 dst_x += video_xoffset;
1122 dst_y += video_yoffset;
1128 dst_rect.h = height;
1130 // if (src_bitmap != backbuffer || dst_bitmap != window)
1131 if (!(src_bitmap == backbuffer && dst_bitmap == window))
1132 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
1133 src_bitmap->surface_masked : src_bitmap->surface),
1134 &src_rect, real_dst_bitmap->surface, &dst_rect);
1136 #if defined(TARGET_SDL2)
1137 if (dst_bitmap == window)
1139 // SDL_UpdateWindowSurface(sdl_window);
1140 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
1141 UpdateScreen(&dst_rect);
1144 if (dst_bitmap == window)
1146 // SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
1147 UpdateScreen(&dst_rect);
1152 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
1155 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
1158 if (dst_bitmap == backbuffer || dst_bitmap == window)
1169 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
1171 #if defined(TARGET_SDL2)
1172 if (dst_bitmap == window)
1174 // SDL_UpdateWindowSurface(sdl_window);
1175 // SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
1176 UpdateScreen(&rect);
1179 if (dst_bitmap == window)
1181 // SDL_UpdateRect(backbuffer->surface, x, y, width, height);
1182 UpdateScreen(&rect);
1187 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
1188 int fade_mode, int fade_delay, int post_delay,
1189 void (*draw_border_function)(void))
1191 static boolean initialization_needed = TRUE;
1192 static SDL_Surface *surface_source = NULL;
1193 static SDL_Surface *surface_target = NULL;
1194 static SDL_Surface *surface_black = NULL;
1195 SDL_Surface *surface_screen = backbuffer->surface;
1196 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
1197 SDL_Rect src_rect, dst_rect;
1199 int src_x = x, src_y = y;
1200 int dst_x = x, dst_y = y;
1201 unsigned int time_last, time_current;
1203 /* check if screen size has changed */
1204 if (surface_source != NULL && (video.width != surface_source->w ||
1205 video.height != surface_source->h))
1207 SDL_FreeSurface(surface_source);
1208 SDL_FreeSurface(surface_target);
1209 SDL_FreeSurface(surface_black);
1211 initialization_needed = TRUE;
1217 src_rect.h = height;
1219 dst_x += video_xoffset;
1220 dst_y += video_yoffset;
1224 dst_rect.w = width; /* (ignored) */
1225 dst_rect.h = height; /* (ignored) */
1227 dst_rect2 = dst_rect;
1229 if (initialization_needed)
1231 #if defined(TARGET_SDL2)
1232 unsigned int flags = 0;
1234 unsigned int flags = SDL_SRCALPHA;
1236 /* use same surface type as screen surface */
1237 if ((surface_screen->flags & SDL_HWSURFACE))
1238 flags |= SDL_HWSURFACE;
1240 flags |= SDL_SWSURFACE;
1243 /* create surface for temporary copy of screen buffer (source) */
1244 if ((surface_source =
1245 SDL_CreateRGBSurface(flags,
1248 surface_screen->format->BitsPerPixel,
1249 surface_screen->format->Rmask,
1250 surface_screen->format->Gmask,
1251 surface_screen->format->Bmask,
1252 surface_screen->format->Amask)) == NULL)
1253 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1255 /* create surface for cross-fading screen buffer (target) */
1256 if ((surface_target =
1257 SDL_CreateRGBSurface(flags,
1260 surface_screen->format->BitsPerPixel,
1261 surface_screen->format->Rmask,
1262 surface_screen->format->Gmask,
1263 surface_screen->format->Bmask,
1264 surface_screen->format->Amask)) == NULL)
1265 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1267 /* create black surface for fading from/to black */
1268 if ((surface_black =
1269 SDL_CreateRGBSurface(flags,
1272 surface_screen->format->BitsPerPixel,
1273 surface_screen->format->Rmask,
1274 surface_screen->format->Gmask,
1275 surface_screen->format->Bmask,
1276 surface_screen->format->Amask)) == NULL)
1277 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
1279 /* completely fill the surface with black color pixels */
1280 SDL_FillRect(surface_black, NULL,
1281 SDL_MapRGB(surface_screen->format, 0, 0, 0));
1283 initialization_needed = FALSE;
1286 /* copy source and target surfaces to temporary surfaces for fading */
1287 if (fade_mode & FADE_TYPE_TRANSFORM)
1289 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
1290 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
1292 else if (fade_mode & FADE_TYPE_FADE_IN)
1294 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
1295 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
1297 else /* FADE_TYPE_FADE_OUT */
1299 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
1300 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
1303 time_current = SDL_GetTicks();
1305 if (fade_mode == FADE_MODE_MELT)
1307 boolean done = FALSE;
1308 int melt_pixels = 2;
1309 int melt_columns = width / melt_pixels;
1310 int ypos[melt_columns];
1311 int max_steps = height / 8 + 32;
1316 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
1317 #if defined(TARGET_SDL2)
1318 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
1320 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
1323 ypos[0] = -GetSimpleRandom(16);
1325 for (i = 1 ; i < melt_columns; i++)
1327 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
1329 ypos[i] = ypos[i - 1] + r;
1342 time_last = time_current;
1343 time_current = SDL_GetTicks();
1344 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
1345 steps_final = MIN(MAX(0, steps), max_steps);
1349 done = (steps_done >= steps_final);
1351 for (i = 0 ; i < melt_columns; i++)
1359 else if (ypos[i] < height)
1364 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
1366 if (ypos[i] + dy >= height)
1367 dy = height - ypos[i];
1369 /* copy part of (appearing) target surface to upper area */
1370 src_rect.x = src_x + i * melt_pixels;
1371 // src_rect.y = src_y + ypos[i];
1373 src_rect.w = melt_pixels;
1375 src_rect.h = ypos[i] + dy;
1377 dst_rect.x = dst_x + i * melt_pixels;
1378 // dst_rect.y = dst_y + ypos[i];
1381 if (steps_done >= steps_final)
1382 SDL_BlitSurface(surface_target, &src_rect,
1383 surface_screen, &dst_rect);
1387 /* copy part of (disappearing) source surface to lower area */
1388 src_rect.x = src_x + i * melt_pixels;
1390 src_rect.w = melt_pixels;
1391 src_rect.h = height - ypos[i];
1393 dst_rect.x = dst_x + i * melt_pixels;
1394 dst_rect.y = dst_y + ypos[i];
1396 if (steps_done >= steps_final)
1397 SDL_BlitSurface(surface_source, &src_rect,
1398 surface_screen, &dst_rect);
1404 src_rect.x = src_x + i * melt_pixels;
1406 src_rect.w = melt_pixels;
1407 src_rect.h = height;
1409 dst_rect.x = dst_x + i * melt_pixels;
1412 if (steps_done >= steps_final)
1413 SDL_BlitSurface(surface_target, &src_rect,
1414 surface_screen, &dst_rect);
1418 if (steps_done >= steps_final)
1420 if (draw_border_function != NULL)
1421 draw_border_function();
1423 #if defined(TARGET_SDL2)
1424 // SDL_UpdateWindowSurface(sdl_window);
1425 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
1426 UpdateScreen(&dst_rect2);
1428 // SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
1429 UpdateScreen(&dst_rect2);
1439 for (alpha = 0.0; alpha < 255.0;)
1441 time_last = time_current;
1442 time_current = SDL_GetTicks();
1443 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
1444 alpha_final = MIN(MAX(0, alpha), 255);
1446 /* draw existing (source) image to screen buffer */
1447 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
1449 /* draw new (target) image to screen buffer using alpha blending */
1450 #if defined(TARGET_SDL2)
1451 SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
1452 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
1454 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
1456 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
1458 if (draw_border_function != NULL)
1459 draw_border_function();
1462 /* only update the region of the screen that is affected from fading */
1463 #if defined(TARGET_SDL2)
1464 // SDL_UpdateWindowSurface(sdl_window);
1465 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
1466 UpdateScreen(&dst_rect);
1468 // SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
1469 UpdateScreen(&dst_rect);
1472 SDL_Flip(surface_screen);
1480 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
1481 int to_x, int to_y, Uint32 color)
1483 SDL_Surface *surface = dst_bitmap->surface;
1487 swap_numbers(&from_x, &to_x);
1490 swap_numbers(&from_y, &to_y);
1494 rect.w = (to_x - from_x + 1);
1495 rect.h = (to_y - from_y + 1);
1497 if (dst_bitmap == backbuffer || dst_bitmap == window)
1499 rect.x += video_xoffset;
1500 rect.y += video_yoffset;
1503 SDL_FillRect(surface, &rect, color);
1506 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
1507 int to_x, int to_y, Uint32 color)
1509 if (dst_bitmap == backbuffer || dst_bitmap == window)
1511 from_x += video_xoffset;
1512 from_y += video_yoffset;
1513 to_x += video_xoffset;
1514 to_y += video_yoffset;
1517 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
1521 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
1522 int num_points, Uint32 color)
1527 for (i = 0; i < num_points - 1; i++)
1529 for (x = 0; x < line_width; x++)
1531 for (y = 0; y < line_width; y++)
1533 int dx = x - line_width / 2;
1534 int dy = y - line_width / 2;
1536 if ((x == 0 && y == 0) ||
1537 (x == 0 && y == line_width - 1) ||
1538 (x == line_width - 1 && y == 0) ||
1539 (x == line_width - 1 && y == line_width - 1))
1542 sge_Line(surface, points[i].x + dx, points[i].y + dy,
1543 points[i+1].x + dx, points[i+1].y + dy, color);
1550 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
1552 SDL_Surface *surface = src_bitmap->surface;
1554 if (src_bitmap == backbuffer || src_bitmap == window)
1560 switch (surface->format->BytesPerPixel)
1562 case 1: /* assuming 8-bpp */
1564 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
1568 case 2: /* probably 15-bpp or 16-bpp */
1570 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
1574 case 3: /* slow 24-bpp mode; usually not used */
1576 /* does this work? */
1577 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
1581 shift = surface->format->Rshift;
1582 color |= *(pix + shift / 8) >> shift;
1583 shift = surface->format->Gshift;
1584 color |= *(pix + shift / 8) >> shift;
1585 shift = surface->format->Bshift;
1586 color |= *(pix + shift / 8) >> shift;
1592 case 4: /* probably 32-bpp */
1594 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
1603 /* ========================================================================= */
1604 /* The following functions were taken from the SGE library */
1605 /* (SDL Graphics Extension Library) by Anders Lindström */
1606 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
1607 /* ========================================================================= */
1609 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1611 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
1613 switch (surface->format->BytesPerPixel)
1617 /* Assuming 8-bpp */
1618 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1624 /* Probably 15-bpp or 16-bpp */
1625 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1631 /* Slow 24-bpp mode, usually not used */
1635 /* Gack - slow, but endian correct */
1636 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1637 shift = surface->format->Rshift;
1638 *(pix+shift/8) = color>>shift;
1639 shift = surface->format->Gshift;
1640 *(pix+shift/8) = color>>shift;
1641 shift = surface->format->Bshift;
1642 *(pix+shift/8) = color>>shift;
1648 /* Probably 32-bpp */
1649 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1656 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1657 Uint8 R, Uint8 G, Uint8 B)
1659 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
1662 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1664 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1667 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1669 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1672 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1677 /* Gack - slow, but endian correct */
1678 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1679 shift = surface->format->Rshift;
1680 *(pix+shift/8) = color>>shift;
1681 shift = surface->format->Gshift;
1682 *(pix+shift/8) = color>>shift;
1683 shift = surface->format->Bshift;
1684 *(pix+shift/8) = color>>shift;
1687 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1689 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1692 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
1694 switch (dest->format->BytesPerPixel)
1697 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
1701 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
1705 _PutPixel24(dest,x,y,color);
1709 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
1714 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1716 if (SDL_MUSTLOCK(surface))
1718 if (SDL_LockSurface(surface) < 0)
1724 _PutPixel(surface, x, y, color);
1726 if (SDL_MUSTLOCK(surface))
1728 SDL_UnlockSurface(surface);
1732 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1733 Uint8 r, Uint8 g, Uint8 b)
1735 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
1738 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
1740 if (y >= 0 && y <= dest->h - 1)
1742 switch (dest->format->BytesPerPixel)
1745 return y*dest->pitch;
1749 return y*dest->pitch/2;
1753 return y*dest->pitch;
1757 return y*dest->pitch/4;
1765 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
1767 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
1769 switch (surface->format->BytesPerPixel)
1773 /* Assuming 8-bpp */
1774 *((Uint8 *)surface->pixels + ypitch + x) = color;
1780 /* Probably 15-bpp or 16-bpp */
1781 *((Uint16 *)surface->pixels + ypitch + x) = color;
1787 /* Slow 24-bpp mode, usually not used */
1791 /* Gack - slow, but endian correct */
1792 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1793 shift = surface->format->Rshift;
1794 *(pix+shift/8) = color>>shift;
1795 shift = surface->format->Gshift;
1796 *(pix+shift/8) = color>>shift;
1797 shift = surface->format->Bshift;
1798 *(pix+shift/8) = color>>shift;
1804 /* Probably 32-bpp */
1805 *((Uint32 *)surface->pixels + ypitch + x) = color;
1812 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1817 if (SDL_MUSTLOCK(Surface))
1819 if (SDL_LockSurface(Surface) < 0)
1832 /* Do the clipping */
1833 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1837 if (x2 > Surface->w - 1)
1838 x2 = Surface->w - 1;
1845 SDL_FillRect(Surface, &l, Color);
1847 if (SDL_MUSTLOCK(Surface))
1849 SDL_UnlockSurface(Surface);
1853 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1854 Uint8 R, Uint8 G, Uint8 B)
1856 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1859 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1870 /* Do the clipping */
1871 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1875 if (x2 > Surface->w - 1)
1876 x2 = Surface->w - 1;
1883 SDL_FillRect(Surface, &l, Color);
1886 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1891 if (SDL_MUSTLOCK(Surface))
1893 if (SDL_LockSurface(Surface) < 0)
1906 /* Do the clipping */
1907 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1911 if (y2 > Surface->h - 1)
1912 y2 = Surface->h - 1;
1919 SDL_FillRect(Surface, &l, Color);
1921 if (SDL_MUSTLOCK(Surface))
1923 SDL_UnlockSurface(Surface);
1927 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1928 Uint8 R, Uint8 G, Uint8 B)
1930 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1933 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1944 /* Do the clipping */
1945 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1949 if (y2 > Surface->h - 1)
1950 y2 = Surface->h - 1;
1957 SDL_FillRect(Surface, &l, Color);
1960 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1961 Sint16 x2, Sint16 y2, Uint32 Color,
1962 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1965 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1970 sdx = (dx < 0) ? -1 : 1;
1971 sdy = (dy < 0) ? -1 : 1;
1983 for (x = 0; x < dx; x++)
1985 Callback(Surface, px, py, Color);
1999 for (y = 0; y < dy; y++)
2001 Callback(Surface, px, py, Color);
2015 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
2016 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
2017 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
2020 sge_DoLine(Surface, X1, Y1, X2, Y2,
2021 SDL_MapRGB(Surface->format, R, G, B), Callback);
2024 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
2027 if (SDL_MUSTLOCK(Surface))
2029 if (SDL_LockSurface(Surface) < 0)
2034 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
2036 /* unlock the display */
2037 if (SDL_MUSTLOCK(Surface))
2039 SDL_UnlockSurface(Surface);
2043 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
2044 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
2046 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
2049 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
2051 if (dst_bitmap == backbuffer || dst_bitmap == window)
2057 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
2062 -----------------------------------------------------------------------------
2063 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
2064 -----------------------------------------------------------------------------
2067 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
2068 int width, int height, Uint32 color)
2072 for (y = src_y; y < src_y + height; y++)
2074 for (x = src_x; x < src_x + width; x++)
2076 Uint32 pixel = SDLGetPixel(bitmap, x, y);
2078 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
2083 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
2084 int src_x, int src_y, int width, int height,
2085 int dst_x, int dst_y)
2089 for (y = 0; y < height; y++)
2091 for (x = 0; x < width; x++)
2093 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
2095 if (pixel != BLACK_PIXEL)
2096 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
2102 /* ========================================================================= */
2103 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
2104 /* (Rotozoomer) by Andreas Schiffler */
2105 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
2106 /* ========================================================================= */
2109 -----------------------------------------------------------------------------
2112 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
2113 -----------------------------------------------------------------------------
2124 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
2127 tColorRGBA *sp, *csp, *dp;
2134 sp = csp = (tColorRGBA *) src->pixels;
2135 dp = (tColorRGBA *) dst->pixels;
2137 sgap = src->pitch - src->w * 4;
2139 dgap = dst->pitch - dst->w * 4;
2141 for (y = 0; y < dst->h; y++)
2145 for (x = 0; x < dst->w; x++)
2147 tColorRGBA *sp0 = sp;
2148 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
2149 tColorRGBA *sp00 = &sp0[0];
2150 tColorRGBA *sp01 = &sp0[1];
2151 tColorRGBA *sp10 = &sp1[0];
2152 tColorRGBA *sp11 = &sp1[1];
2155 /* create new color pixel from all four source color pixels */
2156 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
2157 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
2158 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
2159 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
2164 /* advance source pointers */
2167 /* advance destination pointer */
2171 /* advance source pointer */
2172 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
2174 /* advance destination pointers */
2175 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
2183 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
2185 int x, y, *sax, *say, *csax, *csay;
2187 tColorRGBA *sp, *csp, *csp0, *dp;
2190 /* use specialized zoom function when scaling down to exactly half size */
2191 if (src->w == 2 * dst->w &&
2192 src->h == 2 * dst->h)
2193 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
2196 printf("::: zoomSurfaceRGBA: %d, %d -> %d, %d\n",
2197 src->w, src->h, dst->w, dst->h);
2200 /* variable setup */
2201 sx = (float) src->w / (float) dst->w;
2202 sy = (float) src->h / (float) dst->h;
2204 /* allocate memory for row increments */
2205 csax = sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
2206 csay = say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
2208 /* precalculate row increments */
2209 for (x = 0; x <= dst->w; x++)
2210 *csax++ = (int)(sx * x);
2212 for (y = 0; y <= dst->h; y++)
2213 *csay++ = (int)(sy * y);
2216 sp = csp = csp0 = (tColorRGBA *) src->pixels;
2217 dp = (tColorRGBA *) dst->pixels;
2218 dgap = dst->pitch - dst->w * 4;
2221 for (y = 0; y < dst->h; y++)
2226 for (x = 0; x < dst->w; x++)
2231 /* advance source pointers */
2235 /* advance destination pointer */
2239 /* advance source pointer */
2241 csp = (tColorRGBA *) ((Uint8 *) csp0 + *csay * src->pitch);
2243 /* advance destination pointers */
2244 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
2255 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
2257 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
2258 tColorRGBA *sp, *csp, *dp;
2264 /* use specialized zoom function when scaling down to exactly half size */
2265 if (src->w == 2 * dst->w &&
2266 src->h == 2 * dst->h)
2267 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
2269 /* variable setup */
2270 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
2271 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
2273 /* allocate memory for row increments */
2274 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
2275 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
2277 /* precalculate row increments */
2280 for (x = 0; x <= dst->w; x++)
2290 for (y = 0; y <= dst->h; y++)
2299 sp = csp = (tColorRGBA *) src->pixels;
2300 dp = (tColorRGBA *) dst->pixels;
2302 sgap = src->pitch - src->w * 4;
2304 dgap = dst->pitch - dst->w * 4;
2307 for (y = 0; y < dst->h; y++)
2312 for (x = 0; x < dst->w; x++)
2317 /* advance source pointers */
2319 sp += (*csax >> 16);
2321 /* advance destination pointer */
2325 /* advance source pointer */
2327 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
2329 /* advance destination pointers */
2330 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
2342 -----------------------------------------------------------------------------
2345 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
2346 -----------------------------------------------------------------------------
2349 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
2351 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
2352 Uint8 *sp, *dp, *csp;
2355 /* variable setup */
2356 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
2357 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
2359 /* allocate memory for row increments */
2360 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
2361 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
2363 /* precalculate row increments */
2366 for (x = 0; x < dst->w; x++)
2369 *csax = (csx >> 16);
2376 for (y = 0; y < dst->h; y++)
2379 *csay = (csy >> 16);
2386 for (x = 0; x < dst->w; x++)
2394 for (y = 0; y < dst->h; y++)
2401 sp = csp = (Uint8 *) src->pixels;
2402 dp = (Uint8 *) dst->pixels;
2403 dgap = dst->pitch - dst->w;
2407 for (y = 0; y < dst->h; y++)
2411 for (x = 0; x < dst->w; x++)
2416 /* advance source pointers */
2420 /* advance destination pointer */
2424 /* advance source pointer (for row) */
2425 csp += ((*csay) * src->pitch);
2428 /* advance destination pointers */
2439 -----------------------------------------------------------------------------
2442 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
2443 'zoomx' and 'zoomy' are scaling factors for width and height.
2444 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
2445 into a 32bit RGBA format on the fly.
2446 -----------------------------------------------------------------------------
2449 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
2451 SDL_Surface *zoom_src = NULL;
2452 SDL_Surface *zoom_dst = NULL;
2453 boolean is_converted = FALSE;
2460 /* determine if source surface is 32 bit or 8 bit */
2461 is_32bit = (src->format->BitsPerPixel == 32);
2463 if (is_32bit || src->format->BitsPerPixel == 8)
2465 /* use source surface 'as is' */
2470 /* new source surface is 32 bit with a defined RGB ordering */
2471 zoom_src = SDL_CreateRGBSurface(SURFACE_FLAGS, src->w, src->h, 32,
2472 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
2473 SDL_BlitSurface(src, NULL, zoom_src, NULL);
2475 is_converted = TRUE;
2478 /* allocate surface to completely contain the zoomed surface */
2481 /* target surface is 32 bit with source RGBA/ABGR ordering */
2482 zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 32,
2483 zoom_src->format->Rmask,
2484 zoom_src->format->Gmask,
2485 zoom_src->format->Bmask, 0);
2489 /* target surface is 8 bit */
2490 zoom_dst = SDL_CreateRGBSurface(SURFACE_FLAGS, dst_width, dst_height, 8,
2494 /* lock source surface */
2495 SDL_LockSurface(zoom_src);
2497 /* check which kind of surface we have */
2500 /* call the 32 bit transformation routine to do the zooming */
2501 zoomSurfaceRGBA(zoom_src, zoom_dst);
2506 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
2507 zoom_dst->format->palette->colors[i] =
2508 zoom_src->format->palette->colors[i];
2509 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
2511 /* call the 8 bit transformation routine to do the zooming */
2512 zoomSurfaceY(zoom_src, zoom_dst);
2515 /* unlock source surface */
2516 SDL_UnlockSurface(zoom_src);
2518 /* free temporary surface */
2520 SDL_FreeSurface(zoom_src);
2522 /* return destination surface */
2528 Bitmap *SDLZoomBitmap(Bitmap *src_bitmap, int dst_width, int dst_height)
2532 Bitmap *dst_bitmap = CreateBitmapStruct();
2533 SDL_Surface **dst_surface = &dst_bitmap->surface;
2535 dst_width = MAX(1, dst_width); /* prevent zero bitmap width */
2536 dst_height = MAX(1, dst_height); /* prevent zero bitmap height */
2538 dst_bitmap->width = dst_width;
2539 dst_bitmap->height = dst_height;
2541 /* create zoomed temporary surface from source surface */
2542 *dst_surface = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2544 /* create native format destination surface from zoomed temporary surface */
2545 SDLSetNativeSurface(dst_surface);
2551 Bitmap *dst_bitmap = CreateBitmapStruct();
2552 SDL_Surface *sdl_surface_tmp;
2554 dst_width = MAX(1, dst_width); /* prevent zero bitmap width */
2555 dst_height = MAX(1, dst_height); /* prevent zero bitmap height */
2557 dst_bitmap->width = dst_width;
2558 dst_bitmap->height = dst_height;
2560 print_timestamp_init("SDLZoomBitmap");
2562 /* create zoomed temporary surface from source surface */
2563 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2564 print_timestamp_time("zoomSurface");
2566 /* create native format destination surface from zoomed temporary surface */
2567 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
2568 print_timestamp_time("SDL_DisplayFormat");
2570 /* free temporary surface */
2571 SDL_FreeSurface(sdl_surface_tmp);
2572 print_timestamp_time("SDL_FreeSurface");
2574 print_timestamp_done("SDLZoomBitmap");
2583 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
2585 SDL_Surface *sdl_surface_tmp;
2586 int dst_width = dst_bitmap->width;
2587 int dst_height = dst_bitmap->height;
2589 print_timestamp_init("SDLZoomBitmap");
2591 /* throw away old destination surface */
2592 SDL_FreeSurface(dst_bitmap->surface);
2593 print_timestamp_time("SDL_FreeSurface");
2595 /* create zoomed temporary surface from source surface */
2596 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2597 print_timestamp_time("zoomSurface");
2599 /* create native format destination surface from zoomed temporary surface */
2600 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
2601 print_timestamp_time("SDL_DisplayFormat");
2603 /* free temporary surface */
2604 SDL_FreeSurface(sdl_surface_tmp);
2605 print_timestamp_time("SDL_FreeSurface");
2607 print_timestamp_done("SDLZoomBitmap");
2613 /* ========================================================================= */
2614 /* load image to bitmap */
2615 /* ========================================================================= */
2617 Bitmap *SDLLoadImage(char *filename)
2619 Bitmap *new_bitmap = CreateBitmapStruct();
2620 SDL_Surface *sdl_image_tmp;
2622 print_timestamp_init("SDLLoadImage");
2624 print_timestamp_time(getBaseNamePtr(filename));
2626 /* load image to temporary surface */
2627 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
2629 SetError("IMG_Load(): %s", SDL_GetError());
2634 print_timestamp_time("IMG_Load");
2636 UPDATE_BUSY_STATE();
2638 /* create native non-transparent surface for current image */
2640 if ((new_bitmap->surface = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
2642 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2647 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
2649 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2655 print_timestamp_time("SDL_DisplayFormat (opaque)");
2657 UPDATE_BUSY_STATE();
2659 /* create native transparent surface for current image */
2660 SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
2661 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
2663 if ((new_bitmap->surface_masked = SDLGetNativeSurface(sdl_image_tmp)) == NULL)
2665 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2670 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
2672 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2678 print_timestamp_time("SDL_DisplayFormat (masked)");
2680 UPDATE_BUSY_STATE();
2682 /* free temporary surface */
2683 SDL_FreeSurface(sdl_image_tmp);
2685 new_bitmap->width = new_bitmap->surface->w;
2686 new_bitmap->height = new_bitmap->surface->h;
2688 print_timestamp_done("SDLLoadImage");
2694 /* ------------------------------------------------------------------------- */
2695 /* custom cursor fuctions */
2696 /* ------------------------------------------------------------------------- */
2698 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
2700 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
2701 cursor_info->width, cursor_info->height,
2702 cursor_info->hot_x, cursor_info->hot_y);
2705 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
2707 static struct MouseCursorInfo *last_cursor_info = NULL;
2708 static struct MouseCursorInfo *last_cursor_info2 = NULL;
2709 static SDL_Cursor *cursor_default = NULL;
2710 static SDL_Cursor *cursor_current = NULL;
2712 /* if invoked for the first time, store the SDL default cursor */
2713 if (cursor_default == NULL)
2714 cursor_default = SDL_GetCursor();
2716 /* only create new cursor if cursor info (custom only) has changed */
2717 if (cursor_info != NULL && cursor_info != last_cursor_info)
2719 cursor_current = create_cursor(cursor_info);
2720 last_cursor_info = cursor_info;
2723 /* only set new cursor if cursor info (custom or NULL) has changed */
2724 if (cursor_info != last_cursor_info2)
2725 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
2727 last_cursor_info2 = cursor_info;
2731 /* ========================================================================= */
2732 /* audio functions */
2733 /* ========================================================================= */
2735 void SDLOpenAudio(void)
2737 #if !defined(TARGET_SDL2)
2738 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
2739 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
2742 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
2744 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
2748 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
2749 AUDIO_NUM_CHANNELS_STEREO,
2750 setup.system.audio_fragment_size) < 0)
2752 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
2756 audio.sound_available = TRUE;
2757 audio.music_available = TRUE;
2758 audio.loops_available = TRUE;
2759 audio.sound_enabled = TRUE;
2761 /* set number of available mixer channels */
2762 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
2763 audio.music_channel = MUSIC_CHANNEL;
2764 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
2766 Mixer_InitChannels();
2769 void SDLCloseAudio(void)
2772 Mix_HaltChannel(-1);
2775 SDL_QuitSubSystem(SDL_INIT_AUDIO);
2779 /* ========================================================================= */
2780 /* event functions */
2781 /* ========================================================================= */
2783 void SDLNextEvent(Event *event)
2785 SDL_WaitEvent(event);
2787 if (event->type == EVENT_BUTTONPRESS ||
2788 event->type == EVENT_BUTTONRELEASE)
2790 if (((ButtonEvent *)event)->x > video_xoffset)
2791 ((ButtonEvent *)event)->x -= video_xoffset;
2793 ((ButtonEvent *)event)->x = 0;
2794 if (((ButtonEvent *)event)->y > video_yoffset)
2795 ((ButtonEvent *)event)->y -= video_yoffset;
2797 ((ButtonEvent *)event)->y = 0;
2799 else if (event->type == EVENT_MOTIONNOTIFY)
2801 if (((MotionEvent *)event)->x > video_xoffset)
2802 ((MotionEvent *)event)->x -= video_xoffset;
2804 ((MotionEvent *)event)->x = 0;
2805 if (((MotionEvent *)event)->y > video_yoffset)
2806 ((MotionEvent *)event)->y -= video_yoffset;
2808 ((MotionEvent *)event)->y = 0;
2812 void SDLHandleWindowManagerEvent(Event *event)
2814 #if defined(PLATFORM_WIN32)
2815 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
2816 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
2818 #if defined(TARGET_SDL2)
2819 if (syswmmsg->msg.win.msg == WM_DROPFILES)
2821 if (syswmmsg->msg == WM_DROPFILES)
2824 #if defined(TARGET_SDL2)
2825 HDROP hdrop = (HDROP)syswmmsg->msg.win.wParam;
2827 HDROP hdrop = (HDROP)syswmmsg->wParam;
2831 printf("::: SDL_SYSWMEVENT:\n");
2833 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
2835 for (i = 0; i < num_files; i++)
2837 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
2838 char buffer[buffer_len + 1];
2840 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
2842 printf("::: - '%s'\n", buffer);
2845 #if defined(TARGET_SDL2)
2846 DragFinish((HDROP)syswmmsg->msg.win.wParam);
2848 DragFinish((HDROP)syswmmsg->wParam);
2855 /* ========================================================================= */
2856 /* joystick functions */
2857 /* ========================================================================= */
2859 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
2860 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2861 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2863 static boolean SDLOpenJoystick(int nr)
2865 if (nr < 0 || nr > MAX_PLAYERS)
2868 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
2871 static void SDLCloseJoystick(int nr)
2873 if (nr < 0 || nr > MAX_PLAYERS)
2876 SDL_JoystickClose(sdl_joystick[nr]);
2878 sdl_joystick[nr] = NULL;
2881 static boolean SDLCheckJoystickOpened(int nr)
2883 if (nr < 0 || nr > MAX_PLAYERS)
2886 #if defined(TARGET_SDL2)
2887 return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
2889 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
2893 void HandleJoystickEvent(Event *event)
2897 case SDL_JOYAXISMOTION:
2898 if (event->jaxis.axis < 2)
2899 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
2902 case SDL_JOYBUTTONDOWN:
2903 if (event->jbutton.button < 2)
2904 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
2907 case SDL_JOYBUTTONUP:
2908 if (event->jbutton.button < 2)
2909 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
2917 void SDLInitJoysticks()
2919 static boolean sdl_joystick_subsystem_initialized = FALSE;
2920 boolean print_warning = !sdl_joystick_subsystem_initialized;
2923 if (!sdl_joystick_subsystem_initialized)
2925 sdl_joystick_subsystem_initialized = TRUE;
2927 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2929 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
2934 for (i = 0; i < MAX_PLAYERS; i++)
2936 /* get configured joystick for this player */
2937 char *device_name = setup.input[i].joy.device_name;
2938 int joystick_nr = getJoystickNrFromDeviceName(device_name);
2940 if (joystick_nr >= SDL_NumJoysticks())
2942 if (setup.input[i].use_joystick && print_warning)
2943 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
2948 /* misuse joystick file descriptor variable to store joystick number */
2949 joystick.fd[i] = joystick_nr;
2951 if (joystick_nr == -1)
2954 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
2955 if (SDLCheckJoystickOpened(joystick_nr))
2956 SDLCloseJoystick(joystick_nr);
2958 if (!setup.input[i].use_joystick)
2961 if (!SDLOpenJoystick(joystick_nr))
2964 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
2969 joystick.status = JOYSTICK_ACTIVATED;
2973 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
2975 if (nr < 0 || nr >= MAX_PLAYERS)
2979 *x = sdl_js_axis[nr][0];
2981 *y = sdl_js_axis[nr][1];
2984 *b1 = sdl_js_button[nr][0];
2986 *b2 = sdl_js_button[nr][1];
2991 #endif /* TARGET_SDL */