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;
34 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
35 static int fullscreen_width;
36 static int fullscreen_height;
37 static int fullscreen_xoffset;
38 static int fullscreen_yoffset;
39 static int video_xoffset;
40 static int video_yoffset;
42 /* functions from SGE library */
43 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
45 static void UpdateScreen(SDL_Rect *rect)
48 SDL_Surface *screen = backbuffer->surface;
50 SDL_UpdateTexture(sdl_texture, NULL, screen->pixels, screen->pitch);
51 SDL_RenderClear(sdl_renderer);
52 SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
53 SDL_RenderPresent(sdl_renderer);
56 SDL_UpdateWindowSurfaceRects(sdl_window, rect, 1);
58 SDL_UpdateWindowSurface(sdl_window);
62 static void setFullscreenParameters(char *fullscreen_mode_string)
64 struct ScreenModeInfo *fullscreen_mode;
67 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
69 if (fullscreen_mode == NULL)
72 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
74 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
75 fullscreen_mode->height == video.fullscreen_modes[i].height)
77 fullscreen_width = fullscreen_mode->width;
78 fullscreen_height = fullscreen_mode->height;
80 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
81 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
88 static void SDLSetWindowIcon(char *basename)
90 /* (setting the window icon on Mac OS X would replace the high-quality
91 dock icon with the currently smaller (and uglier) icon from file) */
93 #if !defined(PLATFORM_MACOSX)
94 char *filename = getCustomImageFilename(basename);
99 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
104 if ((surface = IMG_Load(filename)) == NULL)
106 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
111 /* set transparent color */
112 SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
113 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
115 #if defined(TARGET_SDL2)
116 SDL_SetWindowIcon(sdl_window, surface);
118 SDL_WM_SetIcon(surface, NULL);
123 #if defined(TARGET_SDL2)
124 SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface)
126 if (backbuffer == NULL ||
127 backbuffer->surface == NULL)
130 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
134 void SDLInitVideoDisplay(void)
136 #if !defined(TARGET_SDL2)
137 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
138 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
140 SDL_putenv("SDL_VIDEO_CENTERED=1");
143 /* initialize SDL video */
144 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
145 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
147 /* set default SDL depth */
148 #if !defined(TARGET_SDL2)
149 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
151 video.default_depth = 32; // (how to determine video depth in SDL2?)
155 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
158 static int screen_xy[][2] =
168 /* default: normal game window size */
169 fullscreen_width = video.width;
170 fullscreen_height = video.height;
171 fullscreen_xoffset = 0;
172 fullscreen_yoffset = 0;
174 for (i = 0; screen_xy[i][0] != -1; i++)
176 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
178 fullscreen_width = screen_xy[i][0];
179 fullscreen_height = screen_xy[i][1];
185 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
186 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
189 checked_free(video.fullscreen_modes);
191 video.fullscreen_modes = NULL;
192 video.fullscreen_mode_current = NULL;
195 #if !defined(TARGET_SDL2)
196 /* get available hardware supported fullscreen modes */
197 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
199 // (for now, no display modes in SDL2 -- change this later)
205 /* no screen modes available => no fullscreen mode support */
206 video.fullscreen_available = FALSE;
208 else if (modes == (SDL_Rect **)-1)
210 /* fullscreen resolution is not restricted -- all resolutions available */
211 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
213 /* use native video buffer size for fullscreen mode */
214 video.fullscreen_modes[0].width = video.width;
215 video.fullscreen_modes[0].height = video.height;
217 video.fullscreen_modes[1].width = -1;
218 video.fullscreen_modes[1].height = -1;
222 /* in this case, a certain number of screen modes is available */
225 for(i = 0; modes[i] != NULL; i++)
227 boolean found_mode = FALSE;
229 /* screen mode is smaller than video buffer size -- skip it */
230 if (modes[i]->w < video.width || modes[i]->h < video.height)
233 if (video.fullscreen_modes != NULL)
234 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
235 if (modes[i]->w == video.fullscreen_modes[j].width &&
236 modes[i]->h == video.fullscreen_modes[j].height)
239 if (found_mode) /* screen mode already stored -- skip it */
242 /* new mode found; add it to list of available fullscreen modes */
246 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
248 sizeof(struct ScreenModeInfo));
250 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
251 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
253 video.fullscreen_modes[num_modes].width = -1;
254 video.fullscreen_modes[num_modes].height = -1;
259 /* no appropriate screen modes available => no fullscreen mode support */
260 video.fullscreen_available = FALSE;
265 /* set window icon */
266 SDLSetWindowIcon(program.sdl_icon_filename);
269 /* open SDL video output device (window or fullscreen mode) */
270 if (!SDLSetVideoMode(backbuffer, fullscreen))
271 Error(ERR_EXIT, "setting video mode failed");
274 /* !!! SDL2 can only set the window icon if the window already exists !!! */
275 /* set window icon */
276 SDLSetWindowIcon(program.sdl_icon_filename);
279 /* set window and icon title */
280 #if defined(TARGET_SDL2)
281 SDL_SetWindowTitle(sdl_window, program.window_title);
283 SDL_WM_SetCaption(program.window_title, program.window_title);
286 /* SDL cannot directly draw to the visible video framebuffer like X11,
287 but always uses a backbuffer, which is then blitted to the visible
288 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
289 visible video framebuffer with 'SDL_Flip', if the hardware supports
290 this). Therefore do not use an additional backbuffer for drawing, but
291 use a symbolic buffer (distinguishable from the SDL backbuffer) called
292 'window', which indicates that the SDL backbuffer should be updated to
293 the visible video framebuffer when attempting to blit to it.
295 For convenience, it seems to be a good idea to create this symbolic
296 buffer 'window' at the same size as the SDL backbuffer. Although it
297 should never be drawn to directly, it would do no harm nevertheless. */
299 /* create additional (symbolic) buffer for double-buffering */
301 ReCreateBitmap(window, video.width, video.height, video.depth);
303 *window = CreateBitmap(video.width, video.height, video.depth);
307 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
309 boolean success = TRUE;
310 #if defined(TARGET_SDL2)
311 // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
312 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
313 int surface_flags_window = SURFACE_FLAGS;
315 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
316 int surface_flags_window = SURFACE_FLAGS;
318 SDL_Surface *new_surface = NULL;
320 if (*backbuffer == NULL)
321 *backbuffer = CreateBitmapStruct();
323 /* (real bitmap might be larger in fullscreen mode with video offsets) */
324 (*backbuffer)->width = video.width;
325 (*backbuffer)->height = video.height;
327 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
329 setFullscreenParameters(setup.fullscreen_mode);
331 video_xoffset = fullscreen_xoffset;
332 video_yoffset = fullscreen_yoffset;
334 /* switch display to fullscreen mode, if available */
335 #if defined(TARGET_SDL2)
336 sdl_window = SDL_CreateWindow(program.window_title,
337 SDL_WINDOWPOS_CENTERED,
338 SDL_WINDOWPOS_CENTERED,
339 fullscreen_width, fullscreen_height,
340 surface_flags_fullscreen);
341 if (sdl_window != NULL)
343 new_surface = SDL_GetWindowSurface(sdl_window);
345 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
346 UpdateScreen(NULL); // immediately map window
349 new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
350 video.depth, surface_flags_fullscreen);
353 if (new_surface == NULL)
355 /* switching display to fullscreen mode failed */
356 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
358 /* do not try it again */
359 video.fullscreen_available = FALSE;
365 (*backbuffer)->surface = new_surface;
367 video.fullscreen_enabled = TRUE;
368 video.fullscreen_mode_current = setup.fullscreen_mode;
374 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
379 /* switch display to window mode */
380 #if defined(TARGET_SDL2)
383 float scale_factor = 1;
384 int test_fullscreen = 0;
385 int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
386 surface_flags_window);
388 sdl_window = SDL_CreateWindow(program.window_title,
389 SDL_WINDOWPOS_CENTERED,
390 SDL_WINDOWPOS_CENTERED,
391 (int)(scale_factor * video.width),
392 (int)(scale_factor * video.height),
395 if (sdl_window != NULL)
397 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
399 if (sdl_renderer != NULL)
401 SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height);
402 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
404 sdl_texture = SDL_CreateTexture(sdl_renderer,
405 SDL_PIXELFORMAT_ARGB8888,
406 SDL_TEXTUREACCESS_STREAMING,
407 video.width, video.height);
409 if (sdl_texture != NULL)
411 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
417 if (new_surface == NULL)
418 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
423 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
428 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
433 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
436 sdl_window = SDL_CreateWindow(program.window_title,
437 SDL_WINDOWPOS_CENTERED,
438 SDL_WINDOWPOS_CENTERED,
439 video.width, video.height,
440 surface_flags_window);
442 if (sdl_window != NULL)
444 new_surface = SDL_GetWindowSurface(sdl_window);
446 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
447 UpdateScreen(NULL); // immediately map window
452 new_surface = SDL_SetVideoMode(video.width, video.height,
453 video.depth, surface_flags_window);
456 if (new_surface == NULL)
458 /* switching display to window mode failed -- should not happen */
459 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
465 (*backbuffer)->surface = new_surface;
467 video.fullscreen_enabled = FALSE;
474 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
476 #if defined(PLATFORM_WIN32)
478 SDL_SysWMinfo wminfo;
481 SDL_VERSION(&wminfo.version);
482 SDL_GetWMInfo(&wminfo);
484 hwnd = wminfo.window;
486 DragAcceptFiles(hwnd, TRUE);
495 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
498 SDL_Surface *surface_tmp, *surface_native;
500 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
503 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
505 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
506 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
508 SDL_FreeSurface(surface_tmp);
510 new_bitmap->surface = surface_native;
513 void SDLFreeBitmapPointers(Bitmap *bitmap)
516 SDL_FreeSurface(bitmap->surface);
517 if (bitmap->surface_masked)
518 SDL_FreeSurface(bitmap->surface_masked);
519 bitmap->surface = NULL;
520 bitmap->surface_masked = NULL;
523 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
524 int src_x, int src_y, int width, int height,
525 int dst_x, int dst_y, int mask_mode)
527 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
528 SDL_Rect src_rect, dst_rect;
530 if (src_bitmap == backbuffer)
532 src_x += video_xoffset;
533 src_y += video_yoffset;
541 if (dst_bitmap == backbuffer || dst_bitmap == window)
543 dst_x += video_xoffset;
544 dst_y += video_yoffset;
552 if (src_bitmap != backbuffer || dst_bitmap != window)
553 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
554 src_bitmap->surface_masked : src_bitmap->surface),
555 &src_rect, real_dst_bitmap->surface, &dst_rect);
557 #if defined(TARGET_SDL2)
558 if (dst_bitmap == window)
560 // SDL_UpdateWindowSurface(sdl_window);
561 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
562 UpdateScreen(&dst_rect);
565 if (dst_bitmap == window)
566 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
570 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
573 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
576 if (dst_bitmap == backbuffer || dst_bitmap == window)
587 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
589 #if defined(TARGET_SDL2)
590 if (dst_bitmap == window)
592 // SDL_UpdateWindowSurface(sdl_window);
593 // SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
597 if (dst_bitmap == window)
598 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
602 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
603 int fade_mode, int fade_delay, int post_delay,
604 void (*draw_border_function)(void))
606 static boolean initialization_needed = TRUE;
607 static SDL_Surface *surface_source = NULL;
608 static SDL_Surface *surface_target = NULL;
609 static SDL_Surface *surface_black = NULL;
610 SDL_Surface *surface_screen = backbuffer->surface;
611 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
612 SDL_Rect src_rect, dst_rect;
613 #if defined(TARGET_SDL2)
616 int src_x = x, src_y = y;
617 int dst_x = x, dst_y = y;
618 unsigned int time_last, time_current;
620 /* check if screen size has changed */
621 if (surface_source != NULL && (video.width != surface_source->w ||
622 video.height != surface_source->h))
624 SDL_FreeSurface(surface_source);
625 SDL_FreeSurface(surface_target);
626 SDL_FreeSurface(surface_black);
628 initialization_needed = TRUE;
636 dst_x += video_xoffset;
637 dst_y += video_yoffset;
641 dst_rect.w = width; /* (ignored) */
642 dst_rect.h = height; /* (ignored) */
644 #if defined(TARGET_SDL2)
645 dst_rect2 = dst_rect;
648 if (initialization_needed)
650 #if defined(TARGET_SDL2)
651 unsigned int flags = 0;
653 unsigned int flags = SDL_SRCALPHA;
655 /* use same surface type as screen surface */
656 if ((surface_screen->flags & SDL_HWSURFACE))
657 flags |= SDL_HWSURFACE;
659 flags |= SDL_SWSURFACE;
662 /* create surface for temporary copy of screen buffer (source) */
663 if ((surface_source =
664 SDL_CreateRGBSurface(flags,
667 surface_screen->format->BitsPerPixel,
668 surface_screen->format->Rmask,
669 surface_screen->format->Gmask,
670 surface_screen->format->Bmask,
671 surface_screen->format->Amask)) == NULL)
672 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
674 /* create surface for cross-fading screen buffer (target) */
675 if ((surface_target =
676 SDL_CreateRGBSurface(flags,
679 surface_screen->format->BitsPerPixel,
680 surface_screen->format->Rmask,
681 surface_screen->format->Gmask,
682 surface_screen->format->Bmask,
683 surface_screen->format->Amask)) == NULL)
684 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
686 /* create black surface for fading from/to black */
688 SDL_CreateRGBSurface(flags,
691 surface_screen->format->BitsPerPixel,
692 surface_screen->format->Rmask,
693 surface_screen->format->Gmask,
694 surface_screen->format->Bmask,
695 surface_screen->format->Amask)) == NULL)
696 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
698 /* completely fill the surface with black color pixels */
699 SDL_FillRect(surface_black, NULL,
700 SDL_MapRGB(surface_screen->format, 0, 0, 0));
702 initialization_needed = FALSE;
705 /* copy source and target surfaces to temporary surfaces for fading */
706 if (fade_mode & FADE_TYPE_TRANSFORM)
708 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
709 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
711 else if (fade_mode & FADE_TYPE_FADE_IN)
713 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
714 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
716 else /* FADE_TYPE_FADE_OUT */
718 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
719 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
722 time_current = SDL_GetTicks();
724 if (fade_mode == FADE_MODE_MELT)
726 boolean done = FALSE;
728 int melt_columns = width / melt_pixels;
729 int ypos[melt_columns];
730 int max_steps = height / 8 + 32;
735 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
736 #if defined(TARGET_SDL2)
737 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
739 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
742 ypos[0] = -GetSimpleRandom(16);
744 for (i = 1 ; i < melt_columns; i++)
746 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
748 ypos[i] = ypos[i - 1] + r;
761 time_last = time_current;
762 time_current = SDL_GetTicks();
763 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
764 steps_final = MIN(MAX(0, steps), max_steps);
768 done = (steps_done >= steps_final);
770 for (i = 0 ; i < melt_columns; i++)
778 else if (ypos[i] < height)
783 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
785 if (ypos[i] + dy >= height)
786 dy = height - ypos[i];
788 /* copy part of (appearing) target surface to upper area */
789 src_rect.x = src_x + i * melt_pixels;
790 // src_rect.y = src_y + ypos[i];
792 src_rect.w = melt_pixels;
794 src_rect.h = ypos[i] + dy;
796 dst_rect.x = dst_x + i * melt_pixels;
797 // dst_rect.y = dst_y + ypos[i];
800 if (steps_done >= steps_final)
801 SDL_BlitSurface(surface_target, &src_rect,
802 surface_screen, &dst_rect);
806 /* copy part of (disappearing) source surface to lower area */
807 src_rect.x = src_x + i * melt_pixels;
809 src_rect.w = melt_pixels;
810 src_rect.h = height - ypos[i];
812 dst_rect.x = dst_x + i * melt_pixels;
813 dst_rect.y = dst_y + ypos[i];
815 if (steps_done >= steps_final)
816 SDL_BlitSurface(surface_source, &src_rect,
817 surface_screen, &dst_rect);
823 src_rect.x = src_x + i * melt_pixels;
825 src_rect.w = melt_pixels;
828 dst_rect.x = dst_x + i * melt_pixels;
831 if (steps_done >= steps_final)
832 SDL_BlitSurface(surface_target, &src_rect,
833 surface_screen, &dst_rect);
837 if (steps_done >= steps_final)
839 if (draw_border_function != NULL)
840 draw_border_function();
842 #if defined(TARGET_SDL2)
843 // SDL_UpdateWindowSurface(sdl_window);
844 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
845 UpdateScreen(&dst_rect2);
847 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
857 for (alpha = 0.0; alpha < 255.0;)
859 time_last = time_current;
860 time_current = SDL_GetTicks();
861 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
862 alpha_final = MIN(MAX(0, alpha), 255);
864 /* draw existing (source) image to screen buffer */
865 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
867 /* draw new (target) image to screen buffer using alpha blending */
868 #if defined(TARGET_SDL2)
869 SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
870 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
872 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
874 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
876 if (draw_border_function != NULL)
877 draw_border_function();
880 /* only update the region of the screen that is affected from fading */
881 #if defined(TARGET_SDL2)
882 // SDL_UpdateWindowSurface(sdl_window);
883 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
884 UpdateScreen(&dst_rect);
886 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
889 SDL_Flip(surface_screen);
897 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
898 int to_x, int to_y, Uint32 color)
900 SDL_Surface *surface = dst_bitmap->surface;
904 swap_numbers(&from_x, &to_x);
907 swap_numbers(&from_y, &to_y);
911 rect.w = (to_x - from_x + 1);
912 rect.h = (to_y - from_y + 1);
914 if (dst_bitmap == backbuffer || dst_bitmap == window)
916 rect.x += video_xoffset;
917 rect.y += video_yoffset;
920 SDL_FillRect(surface, &rect, color);
923 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
924 int to_x, int to_y, Uint32 color)
926 if (dst_bitmap == backbuffer || dst_bitmap == window)
928 from_x += video_xoffset;
929 from_y += video_yoffset;
930 to_x += video_xoffset;
931 to_y += video_yoffset;
934 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
938 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
939 int num_points, Uint32 color)
944 for (i = 0; i < num_points - 1; i++)
946 for (x = 0; x < line_width; x++)
948 for (y = 0; y < line_width; y++)
950 int dx = x - line_width / 2;
951 int dy = y - line_width / 2;
953 if ((x == 0 && y == 0) ||
954 (x == 0 && y == line_width - 1) ||
955 (x == line_width - 1 && y == 0) ||
956 (x == line_width - 1 && y == line_width - 1))
959 sge_Line(surface, points[i].x + dx, points[i].y + dy,
960 points[i+1].x + dx, points[i+1].y + dy, color);
967 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
969 SDL_Surface *surface = src_bitmap->surface;
971 if (src_bitmap == backbuffer || src_bitmap == window)
977 switch (surface->format->BytesPerPixel)
979 case 1: /* assuming 8-bpp */
981 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
985 case 2: /* probably 15-bpp or 16-bpp */
987 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
991 case 3: /* slow 24-bpp mode; usually not used */
993 /* does this work? */
994 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
998 shift = surface->format->Rshift;
999 color |= *(pix + shift / 8) >> shift;
1000 shift = surface->format->Gshift;
1001 color |= *(pix + shift / 8) >> shift;
1002 shift = surface->format->Bshift;
1003 color |= *(pix + shift / 8) >> shift;
1009 case 4: /* probably 32-bpp */
1011 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
1020 /* ========================================================================= */
1021 /* The following functions were taken from the SGE library */
1022 /* (SDL Graphics Extension Library) by Anders Lindström */
1023 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
1024 /* ========================================================================= */
1026 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1028 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
1030 switch (surface->format->BytesPerPixel)
1034 /* Assuming 8-bpp */
1035 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1041 /* Probably 15-bpp or 16-bpp */
1042 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1048 /* Slow 24-bpp mode, usually not used */
1052 /* Gack - slow, but endian correct */
1053 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1054 shift = surface->format->Rshift;
1055 *(pix+shift/8) = color>>shift;
1056 shift = surface->format->Gshift;
1057 *(pix+shift/8) = color>>shift;
1058 shift = surface->format->Bshift;
1059 *(pix+shift/8) = color>>shift;
1065 /* Probably 32-bpp */
1066 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1073 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1074 Uint8 R, Uint8 G, Uint8 B)
1076 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
1079 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1081 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1084 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1086 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1089 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1094 /* Gack - slow, but endian correct */
1095 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1096 shift = surface->format->Rshift;
1097 *(pix+shift/8) = color>>shift;
1098 shift = surface->format->Gshift;
1099 *(pix+shift/8) = color>>shift;
1100 shift = surface->format->Bshift;
1101 *(pix+shift/8) = color>>shift;
1104 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1106 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1109 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
1111 switch (dest->format->BytesPerPixel)
1114 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
1118 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
1122 _PutPixel24(dest,x,y,color);
1126 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
1131 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1133 if (SDL_MUSTLOCK(surface))
1135 if (SDL_LockSurface(surface) < 0)
1141 _PutPixel(surface, x, y, color);
1143 if (SDL_MUSTLOCK(surface))
1145 SDL_UnlockSurface(surface);
1149 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1150 Uint8 r, Uint8 g, Uint8 b)
1152 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
1155 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
1157 if (y >= 0 && y <= dest->h - 1)
1159 switch (dest->format->BytesPerPixel)
1162 return y*dest->pitch;
1166 return y*dest->pitch/2;
1170 return y*dest->pitch;
1174 return y*dest->pitch/4;
1182 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
1184 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
1186 switch (surface->format->BytesPerPixel)
1190 /* Assuming 8-bpp */
1191 *((Uint8 *)surface->pixels + ypitch + x) = color;
1197 /* Probably 15-bpp or 16-bpp */
1198 *((Uint16 *)surface->pixels + ypitch + x) = color;
1204 /* Slow 24-bpp mode, usually not used */
1208 /* Gack - slow, but endian correct */
1209 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1210 shift = surface->format->Rshift;
1211 *(pix+shift/8) = color>>shift;
1212 shift = surface->format->Gshift;
1213 *(pix+shift/8) = color>>shift;
1214 shift = surface->format->Bshift;
1215 *(pix+shift/8) = color>>shift;
1221 /* Probably 32-bpp */
1222 *((Uint32 *)surface->pixels + ypitch + x) = color;
1229 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1234 if (SDL_MUSTLOCK(Surface))
1236 if (SDL_LockSurface(Surface) < 0)
1249 /* Do the clipping */
1250 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1254 if (x2 > Surface->w - 1)
1255 x2 = Surface->w - 1;
1262 SDL_FillRect(Surface, &l, Color);
1264 if (SDL_MUSTLOCK(Surface))
1266 SDL_UnlockSurface(Surface);
1270 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1271 Uint8 R, Uint8 G, Uint8 B)
1273 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1276 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1287 /* Do the clipping */
1288 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1292 if (x2 > Surface->w - 1)
1293 x2 = Surface->w - 1;
1300 SDL_FillRect(Surface, &l, Color);
1303 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1308 if (SDL_MUSTLOCK(Surface))
1310 if (SDL_LockSurface(Surface) < 0)
1323 /* Do the clipping */
1324 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1328 if (y2 > Surface->h - 1)
1329 y2 = Surface->h - 1;
1336 SDL_FillRect(Surface, &l, Color);
1338 if (SDL_MUSTLOCK(Surface))
1340 SDL_UnlockSurface(Surface);
1344 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1345 Uint8 R, Uint8 G, Uint8 B)
1347 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1350 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1361 /* Do the clipping */
1362 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1366 if (y2 > Surface->h - 1)
1367 y2 = Surface->h - 1;
1374 SDL_FillRect(Surface, &l, Color);
1377 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1378 Sint16 x2, Sint16 y2, Uint32 Color,
1379 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1382 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1387 sdx = (dx < 0) ? -1 : 1;
1388 sdy = (dy < 0) ? -1 : 1;
1400 for (x = 0; x < dx; x++)
1402 Callback(Surface, px, py, Color);
1416 for (y = 0; y < dy; y++)
1418 Callback(Surface, px, py, Color);
1432 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
1433 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
1434 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1437 sge_DoLine(Surface, X1, Y1, X2, Y2,
1438 SDL_MapRGB(Surface->format, R, G, B), Callback);
1441 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
1444 if (SDL_MUSTLOCK(Surface))
1446 if (SDL_LockSurface(Surface) < 0)
1451 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
1453 /* unlock the display */
1454 if (SDL_MUSTLOCK(Surface))
1456 SDL_UnlockSurface(Surface);
1460 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
1461 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1463 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
1466 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
1468 if (dst_bitmap == backbuffer || dst_bitmap == window)
1474 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
1479 -----------------------------------------------------------------------------
1480 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
1481 -----------------------------------------------------------------------------
1484 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
1485 int width, int height, Uint32 color)
1489 for (y = src_y; y < src_y + height; y++)
1491 for (x = src_x; x < src_x + width; x++)
1493 Uint32 pixel = SDLGetPixel(bitmap, x, y);
1495 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
1500 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1501 int src_x, int src_y, int width, int height,
1502 int dst_x, int dst_y)
1506 for (y = 0; y < height; y++)
1508 for (x = 0; x < width; x++)
1510 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
1512 if (pixel != BLACK_PIXEL)
1513 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
1519 /* ========================================================================= */
1520 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
1521 /* (Rotozoomer) by Andreas Schiffler */
1522 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
1523 /* ========================================================================= */
1526 -----------------------------------------------------------------------------
1529 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
1530 -----------------------------------------------------------------------------
1541 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
1544 tColorRGBA *sp, *csp, *dp;
1551 sp = csp = (tColorRGBA *) src->pixels;
1552 dp = (tColorRGBA *) dst->pixels;
1554 sgap = src->pitch - src->w * 4;
1556 dgap = dst->pitch - dst->w * 4;
1558 for (y = 0; y < dst->h; y++)
1562 for (x = 0; x < dst->w; x++)
1564 tColorRGBA *sp0 = sp;
1565 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1566 tColorRGBA *sp00 = &sp0[0];
1567 tColorRGBA *sp01 = &sp0[1];
1568 tColorRGBA *sp10 = &sp1[0];
1569 tColorRGBA *sp11 = &sp1[1];
1572 /* create new color pixel from all four source color pixels */
1573 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1574 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1575 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1576 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1581 /* advance source pointers */
1584 /* advance destination pointer */
1588 /* advance source pointer */
1589 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1591 /* advance destination pointers */
1592 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1598 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1600 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1601 tColorRGBA *sp, *csp, *dp;
1607 /* use specialized zoom function when scaling down to exactly half size */
1608 if (src->w == 2 * dst->w &&
1609 src->h == 2 * dst->h)
1610 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1612 /* variable setup */
1613 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1614 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1616 /* allocate memory for row increments */
1617 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1618 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1620 /* precalculate row increments */
1623 for (x = 0; x <= dst->w; x++)
1633 for (y = 0; y <= dst->h; y++)
1642 sp = csp = (tColorRGBA *) src->pixels;
1643 dp = (tColorRGBA *) dst->pixels;
1645 sgap = src->pitch - src->w * 4;
1647 dgap = dst->pitch - dst->w * 4;
1650 for (y = 0; y < dst->h; y++)
1655 for (x = 0; x < dst->w; x++)
1660 /* advance source pointers */
1662 sp += (*csax >> 16);
1664 /* advance destination pointer */
1668 /* advance source pointer */
1670 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1672 /* advance destination pointers */
1673 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1683 -----------------------------------------------------------------------------
1686 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1687 -----------------------------------------------------------------------------
1690 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1692 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1693 Uint8 *sp, *dp, *csp;
1696 /* variable setup */
1697 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1698 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1700 /* allocate memory for row increments */
1701 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1702 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1704 /* precalculate row increments */
1707 for (x = 0; x < dst->w; x++)
1710 *csax = (csx >> 16);
1717 for (y = 0; y < dst->h; y++)
1720 *csay = (csy >> 16);
1727 for (x = 0; x < dst->w; x++)
1735 for (y = 0; y < dst->h; y++)
1742 sp = csp = (Uint8 *) src->pixels;
1743 dp = (Uint8 *) dst->pixels;
1744 dgap = dst->pitch - dst->w;
1748 for (y = 0; y < dst->h; y++)
1752 for (x = 0; x < dst->w; x++)
1757 /* advance source pointers */
1761 /* advance destination pointer */
1765 /* advance source pointer (for row) */
1766 csp += ((*csay) * src->pitch);
1769 /* advance destination pointers */
1780 -----------------------------------------------------------------------------
1783 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1784 'zoomx' and 'zoomy' are scaling factors for width and height.
1785 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1786 into a 32bit RGBA format on the fly.
1787 -----------------------------------------------------------------------------
1790 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1792 SDL_Surface *zoom_src = NULL;
1793 SDL_Surface *zoom_dst = NULL;
1794 boolean is_converted = FALSE;
1801 /* determine if source surface is 32 bit or 8 bit */
1802 is_32bit = (src->format->BitsPerPixel == 32);
1804 if (is_32bit || src->format->BitsPerPixel == 8)
1806 /* use source surface 'as is' */
1811 /* new source surface is 32 bit with a defined RGB ordering */
1812 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1813 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1814 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1816 is_converted = TRUE;
1819 /* allocate surface to completely contain the zoomed surface */
1822 /* target surface is 32 bit with source RGBA/ABGR ordering */
1823 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1824 zoom_src->format->Rmask,
1825 zoom_src->format->Gmask,
1826 zoom_src->format->Bmask, 0);
1830 /* target surface is 8 bit */
1831 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1835 /* lock source surface */
1836 SDL_LockSurface(zoom_src);
1838 /* check which kind of surface we have */
1841 /* call the 32 bit transformation routine to do the zooming */
1842 zoomSurfaceRGBA(zoom_src, zoom_dst);
1847 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1848 zoom_dst->format->palette->colors[i] =
1849 zoom_src->format->palette->colors[i];
1850 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1852 /* call the 8 bit transformation routine to do the zooming */
1853 zoomSurfaceY(zoom_src, zoom_dst);
1856 /* unlock source surface */
1857 SDL_UnlockSurface(zoom_src);
1859 /* free temporary surface */
1861 SDL_FreeSurface(zoom_src);
1863 /* return destination surface */
1867 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1869 SDL_Surface *sdl_surface_tmp;
1870 int dst_width = dst_bitmap->width;
1871 int dst_height = dst_bitmap->height;
1873 /* throw away old destination surface */
1874 SDL_FreeSurface(dst_bitmap->surface);
1876 /* create zoomed temporary surface from source surface */
1877 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1879 /* create native format destination surface from zoomed temporary surface */
1880 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1882 /* free temporary surface */
1883 SDL_FreeSurface(sdl_surface_tmp);
1887 /* ========================================================================= */
1888 /* load image to bitmap */
1889 /* ========================================================================= */
1891 Bitmap *SDLLoadImage(char *filename)
1893 Bitmap *new_bitmap = CreateBitmapStruct();
1894 SDL_Surface *sdl_image_tmp;
1896 print_timestamp_init("SDLLoadImage");
1898 print_timestamp_time(getBaseNamePtr(filename));
1900 /* load image to temporary surface */
1901 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1903 SetError("IMG_Load(): %s", SDL_GetError());
1908 print_timestamp_time("IMG_Load");
1910 UPDATE_BUSY_STATE();
1912 /* create native non-transparent surface for current image */
1913 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1915 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1920 print_timestamp_time("SDL_DisplayFormat (opaque)");
1922 UPDATE_BUSY_STATE();
1924 /* create native transparent surface for current image */
1925 SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
1926 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1927 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1929 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1934 print_timestamp_time("SDL_DisplayFormat (masked)");
1936 UPDATE_BUSY_STATE();
1938 /* free temporary surface */
1939 SDL_FreeSurface(sdl_image_tmp);
1941 new_bitmap->width = new_bitmap->surface->w;
1942 new_bitmap->height = new_bitmap->surface->h;
1944 print_timestamp_done("SDLLoadImage");
1950 /* ------------------------------------------------------------------------- */
1951 /* custom cursor fuctions */
1952 /* ------------------------------------------------------------------------- */
1954 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1956 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1957 cursor_info->width, cursor_info->height,
1958 cursor_info->hot_x, cursor_info->hot_y);
1961 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1963 static struct MouseCursorInfo *last_cursor_info = NULL;
1964 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1965 static SDL_Cursor *cursor_default = NULL;
1966 static SDL_Cursor *cursor_current = NULL;
1968 /* if invoked for the first time, store the SDL default cursor */
1969 if (cursor_default == NULL)
1970 cursor_default = SDL_GetCursor();
1972 /* only create new cursor if cursor info (custom only) has changed */
1973 if (cursor_info != NULL && cursor_info != last_cursor_info)
1975 cursor_current = create_cursor(cursor_info);
1976 last_cursor_info = cursor_info;
1979 /* only set new cursor if cursor info (custom or NULL) has changed */
1980 if (cursor_info != last_cursor_info2)
1981 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1983 last_cursor_info2 = cursor_info;
1987 /* ========================================================================= */
1988 /* audio functions */
1989 /* ========================================================================= */
1991 void SDLOpenAudio(void)
1993 #if !defined(TARGET_SDL2)
1994 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1995 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1998 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
2000 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
2004 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
2005 AUDIO_NUM_CHANNELS_STEREO,
2006 setup.system.audio_fragment_size) < 0)
2008 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
2012 audio.sound_available = TRUE;
2013 audio.music_available = TRUE;
2014 audio.loops_available = TRUE;
2015 audio.sound_enabled = TRUE;
2017 /* set number of available mixer channels */
2018 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
2019 audio.music_channel = MUSIC_CHANNEL;
2020 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
2022 Mixer_InitChannels();
2025 void SDLCloseAudio(void)
2028 Mix_HaltChannel(-1);
2031 SDL_QuitSubSystem(SDL_INIT_AUDIO);
2035 /* ========================================================================= */
2036 /* event functions */
2037 /* ========================================================================= */
2039 void SDLNextEvent(Event *event)
2041 SDL_WaitEvent(event);
2043 if (event->type == EVENT_BUTTONPRESS ||
2044 event->type == EVENT_BUTTONRELEASE)
2046 if (((ButtonEvent *)event)->x > video_xoffset)
2047 ((ButtonEvent *)event)->x -= video_xoffset;
2049 ((ButtonEvent *)event)->x = 0;
2050 if (((ButtonEvent *)event)->y > video_yoffset)
2051 ((ButtonEvent *)event)->y -= video_yoffset;
2053 ((ButtonEvent *)event)->y = 0;
2055 else if (event->type == EVENT_MOTIONNOTIFY)
2057 if (((MotionEvent *)event)->x > video_xoffset)
2058 ((MotionEvent *)event)->x -= video_xoffset;
2060 ((MotionEvent *)event)->x = 0;
2061 if (((MotionEvent *)event)->y > video_yoffset)
2062 ((MotionEvent *)event)->y -= video_yoffset;
2064 ((MotionEvent *)event)->y = 0;
2068 void SDLHandleWindowManagerEvent(Event *event)
2070 #if defined(PLATFORM_WIN32)
2071 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
2072 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
2074 if (syswmmsg->msg == WM_DROPFILES)
2076 HDROP hdrop = (HDROP)syswmmsg->wParam;
2079 printf("::: SDL_SYSWMEVENT:\n");
2081 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
2083 for (i = 0; i < num_files; i++)
2085 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
2086 char buffer[buffer_len + 1];
2088 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
2090 printf("::: - '%s'\n", buffer);
2093 DragFinish((HDROP)syswmmsg->wParam);
2099 /* ========================================================================= */
2100 /* joystick functions */
2101 /* ========================================================================= */
2103 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
2104 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2105 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2107 static boolean SDLOpenJoystick(int nr)
2109 if (nr < 0 || nr > MAX_PLAYERS)
2112 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
2115 static void SDLCloseJoystick(int nr)
2117 if (nr < 0 || nr > MAX_PLAYERS)
2120 SDL_JoystickClose(sdl_joystick[nr]);
2122 sdl_joystick[nr] = NULL;
2125 static boolean SDLCheckJoystickOpened(int nr)
2127 if (nr < 0 || nr > MAX_PLAYERS)
2130 #if defined(TARGET_SDL2)
2131 return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
2133 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
2137 void HandleJoystickEvent(Event *event)
2141 case SDL_JOYAXISMOTION:
2142 if (event->jaxis.axis < 2)
2143 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
2146 case SDL_JOYBUTTONDOWN:
2147 if (event->jbutton.button < 2)
2148 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
2151 case SDL_JOYBUTTONUP:
2152 if (event->jbutton.button < 2)
2153 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
2161 void SDLInitJoysticks()
2163 static boolean sdl_joystick_subsystem_initialized = FALSE;
2164 boolean print_warning = !sdl_joystick_subsystem_initialized;
2167 if (!sdl_joystick_subsystem_initialized)
2169 sdl_joystick_subsystem_initialized = TRUE;
2171 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2173 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
2178 for (i = 0; i < MAX_PLAYERS; i++)
2180 /* get configured joystick for this player */
2181 char *device_name = setup.input[i].joy.device_name;
2182 int joystick_nr = getJoystickNrFromDeviceName(device_name);
2184 if (joystick_nr >= SDL_NumJoysticks())
2186 if (setup.input[i].use_joystick && print_warning)
2187 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
2192 /* misuse joystick file descriptor variable to store joystick number */
2193 joystick.fd[i] = joystick_nr;
2195 if (joystick_nr == -1)
2198 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
2199 if (SDLCheckJoystickOpened(joystick_nr))
2200 SDLCloseJoystick(joystick_nr);
2202 if (!setup.input[i].use_joystick)
2205 if (!SDLOpenJoystick(joystick_nr))
2208 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
2213 joystick.status = JOYSTICK_ACTIVATED;
2217 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
2219 if (nr < 0 || nr >= MAX_PLAYERS)
2223 *x = sdl_js_axis[nr][0];
2225 *y = sdl_js_axis[nr][1];
2228 *b1 = sdl_js_button[nr][0];
2230 *b2 = sdl_js_button[nr][1];
2235 #endif /* TARGET_SDL */