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 1
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;
44 /* functions from SGE library */
45 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
47 #if defined(TARGET_SDL2)
48 static void UpdateScreen(SDL_Rect *rect)
51 SDL_Surface *screen = backbuffer->surface;
56 int bytes_x = screen->pitch / video.width;
57 int bytes_y = screen->pitch;
59 if (video.fullscreen_enabled)
60 bytes_x = screen->pitch / fullscreen_width;
62 SDL_UpdateTexture(sdl_texture, rect,
63 screen->pixels + rect->x * bytes_x + rect->y * bytes_y,
68 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
71 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
73 SDL_RenderClear(sdl_renderer);
74 SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
75 SDL_RenderPresent(sdl_renderer);
78 SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
80 SDL_UpdateWindowSurface(sdl_window);
85 static void setFullscreenParameters(char *fullscreen_mode_string)
87 #if defined(TARGET_SDL2)
88 fullscreen_width = video.width;
89 fullscreen_height = video.height;
90 fullscreen_xoffset = 0;
91 fullscreen_yoffset = 0;
95 struct ScreenModeInfo *fullscreen_mode;
98 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
100 if (fullscreen_mode == NULL)
103 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
105 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
106 fullscreen_mode->height == video.fullscreen_modes[i].height)
108 fullscreen_width = fullscreen_mode->width;
109 fullscreen_height = fullscreen_mode->height;
111 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
112 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
120 static void SDLSetWindowIcon(char *basename)
122 /* (setting the window icon on Mac OS X would replace the high-quality
123 dock icon with the currently smaller (and uglier) icon from file) */
125 #if !defined(PLATFORM_MACOSX)
126 char *filename = getCustomImageFilename(basename);
127 SDL_Surface *surface;
129 if (filename == NULL)
131 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
136 if ((surface = IMG_Load(filename)) == NULL)
138 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
143 /* set transparent color */
144 SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
145 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
147 #if defined(TARGET_SDL2)
148 SDL_SetWindowIcon(sdl_window, surface);
150 SDL_WM_SetIcon(surface, NULL);
155 #if defined(TARGET_SDL2)
156 SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface)
158 if (backbuffer == NULL ||
159 backbuffer->surface == NULL)
162 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
166 void SDLInitVideoDisplay(void)
168 #if !defined(TARGET_SDL2)
169 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
170 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
172 SDL_putenv("SDL_VIDEO_CENTERED=1");
175 /* initialize SDL video */
176 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
177 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
179 /* set default SDL depth */
180 #if !defined(TARGET_SDL2)
181 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
183 video.default_depth = 32; // (how to determine video depth in SDL2?)
187 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
190 #if !defined(TARGET_SDL2)
191 static int screen_xy[][2] =
199 SDL_Rect **modes = NULL;
202 /* default: normal game window size */
203 fullscreen_width = video.width;
204 fullscreen_height = video.height;
205 fullscreen_xoffset = 0;
206 fullscreen_yoffset = 0;
208 #if !defined(TARGET_SDL2)
209 for (i = 0; screen_xy[i][0] != -1; i++)
211 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
213 fullscreen_width = screen_xy[i][0];
214 fullscreen_height = screen_xy[i][1];
220 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
221 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
225 checked_free(video.fullscreen_modes);
227 video.fullscreen_modes = NULL;
228 video.fullscreen_mode_current = NULL;
231 #if defined(TARGET_SDL2)
232 int num_displays = SDL_GetNumVideoDisplays();
234 if (num_displays > 0)
236 // currently only display modes of first display supported
237 int num_modes = SDL_GetNumDisplayModes(0);
241 modes = checked_calloc((num_modes + 1) * sizeof(SDL_Rect *));
243 for (i = 0; i < num_modes; i++)
245 SDL_DisplayMode mode;
247 if (SDL_GetDisplayMode(0, i, &mode) < 0)
250 modes[i] = checked_calloc(sizeof(SDL_Rect));
252 modes[i]->w = mode.w;
253 modes[i]->h = mode.h;
260 /* get available hardware supported fullscreen modes */
261 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
266 /* no screen modes available => no fullscreen mode support */
267 video.fullscreen_available = FALSE;
269 else if (modes == (SDL_Rect **)-1)
271 /* fullscreen resolution is not restricted -- all resolutions available */
272 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
274 /* use native video buffer size for fullscreen mode */
275 video.fullscreen_modes[0].width = video.width;
276 video.fullscreen_modes[0].height = video.height;
278 video.fullscreen_modes[1].width = -1;
279 video.fullscreen_modes[1].height = -1;
283 /* in this case, a certain number of screen modes is available */
286 for (i = 0; modes[i] != NULL; i++)
288 boolean found_mode = FALSE;
290 /* screen mode is smaller than video buffer size -- skip it */
291 if (modes[i]->w < video.width || modes[i]->h < video.height)
294 if (video.fullscreen_modes != NULL)
295 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
296 if (modes[i]->w == video.fullscreen_modes[j].width &&
297 modes[i]->h == video.fullscreen_modes[j].height)
300 if (found_mode) /* screen mode already stored -- skip it */
303 /* new mode found; add it to list of available fullscreen modes */
307 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
309 sizeof(struct ScreenModeInfo));
311 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
312 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
314 video.fullscreen_modes[num_modes].width = -1;
315 video.fullscreen_modes[num_modes].height = -1;
320 /* no appropriate screen modes available => no fullscreen mode support */
321 video.fullscreen_available = FALSE;
325 #if defined(TARGET_SDL2)
328 for (i = 0; modes[i] != NULL; i++)
329 checked_free(modes[i]);
336 /* set window icon */
337 SDLSetWindowIcon(program.sdl_icon_filename);
340 /* open SDL video output device (window or fullscreen mode) */
341 if (!SDLSetVideoMode(backbuffer, fullscreen))
342 Error(ERR_EXIT, "setting video mode failed");
345 /* !!! SDL2 can only set the window icon if the window already exists !!! */
346 /* set window icon */
347 SDLSetWindowIcon(program.sdl_icon_filename);
350 /* set window and icon title */
351 #if defined(TARGET_SDL2)
352 SDL_SetWindowTitle(sdl_window, program.window_title);
354 SDL_WM_SetCaption(program.window_title, program.window_title);
357 /* SDL cannot directly draw to the visible video framebuffer like X11,
358 but always uses a backbuffer, which is then blitted to the visible
359 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
360 visible video framebuffer with 'SDL_Flip', if the hardware supports
361 this). Therefore do not use an additional backbuffer for drawing, but
362 use a symbolic buffer (distinguishable from the SDL backbuffer) called
363 'window', which indicates that the SDL backbuffer should be updated to
364 the visible video framebuffer when attempting to blit to it.
366 For convenience, it seems to be a good idea to create this symbolic
367 buffer 'window' at the same size as the SDL backbuffer. Although it
368 should never be drawn to directly, it would do no harm nevertheless. */
370 /* create additional (symbolic) buffer for double-buffering */
372 ReCreateBitmap(window, video.width, video.height, video.depth);
374 *window = CreateBitmap(video.width, video.height, video.depth);
378 static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
381 SDL_Surface *new_surface = NULL;
383 int surface_flags_window = SURFACE_FLAGS;
384 #if defined(TARGET_SDL2)
387 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
389 // (never used with SDL2 now)
390 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
394 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
397 int width = (fullscreen ? fullscreen_width : video.width);
398 int height = (fullscreen ? fullscreen_height : video.height);
399 int surface_flags = (fullscreen ? surface_flags_fullscreen :
400 surface_flags_window);
402 #if defined(TARGET_SDL2)
405 float scale_factor = 1.2;
407 if ((*backbuffer)->surface)
408 SDL_FreeSurface((*backbuffer)->surface);
411 SDL_DestroyTexture(sdl_texture);
414 SDL_DestroyRenderer(sdl_renderer);
417 SDL_DestroyWindow(sdl_window);
419 sdl_window = SDL_CreateWindow(program.window_title,
420 SDL_WINDOWPOS_CENTERED,
421 SDL_WINDOWPOS_CENTERED,
422 (int)(scale_factor * width),
423 (int)(scale_factor * height),
426 if (sdl_window != NULL)
428 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
430 if (sdl_renderer != NULL)
432 SDL_RenderSetLogicalSize(sdl_renderer, width, height);
433 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
435 sdl_texture = SDL_CreateTexture(sdl_renderer,
436 SDL_PIXELFORMAT_ARGB8888,
437 SDL_TEXTUREACCESS_STREAMING,
440 if (sdl_texture != NULL)
443 // (do not use alpha channel)
444 new_surface = SDL_CreateRGBSurface(0, width, height, 32,
450 // (this uses an alpha channel, which we don't want here)
451 new_surface = SDL_CreateRGBSurface(0, width, height, 32,
458 if (new_surface == NULL)
459 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
464 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
469 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
474 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
480 SDL_DestroyWindow(sdl_window);
482 sdl_window = SDL_CreateWindow(program.window_title,
483 SDL_WINDOWPOS_CENTERED,
484 SDL_WINDOWPOS_CENTERED,
488 if (sdl_window != NULL)
489 new_surface = SDL_GetWindowSurface(sdl_window);
493 new_surface = SDL_SetVideoMode(width, height, video.depth, surface_flags);
499 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
501 boolean success = TRUE;
504 #if defined(TARGET_SDL2)
505 // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
506 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
507 int surface_flags_window = SURFACE_FLAGS;
509 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
510 int surface_flags_window = SURFACE_FLAGS;
513 SDL_Surface *new_surface = NULL;
515 if (*backbuffer == NULL)
516 *backbuffer = CreateBitmapStruct();
518 /* (real bitmap might be larger in fullscreen mode with video offsets) */
519 (*backbuffer)->width = video.width;
520 (*backbuffer)->height = video.height;
522 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
524 setFullscreenParameters(setup.fullscreen_mode);
526 video_xoffset = fullscreen_xoffset;
527 video_yoffset = fullscreen_yoffset;
529 /* switch display to fullscreen mode, if available */
531 new_surface = SDLCreateScreen(backbuffer, TRUE);
534 #if defined(TARGET_SDL2)
535 sdl_window = SDL_CreateWindow(program.window_title,
536 SDL_WINDOWPOS_CENTERED,
537 SDL_WINDOWPOS_CENTERED,
538 fullscreen_width, fullscreen_height,
539 surface_flags_fullscreen);
540 if (sdl_window != NULL)
542 new_surface = SDL_GetWindowSurface(sdl_window);
544 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
545 // UpdateScreen(NULL); // immediately map window
548 new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
549 video.depth, surface_flags_fullscreen);
553 if (new_surface == NULL)
555 /* switching display to fullscreen mode failed */
556 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
558 /* do not try it again */
559 video.fullscreen_available = FALSE;
565 (*backbuffer)->surface = new_surface;
567 video.fullscreen_enabled = TRUE;
568 video.fullscreen_mode_current = setup.fullscreen_mode;
574 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
579 /* switch display to window mode */
581 new_surface = SDLCreateScreen(backbuffer, FALSE);
584 #if defined(TARGET_SDL2)
587 float scale_factor = 1.2;
588 int test_fullscreen = 0;
589 int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
590 surface_flags_window);
592 if ((*backbuffer)->surface)
593 SDL_FreeSurface((*backbuffer)->surface);
596 SDL_DestroyTexture(sdl_texture);
599 SDL_DestroyRenderer(sdl_renderer);
602 SDL_DestroyWindow(sdl_window);
604 sdl_window = SDL_CreateWindow(program.window_title,
605 SDL_WINDOWPOS_CENTERED,
606 SDL_WINDOWPOS_CENTERED,
607 (int)(scale_factor * video.width),
608 (int)(scale_factor * video.height),
611 if (sdl_window != NULL)
613 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
615 if (sdl_renderer != NULL)
617 SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height);
618 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
620 sdl_texture = SDL_CreateTexture(sdl_renderer,
621 SDL_PIXELFORMAT_ARGB8888,
622 SDL_TEXTUREACCESS_STREAMING,
623 video.width, video.height);
625 if (sdl_texture != NULL)
628 // (do not use alpha channel)
629 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
635 // (this uses an alpha channel, which we don't want here)
636 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
643 if (new_surface == NULL)
644 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
649 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
654 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
659 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
665 SDL_DestroyWindow(sdl_window);
667 sdl_window = SDL_CreateWindow(program.window_title,
668 SDL_WINDOWPOS_CENTERED,
669 SDL_WINDOWPOS_CENTERED,
670 video.width, video.height,
671 surface_flags_window);
673 if (sdl_window != NULL)
675 new_surface = SDL_GetWindowSurface(sdl_window);
677 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
678 // UpdateScreen(NULL); // immediately map window
683 new_surface = SDL_SetVideoMode(video.width, video.height,
684 video.depth, surface_flags_window);
688 if (new_surface == NULL)
690 /* switching display to window mode failed -- should not happen */
691 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
697 (*backbuffer)->surface = new_surface;
699 video.fullscreen_enabled = FALSE;
705 #if defined(TARGET_SDL2)
706 UpdateScreen(NULL); // map window
710 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
712 #if defined(PLATFORM_WIN32)
714 SDL_SysWMinfo wminfo;
717 SDL_VERSION(&wminfo.version);
718 SDL_GetWMInfo(&wminfo);
720 hwnd = wminfo.window;
722 DragAcceptFiles(hwnd, TRUE);
730 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
733 SDL_Surface *surface_tmp, *surface_native;
735 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
738 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
740 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
741 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
743 SDL_FreeSurface(surface_tmp);
745 new_bitmap->surface = surface_native;
748 void SDLFreeBitmapPointers(Bitmap *bitmap)
751 SDL_FreeSurface(bitmap->surface);
752 if (bitmap->surface_masked)
753 SDL_FreeSurface(bitmap->surface_masked);
754 bitmap->surface = NULL;
755 bitmap->surface_masked = NULL;
758 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
759 int src_x, int src_y, int width, int height,
760 int dst_x, int dst_y, int mask_mode)
762 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
763 SDL_Rect src_rect, dst_rect;
765 if (src_bitmap == backbuffer)
767 src_x += video_xoffset;
768 src_y += video_yoffset;
776 if (dst_bitmap == backbuffer || dst_bitmap == window)
778 dst_x += video_xoffset;
779 dst_y += video_yoffset;
787 // if (src_bitmap != backbuffer || dst_bitmap != window)
788 if (!(src_bitmap == backbuffer && dst_bitmap == window))
789 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
790 src_bitmap->surface_masked : src_bitmap->surface),
791 &src_rect, real_dst_bitmap->surface, &dst_rect);
793 #if defined(TARGET_SDL2)
794 if (dst_bitmap == window)
796 // SDL_UpdateWindowSurface(sdl_window);
797 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
798 UpdateScreen(&dst_rect);
801 if (dst_bitmap == window)
802 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
806 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
809 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
812 if (dst_bitmap == backbuffer || dst_bitmap == window)
823 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
825 #if defined(TARGET_SDL2)
826 if (dst_bitmap == window)
828 // SDL_UpdateWindowSurface(sdl_window);
829 // SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
833 if (dst_bitmap == window)
834 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
838 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
839 int fade_mode, int fade_delay, int post_delay,
840 void (*draw_border_function)(void))
842 static boolean initialization_needed = TRUE;
843 static SDL_Surface *surface_source = NULL;
844 static SDL_Surface *surface_target = NULL;
845 static SDL_Surface *surface_black = NULL;
846 SDL_Surface *surface_screen = backbuffer->surface;
847 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
848 SDL_Rect src_rect, dst_rect;
849 #if defined(TARGET_SDL2)
852 int src_x = x, src_y = y;
853 int dst_x = x, dst_y = y;
854 unsigned int time_last, time_current;
856 /* check if screen size has changed */
857 if (surface_source != NULL && (video.width != surface_source->w ||
858 video.height != surface_source->h))
860 SDL_FreeSurface(surface_source);
861 SDL_FreeSurface(surface_target);
862 SDL_FreeSurface(surface_black);
864 initialization_needed = TRUE;
872 dst_x += video_xoffset;
873 dst_y += video_yoffset;
877 dst_rect.w = width; /* (ignored) */
878 dst_rect.h = height; /* (ignored) */
880 #if defined(TARGET_SDL2)
881 dst_rect2 = dst_rect;
884 if (initialization_needed)
886 #if defined(TARGET_SDL2)
887 unsigned int flags = 0;
889 unsigned int flags = SDL_SRCALPHA;
891 /* use same surface type as screen surface */
892 if ((surface_screen->flags & SDL_HWSURFACE))
893 flags |= SDL_HWSURFACE;
895 flags |= SDL_SWSURFACE;
898 /* create surface for temporary copy of screen buffer (source) */
899 if ((surface_source =
900 SDL_CreateRGBSurface(flags,
903 surface_screen->format->BitsPerPixel,
904 surface_screen->format->Rmask,
905 surface_screen->format->Gmask,
906 surface_screen->format->Bmask,
907 surface_screen->format->Amask)) == NULL)
908 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
910 /* create surface for cross-fading screen buffer (target) */
911 if ((surface_target =
912 SDL_CreateRGBSurface(flags,
915 surface_screen->format->BitsPerPixel,
916 surface_screen->format->Rmask,
917 surface_screen->format->Gmask,
918 surface_screen->format->Bmask,
919 surface_screen->format->Amask)) == NULL)
920 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
922 /* create black surface for fading from/to black */
924 SDL_CreateRGBSurface(flags,
927 surface_screen->format->BitsPerPixel,
928 surface_screen->format->Rmask,
929 surface_screen->format->Gmask,
930 surface_screen->format->Bmask,
931 surface_screen->format->Amask)) == NULL)
932 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
934 /* completely fill the surface with black color pixels */
935 SDL_FillRect(surface_black, NULL,
936 SDL_MapRGB(surface_screen->format, 0, 0, 0));
938 initialization_needed = FALSE;
941 /* copy source and target surfaces to temporary surfaces for fading */
942 if (fade_mode & FADE_TYPE_TRANSFORM)
944 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
945 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
947 else if (fade_mode & FADE_TYPE_FADE_IN)
949 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
950 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
952 else /* FADE_TYPE_FADE_OUT */
954 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
955 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
958 time_current = SDL_GetTicks();
960 if (fade_mode == FADE_MODE_MELT)
962 boolean done = FALSE;
964 int melt_columns = width / melt_pixels;
965 int ypos[melt_columns];
966 int max_steps = height / 8 + 32;
971 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
972 #if defined(TARGET_SDL2)
973 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
975 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
978 ypos[0] = -GetSimpleRandom(16);
980 for (i = 1 ; i < melt_columns; i++)
982 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
984 ypos[i] = ypos[i - 1] + r;
997 time_last = time_current;
998 time_current = SDL_GetTicks();
999 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
1000 steps_final = MIN(MAX(0, steps), max_steps);
1004 done = (steps_done >= steps_final);
1006 for (i = 0 ; i < melt_columns; i++)
1014 else if (ypos[i] < height)
1019 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
1021 if (ypos[i] + dy >= height)
1022 dy = height - ypos[i];
1024 /* copy part of (appearing) target surface to upper area */
1025 src_rect.x = src_x + i * melt_pixels;
1026 // src_rect.y = src_y + ypos[i];
1028 src_rect.w = melt_pixels;
1030 src_rect.h = ypos[i] + dy;
1032 dst_rect.x = dst_x + i * melt_pixels;
1033 // dst_rect.y = dst_y + ypos[i];
1036 if (steps_done >= steps_final)
1037 SDL_BlitSurface(surface_target, &src_rect,
1038 surface_screen, &dst_rect);
1042 /* copy part of (disappearing) source surface to lower area */
1043 src_rect.x = src_x + i * melt_pixels;
1045 src_rect.w = melt_pixels;
1046 src_rect.h = height - ypos[i];
1048 dst_rect.x = dst_x + i * melt_pixels;
1049 dst_rect.y = dst_y + ypos[i];
1051 if (steps_done >= steps_final)
1052 SDL_BlitSurface(surface_source, &src_rect,
1053 surface_screen, &dst_rect);
1059 src_rect.x = src_x + i * melt_pixels;
1061 src_rect.w = melt_pixels;
1062 src_rect.h = height;
1064 dst_rect.x = dst_x + i * melt_pixels;
1067 if (steps_done >= steps_final)
1068 SDL_BlitSurface(surface_target, &src_rect,
1069 surface_screen, &dst_rect);
1073 if (steps_done >= steps_final)
1075 if (draw_border_function != NULL)
1076 draw_border_function();
1078 #if defined(TARGET_SDL2)
1079 // SDL_UpdateWindowSurface(sdl_window);
1080 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
1081 UpdateScreen(&dst_rect2);
1083 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
1093 for (alpha = 0.0; alpha < 255.0;)
1095 time_last = time_current;
1096 time_current = SDL_GetTicks();
1097 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
1098 alpha_final = MIN(MAX(0, alpha), 255);
1100 /* draw existing (source) image to screen buffer */
1101 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
1103 /* draw new (target) image to screen buffer using alpha blending */
1104 #if defined(TARGET_SDL2)
1105 SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
1106 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
1108 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
1110 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
1112 if (draw_border_function != NULL)
1113 draw_border_function();
1116 /* only update the region of the screen that is affected from fading */
1117 #if defined(TARGET_SDL2)
1118 // SDL_UpdateWindowSurface(sdl_window);
1119 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
1120 UpdateScreen(&dst_rect);
1122 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
1125 SDL_Flip(surface_screen);
1133 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
1134 int to_x, int to_y, Uint32 color)
1136 SDL_Surface *surface = dst_bitmap->surface;
1140 swap_numbers(&from_x, &to_x);
1143 swap_numbers(&from_y, &to_y);
1147 rect.w = (to_x - from_x + 1);
1148 rect.h = (to_y - from_y + 1);
1150 if (dst_bitmap == backbuffer || dst_bitmap == window)
1152 rect.x += video_xoffset;
1153 rect.y += video_yoffset;
1156 SDL_FillRect(surface, &rect, color);
1159 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
1160 int to_x, int to_y, Uint32 color)
1162 if (dst_bitmap == backbuffer || dst_bitmap == window)
1164 from_x += video_xoffset;
1165 from_y += video_yoffset;
1166 to_x += video_xoffset;
1167 to_y += video_yoffset;
1170 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
1174 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
1175 int num_points, Uint32 color)
1180 for (i = 0; i < num_points - 1; i++)
1182 for (x = 0; x < line_width; x++)
1184 for (y = 0; y < line_width; y++)
1186 int dx = x - line_width / 2;
1187 int dy = y - line_width / 2;
1189 if ((x == 0 && y == 0) ||
1190 (x == 0 && y == line_width - 1) ||
1191 (x == line_width - 1 && y == 0) ||
1192 (x == line_width - 1 && y == line_width - 1))
1195 sge_Line(surface, points[i].x + dx, points[i].y + dy,
1196 points[i+1].x + dx, points[i+1].y + dy, color);
1203 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
1205 SDL_Surface *surface = src_bitmap->surface;
1207 if (src_bitmap == backbuffer || src_bitmap == window)
1213 switch (surface->format->BytesPerPixel)
1215 case 1: /* assuming 8-bpp */
1217 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
1221 case 2: /* probably 15-bpp or 16-bpp */
1223 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
1227 case 3: /* slow 24-bpp mode; usually not used */
1229 /* does this work? */
1230 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
1234 shift = surface->format->Rshift;
1235 color |= *(pix + shift / 8) >> shift;
1236 shift = surface->format->Gshift;
1237 color |= *(pix + shift / 8) >> shift;
1238 shift = surface->format->Bshift;
1239 color |= *(pix + shift / 8) >> shift;
1245 case 4: /* probably 32-bpp */
1247 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
1256 /* ========================================================================= */
1257 /* The following functions were taken from the SGE library */
1258 /* (SDL Graphics Extension Library) by Anders Lindström */
1259 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
1260 /* ========================================================================= */
1262 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1264 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
1266 switch (surface->format->BytesPerPixel)
1270 /* Assuming 8-bpp */
1271 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1277 /* Probably 15-bpp or 16-bpp */
1278 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1284 /* Slow 24-bpp mode, usually not used */
1288 /* Gack - slow, but endian correct */
1289 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1290 shift = surface->format->Rshift;
1291 *(pix+shift/8) = color>>shift;
1292 shift = surface->format->Gshift;
1293 *(pix+shift/8) = color>>shift;
1294 shift = surface->format->Bshift;
1295 *(pix+shift/8) = color>>shift;
1301 /* Probably 32-bpp */
1302 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1309 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1310 Uint8 R, Uint8 G, Uint8 B)
1312 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
1315 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1317 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1320 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1322 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1325 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1330 /* Gack - slow, but endian correct */
1331 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1332 shift = surface->format->Rshift;
1333 *(pix+shift/8) = color>>shift;
1334 shift = surface->format->Gshift;
1335 *(pix+shift/8) = color>>shift;
1336 shift = surface->format->Bshift;
1337 *(pix+shift/8) = color>>shift;
1340 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1342 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1345 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
1347 switch (dest->format->BytesPerPixel)
1350 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
1354 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
1358 _PutPixel24(dest,x,y,color);
1362 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
1367 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1369 if (SDL_MUSTLOCK(surface))
1371 if (SDL_LockSurface(surface) < 0)
1377 _PutPixel(surface, x, y, color);
1379 if (SDL_MUSTLOCK(surface))
1381 SDL_UnlockSurface(surface);
1385 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1386 Uint8 r, Uint8 g, Uint8 b)
1388 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
1391 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
1393 if (y >= 0 && y <= dest->h - 1)
1395 switch (dest->format->BytesPerPixel)
1398 return y*dest->pitch;
1402 return y*dest->pitch/2;
1406 return y*dest->pitch;
1410 return y*dest->pitch/4;
1418 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
1420 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
1422 switch (surface->format->BytesPerPixel)
1426 /* Assuming 8-bpp */
1427 *((Uint8 *)surface->pixels + ypitch + x) = color;
1433 /* Probably 15-bpp or 16-bpp */
1434 *((Uint16 *)surface->pixels + ypitch + x) = color;
1440 /* Slow 24-bpp mode, usually not used */
1444 /* Gack - slow, but endian correct */
1445 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1446 shift = surface->format->Rshift;
1447 *(pix+shift/8) = color>>shift;
1448 shift = surface->format->Gshift;
1449 *(pix+shift/8) = color>>shift;
1450 shift = surface->format->Bshift;
1451 *(pix+shift/8) = color>>shift;
1457 /* Probably 32-bpp */
1458 *((Uint32 *)surface->pixels + ypitch + x) = color;
1465 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1470 if (SDL_MUSTLOCK(Surface))
1472 if (SDL_LockSurface(Surface) < 0)
1485 /* Do the clipping */
1486 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1490 if (x2 > Surface->w - 1)
1491 x2 = Surface->w - 1;
1498 SDL_FillRect(Surface, &l, Color);
1500 if (SDL_MUSTLOCK(Surface))
1502 SDL_UnlockSurface(Surface);
1506 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1507 Uint8 R, Uint8 G, Uint8 B)
1509 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1512 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1523 /* Do the clipping */
1524 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1528 if (x2 > Surface->w - 1)
1529 x2 = Surface->w - 1;
1536 SDL_FillRect(Surface, &l, Color);
1539 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1544 if (SDL_MUSTLOCK(Surface))
1546 if (SDL_LockSurface(Surface) < 0)
1559 /* Do the clipping */
1560 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1564 if (y2 > Surface->h - 1)
1565 y2 = Surface->h - 1;
1572 SDL_FillRect(Surface, &l, Color);
1574 if (SDL_MUSTLOCK(Surface))
1576 SDL_UnlockSurface(Surface);
1580 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1581 Uint8 R, Uint8 G, Uint8 B)
1583 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1586 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1597 /* Do the clipping */
1598 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1602 if (y2 > Surface->h - 1)
1603 y2 = Surface->h - 1;
1610 SDL_FillRect(Surface, &l, Color);
1613 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1614 Sint16 x2, Sint16 y2, Uint32 Color,
1615 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1618 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1623 sdx = (dx < 0) ? -1 : 1;
1624 sdy = (dy < 0) ? -1 : 1;
1636 for (x = 0; x < dx; x++)
1638 Callback(Surface, px, py, Color);
1652 for (y = 0; y < dy; y++)
1654 Callback(Surface, px, py, Color);
1668 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
1669 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
1670 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1673 sge_DoLine(Surface, X1, Y1, X2, Y2,
1674 SDL_MapRGB(Surface->format, R, G, B), Callback);
1677 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
1680 if (SDL_MUSTLOCK(Surface))
1682 if (SDL_LockSurface(Surface) < 0)
1687 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
1689 /* unlock the display */
1690 if (SDL_MUSTLOCK(Surface))
1692 SDL_UnlockSurface(Surface);
1696 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
1697 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1699 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
1702 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
1704 if (dst_bitmap == backbuffer || dst_bitmap == window)
1710 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
1715 -----------------------------------------------------------------------------
1716 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
1717 -----------------------------------------------------------------------------
1720 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
1721 int width, int height, Uint32 color)
1725 for (y = src_y; y < src_y + height; y++)
1727 for (x = src_x; x < src_x + width; x++)
1729 Uint32 pixel = SDLGetPixel(bitmap, x, y);
1731 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
1736 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1737 int src_x, int src_y, int width, int height,
1738 int dst_x, int dst_y)
1742 for (y = 0; y < height; y++)
1744 for (x = 0; x < width; x++)
1746 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
1748 if (pixel != BLACK_PIXEL)
1749 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
1755 /* ========================================================================= */
1756 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
1757 /* (Rotozoomer) by Andreas Schiffler */
1758 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
1759 /* ========================================================================= */
1762 -----------------------------------------------------------------------------
1765 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
1766 -----------------------------------------------------------------------------
1777 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
1780 tColorRGBA *sp, *csp, *dp;
1787 sp = csp = (tColorRGBA *) src->pixels;
1788 dp = (tColorRGBA *) dst->pixels;
1790 sgap = src->pitch - src->w * 4;
1792 dgap = dst->pitch - dst->w * 4;
1794 for (y = 0; y < dst->h; y++)
1798 for (x = 0; x < dst->w; x++)
1800 tColorRGBA *sp0 = sp;
1801 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1802 tColorRGBA *sp00 = &sp0[0];
1803 tColorRGBA *sp01 = &sp0[1];
1804 tColorRGBA *sp10 = &sp1[0];
1805 tColorRGBA *sp11 = &sp1[1];
1808 /* create new color pixel from all four source color pixels */
1809 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1810 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1811 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1812 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1817 /* advance source pointers */
1820 /* advance destination pointer */
1824 /* advance source pointer */
1825 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1827 /* advance destination pointers */
1828 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1834 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1836 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1837 tColorRGBA *sp, *csp, *dp;
1843 /* use specialized zoom function when scaling down to exactly half size */
1844 if (src->w == 2 * dst->w &&
1845 src->h == 2 * dst->h)
1846 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1848 /* variable setup */
1849 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1850 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1852 /* allocate memory for row increments */
1853 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1854 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1856 /* precalculate row increments */
1859 for (x = 0; x <= dst->w; x++)
1869 for (y = 0; y <= dst->h; y++)
1878 sp = csp = (tColorRGBA *) src->pixels;
1879 dp = (tColorRGBA *) dst->pixels;
1881 sgap = src->pitch - src->w * 4;
1883 dgap = dst->pitch - dst->w * 4;
1886 for (y = 0; y < dst->h; y++)
1891 for (x = 0; x < dst->w; x++)
1896 /* advance source pointers */
1898 sp += (*csax >> 16);
1900 /* advance destination pointer */
1904 /* advance source pointer */
1906 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1908 /* advance destination pointers */
1909 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1919 -----------------------------------------------------------------------------
1922 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1923 -----------------------------------------------------------------------------
1926 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1928 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1929 Uint8 *sp, *dp, *csp;
1932 /* variable setup */
1933 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1934 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1936 /* allocate memory for row increments */
1937 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1938 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1940 /* precalculate row increments */
1943 for (x = 0; x < dst->w; x++)
1946 *csax = (csx >> 16);
1953 for (y = 0; y < dst->h; y++)
1956 *csay = (csy >> 16);
1963 for (x = 0; x < dst->w; x++)
1971 for (y = 0; y < dst->h; y++)
1978 sp = csp = (Uint8 *) src->pixels;
1979 dp = (Uint8 *) dst->pixels;
1980 dgap = dst->pitch - dst->w;
1984 for (y = 0; y < dst->h; y++)
1988 for (x = 0; x < dst->w; x++)
1993 /* advance source pointers */
1997 /* advance destination pointer */
2001 /* advance source pointer (for row) */
2002 csp += ((*csay) * src->pitch);
2005 /* advance destination pointers */
2016 -----------------------------------------------------------------------------
2019 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
2020 'zoomx' and 'zoomy' are scaling factors for width and height.
2021 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
2022 into a 32bit RGBA format on the fly.
2023 -----------------------------------------------------------------------------
2026 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
2028 SDL_Surface *zoom_src = NULL;
2029 SDL_Surface *zoom_dst = NULL;
2030 boolean is_converted = FALSE;
2037 /* determine if source surface is 32 bit or 8 bit */
2038 is_32bit = (src->format->BitsPerPixel == 32);
2040 if (is_32bit || src->format->BitsPerPixel == 8)
2042 /* use source surface 'as is' */
2047 /* new source surface is 32 bit with a defined RGB ordering */
2048 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
2049 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
2050 SDL_BlitSurface(src, NULL, zoom_src, NULL);
2052 is_converted = TRUE;
2055 /* allocate surface to completely contain the zoomed surface */
2058 /* target surface is 32 bit with source RGBA/ABGR ordering */
2059 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
2060 zoom_src->format->Rmask,
2061 zoom_src->format->Gmask,
2062 zoom_src->format->Bmask, 0);
2066 /* target surface is 8 bit */
2067 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
2071 /* lock source surface */
2072 SDL_LockSurface(zoom_src);
2074 /* check which kind of surface we have */
2077 /* call the 32 bit transformation routine to do the zooming */
2078 zoomSurfaceRGBA(zoom_src, zoom_dst);
2083 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
2084 zoom_dst->format->palette->colors[i] =
2085 zoom_src->format->palette->colors[i];
2086 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
2088 /* call the 8 bit transformation routine to do the zooming */
2089 zoomSurfaceY(zoom_src, zoom_dst);
2092 /* unlock source surface */
2093 SDL_UnlockSurface(zoom_src);
2095 /* free temporary surface */
2097 SDL_FreeSurface(zoom_src);
2099 /* return destination surface */
2103 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
2105 SDL_Surface *sdl_surface_tmp;
2106 int dst_width = dst_bitmap->width;
2107 int dst_height = dst_bitmap->height;
2109 /* throw away old destination surface */
2110 SDL_FreeSurface(dst_bitmap->surface);
2112 /* create zoomed temporary surface from source surface */
2113 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
2115 /* create native format destination surface from zoomed temporary surface */
2116 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
2118 /* free temporary surface */
2119 SDL_FreeSurface(sdl_surface_tmp);
2123 /* ========================================================================= */
2124 /* load image to bitmap */
2125 /* ========================================================================= */
2127 Bitmap *SDLLoadImage(char *filename)
2129 Bitmap *new_bitmap = CreateBitmapStruct();
2130 SDL_Surface *sdl_image_tmp;
2132 print_timestamp_init("SDLLoadImage");
2134 print_timestamp_time(getBaseNamePtr(filename));
2136 /* load image to temporary surface */
2137 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
2139 SetError("IMG_Load(): %s", SDL_GetError());
2144 print_timestamp_time("IMG_Load");
2146 UPDATE_BUSY_STATE();
2148 /* create native non-transparent surface for current image */
2149 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
2151 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2156 print_timestamp_time("SDL_DisplayFormat (opaque)");
2158 UPDATE_BUSY_STATE();
2160 /* create native transparent surface for current image */
2161 SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
2162 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
2163 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
2165 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
2170 print_timestamp_time("SDL_DisplayFormat (masked)");
2172 UPDATE_BUSY_STATE();
2174 /* free temporary surface */
2175 SDL_FreeSurface(sdl_image_tmp);
2177 new_bitmap->width = new_bitmap->surface->w;
2178 new_bitmap->height = new_bitmap->surface->h;
2180 print_timestamp_done("SDLLoadImage");
2186 /* ------------------------------------------------------------------------- */
2187 /* custom cursor fuctions */
2188 /* ------------------------------------------------------------------------- */
2190 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
2192 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
2193 cursor_info->width, cursor_info->height,
2194 cursor_info->hot_x, cursor_info->hot_y);
2197 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
2199 static struct MouseCursorInfo *last_cursor_info = NULL;
2200 static struct MouseCursorInfo *last_cursor_info2 = NULL;
2201 static SDL_Cursor *cursor_default = NULL;
2202 static SDL_Cursor *cursor_current = NULL;
2204 /* if invoked for the first time, store the SDL default cursor */
2205 if (cursor_default == NULL)
2206 cursor_default = SDL_GetCursor();
2208 /* only create new cursor if cursor info (custom only) has changed */
2209 if (cursor_info != NULL && cursor_info != last_cursor_info)
2211 cursor_current = create_cursor(cursor_info);
2212 last_cursor_info = cursor_info;
2215 /* only set new cursor if cursor info (custom or NULL) has changed */
2216 if (cursor_info != last_cursor_info2)
2217 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
2219 last_cursor_info2 = cursor_info;
2223 /* ========================================================================= */
2224 /* audio functions */
2225 /* ========================================================================= */
2227 void SDLOpenAudio(void)
2229 #if !defined(TARGET_SDL2)
2230 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
2231 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
2234 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
2236 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
2240 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
2241 AUDIO_NUM_CHANNELS_STEREO,
2242 setup.system.audio_fragment_size) < 0)
2244 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
2248 audio.sound_available = TRUE;
2249 audio.music_available = TRUE;
2250 audio.loops_available = TRUE;
2251 audio.sound_enabled = TRUE;
2253 /* set number of available mixer channels */
2254 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
2255 audio.music_channel = MUSIC_CHANNEL;
2256 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
2258 Mixer_InitChannels();
2261 void SDLCloseAudio(void)
2264 Mix_HaltChannel(-1);
2267 SDL_QuitSubSystem(SDL_INIT_AUDIO);
2271 /* ========================================================================= */
2272 /* event functions */
2273 /* ========================================================================= */
2275 void SDLNextEvent(Event *event)
2277 SDL_WaitEvent(event);
2279 if (event->type == EVENT_BUTTONPRESS ||
2280 event->type == EVENT_BUTTONRELEASE)
2282 if (((ButtonEvent *)event)->x > video_xoffset)
2283 ((ButtonEvent *)event)->x -= video_xoffset;
2285 ((ButtonEvent *)event)->x = 0;
2286 if (((ButtonEvent *)event)->y > video_yoffset)
2287 ((ButtonEvent *)event)->y -= video_yoffset;
2289 ((ButtonEvent *)event)->y = 0;
2291 else if (event->type == EVENT_MOTIONNOTIFY)
2293 if (((MotionEvent *)event)->x > video_xoffset)
2294 ((MotionEvent *)event)->x -= video_xoffset;
2296 ((MotionEvent *)event)->x = 0;
2297 if (((MotionEvent *)event)->y > video_yoffset)
2298 ((MotionEvent *)event)->y -= video_yoffset;
2300 ((MotionEvent *)event)->y = 0;
2304 void SDLHandleWindowManagerEvent(Event *event)
2306 #if defined(PLATFORM_WIN32)
2307 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
2308 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
2310 if (syswmmsg->msg == WM_DROPFILES)
2312 HDROP hdrop = (HDROP)syswmmsg->wParam;
2315 printf("::: SDL_SYSWMEVENT:\n");
2317 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
2319 for (i = 0; i < num_files; i++)
2321 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
2322 char buffer[buffer_len + 1];
2324 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
2326 printf("::: - '%s'\n", buffer);
2329 DragFinish((HDROP)syswmmsg->wParam);
2335 /* ========================================================================= */
2336 /* joystick functions */
2337 /* ========================================================================= */
2339 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
2340 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2341 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2343 static boolean SDLOpenJoystick(int nr)
2345 if (nr < 0 || nr > MAX_PLAYERS)
2348 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
2351 static void SDLCloseJoystick(int nr)
2353 if (nr < 0 || nr > MAX_PLAYERS)
2356 SDL_JoystickClose(sdl_joystick[nr]);
2358 sdl_joystick[nr] = NULL;
2361 static boolean SDLCheckJoystickOpened(int nr)
2363 if (nr < 0 || nr > MAX_PLAYERS)
2366 #if defined(TARGET_SDL2)
2367 return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
2369 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
2373 void HandleJoystickEvent(Event *event)
2377 case SDL_JOYAXISMOTION:
2378 if (event->jaxis.axis < 2)
2379 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
2382 case SDL_JOYBUTTONDOWN:
2383 if (event->jbutton.button < 2)
2384 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
2387 case SDL_JOYBUTTONUP:
2388 if (event->jbutton.button < 2)
2389 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
2397 void SDLInitJoysticks()
2399 static boolean sdl_joystick_subsystem_initialized = FALSE;
2400 boolean print_warning = !sdl_joystick_subsystem_initialized;
2403 if (!sdl_joystick_subsystem_initialized)
2405 sdl_joystick_subsystem_initialized = TRUE;
2407 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2409 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
2414 for (i = 0; i < MAX_PLAYERS; i++)
2416 /* get configured joystick for this player */
2417 char *device_name = setup.input[i].joy.device_name;
2418 int joystick_nr = getJoystickNrFromDeviceName(device_name);
2420 if (joystick_nr >= SDL_NumJoysticks())
2422 if (setup.input[i].use_joystick && print_warning)
2423 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
2428 /* misuse joystick file descriptor variable to store joystick number */
2429 joystick.fd[i] = joystick_nr;
2431 if (joystick_nr == -1)
2434 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
2435 if (SDLCheckJoystickOpened(joystick_nr))
2436 SDLCloseJoystick(joystick_nr);
2438 if (!setup.input[i].use_joystick)
2441 if (!SDLOpenJoystick(joystick_nr))
2444 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
2449 joystick.status = JOYSTICK_ACTIVATED;
2453 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
2455 if (nr < 0 || nr >= MAX_PLAYERS)
2459 *x = sdl_js_axis[nr][0];
2461 *y = sdl_js_axis[nr][1];
2464 *b1 = sdl_js_button[nr][0];
2466 *b2 = sdl_js_button[nr][1];
2471 #endif /* TARGET_SDL */