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 /* set window icon */
275 SDLSetWindowIcon(program.sdl_icon_filename);
278 /* set window and icon title */
279 #if defined(TARGET_SDL2)
280 SDL_SetWindowTitle(sdl_window, program.window_title);
282 SDL_WM_SetCaption(program.window_title, program.window_title);
285 /* SDL cannot directly draw to the visible video framebuffer like X11,
286 but always uses a backbuffer, which is then blitted to the visible
287 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
288 visible video framebuffer with 'SDL_Flip', if the hardware supports
289 this). Therefore do not use an additional backbuffer for drawing, but
290 use a symbolic buffer (distinguishable from the SDL backbuffer) called
291 'window', which indicates that the SDL backbuffer should be updated to
292 the visible video framebuffer when attempting to blit to it.
294 For convenience, it seems to be a good idea to create this symbolic
295 buffer 'window' at the same size as the SDL backbuffer. Although it
296 should never be drawn to directly, it would do no harm nevertheless. */
298 /* create additional (symbolic) buffer for double-buffering */
300 ReCreateBitmap(window, video.width, video.height, video.depth);
302 *window = CreateBitmap(video.width, video.height, video.depth);
306 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
308 boolean success = TRUE;
309 #if defined(TARGET_SDL2)
310 // int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
311 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
312 int surface_flags_window = SURFACE_FLAGS;
314 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
315 int surface_flags_window = SURFACE_FLAGS;
317 SDL_Surface *new_surface = NULL;
319 if (*backbuffer == NULL)
320 *backbuffer = CreateBitmapStruct();
322 /* (real bitmap might be larger in fullscreen mode with video offsets) */
323 (*backbuffer)->width = video.width;
324 (*backbuffer)->height = video.height;
326 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
328 setFullscreenParameters(setup.fullscreen_mode);
330 video_xoffset = fullscreen_xoffset;
331 video_yoffset = fullscreen_yoffset;
333 /* switch display to fullscreen mode, if available */
334 #if defined(TARGET_SDL2)
335 sdl_window = SDL_CreateWindow(program.window_title,
336 SDL_WINDOWPOS_CENTERED,
337 SDL_WINDOWPOS_CENTERED,
338 fullscreen_width, fullscreen_height,
339 surface_flags_fullscreen);
340 if (sdl_window != NULL)
342 new_surface = SDL_GetWindowSurface(sdl_window);
344 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
345 UpdateScreen(NULL); // immediately map window
348 new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
349 video.depth, surface_flags_fullscreen);
352 if (new_surface == NULL)
354 /* switching display to fullscreen mode failed */
355 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
357 /* do not try it again */
358 video.fullscreen_available = FALSE;
364 (*backbuffer)->surface = new_surface;
366 video.fullscreen_enabled = TRUE;
367 video.fullscreen_mode_current = setup.fullscreen_mode;
373 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
378 /* switch display to window mode */
379 #if defined(TARGET_SDL2)
382 float scale_factor = 1;
383 int test_fullscreen = 0;
384 int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
385 surface_flags_window);
387 sdl_window = SDL_CreateWindow(program.window_title,
388 SDL_WINDOWPOS_CENTERED,
389 SDL_WINDOWPOS_CENTERED,
390 (int)(scale_factor * video.width),
391 (int)(scale_factor * video.height),
394 if (sdl_window != NULL)
396 sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
398 if (sdl_renderer != NULL)
400 SDL_RenderSetLogicalSize(sdl_renderer, video.width, video.height);
401 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
403 sdl_texture = SDL_CreateTexture(sdl_renderer,
404 SDL_PIXELFORMAT_ARGB8888,
405 SDL_TEXTUREACCESS_STREAMING,
406 video.width, video.height);
408 if (sdl_texture != NULL)
410 new_surface = SDL_CreateRGBSurface(0, video.width, video.height, 32,
416 if (new_surface == NULL)
417 Error(ERR_WARN, "SDL_CreateRGBSurface() failed: %s",
422 Error(ERR_WARN, "SDL_CreateTexture() failed: %s", SDL_GetError());
427 Error(ERR_WARN, "SDL_CreateRenderer() failed: %s", SDL_GetError());
432 Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
435 sdl_window = SDL_CreateWindow(program.window_title,
436 SDL_WINDOWPOS_CENTERED,
437 SDL_WINDOWPOS_CENTERED,
438 video.width, video.height,
439 surface_flags_window);
441 if (sdl_window != NULL)
443 new_surface = SDL_GetWindowSurface(sdl_window);
445 // SDL_UpdateWindowSurface(sdl_window); // immediately map window
446 UpdateScreen(NULL); // immediately map window
451 new_surface = SDL_SetVideoMode(video.width, video.height,
452 video.depth, surface_flags_window);
455 if (new_surface == NULL)
457 /* switching display to window mode failed -- should not happen */
458 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
464 (*backbuffer)->surface = new_surface;
466 video.fullscreen_enabled = FALSE;
473 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
475 #if defined(PLATFORM_WIN32)
477 SDL_SysWMinfo wminfo;
480 SDL_VERSION(&wminfo.version);
481 SDL_GetWMInfo(&wminfo);
483 hwnd = wminfo.window;
485 DragAcceptFiles(hwnd, TRUE);
494 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
497 SDL_Surface *surface_tmp, *surface_native;
499 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
502 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
504 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
505 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
507 SDL_FreeSurface(surface_tmp);
509 new_bitmap->surface = surface_native;
512 void SDLFreeBitmapPointers(Bitmap *bitmap)
515 SDL_FreeSurface(bitmap->surface);
516 if (bitmap->surface_masked)
517 SDL_FreeSurface(bitmap->surface_masked);
518 bitmap->surface = NULL;
519 bitmap->surface_masked = NULL;
522 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
523 int src_x, int src_y, int width, int height,
524 int dst_x, int dst_y, int mask_mode)
526 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
527 SDL_Rect src_rect, dst_rect;
529 if (src_bitmap == backbuffer)
531 src_x += video_xoffset;
532 src_y += video_yoffset;
540 if (dst_bitmap == backbuffer || dst_bitmap == window)
542 dst_x += video_xoffset;
543 dst_y += video_yoffset;
551 if (src_bitmap != backbuffer || dst_bitmap != window)
552 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
553 src_bitmap->surface_masked : src_bitmap->surface),
554 &src_rect, real_dst_bitmap->surface, &dst_rect);
556 #if defined(TARGET_SDL2)
557 if (dst_bitmap == window)
559 // SDL_UpdateWindowSurface(sdl_window);
560 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
561 UpdateScreen(&dst_rect);
564 if (dst_bitmap == window)
565 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
569 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
572 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
575 if (dst_bitmap == backbuffer || dst_bitmap == window)
586 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
588 #if defined(TARGET_SDL2)
589 if (dst_bitmap == window)
591 // SDL_UpdateWindowSurface(sdl_window);
592 // SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
596 if (dst_bitmap == window)
597 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
601 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
602 int fade_mode, int fade_delay, int post_delay,
603 void (*draw_border_function)(void))
605 static boolean initialization_needed = TRUE;
606 static SDL_Surface *surface_source = NULL;
607 static SDL_Surface *surface_target = NULL;
608 static SDL_Surface *surface_black = NULL;
609 SDL_Surface *surface_screen = backbuffer->surface;
610 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
611 SDL_Rect src_rect, dst_rect;
612 #if defined(TARGET_SDL2)
615 int src_x = x, src_y = y;
616 int dst_x = x, dst_y = y;
617 unsigned int time_last, time_current;
619 /* check if screen size has changed */
620 if (surface_source != NULL && (video.width != surface_source->w ||
621 video.height != surface_source->h))
623 SDL_FreeSurface(surface_source);
624 SDL_FreeSurface(surface_target);
625 SDL_FreeSurface(surface_black);
627 initialization_needed = TRUE;
635 dst_x += video_xoffset;
636 dst_y += video_yoffset;
640 dst_rect.w = width; /* (ignored) */
641 dst_rect.h = height; /* (ignored) */
643 #if defined(TARGET_SDL2)
644 dst_rect2 = dst_rect;
647 if (initialization_needed)
649 #if defined(TARGET_SDL2)
650 unsigned int flags = 0;
652 unsigned int flags = SDL_SRCALPHA;
654 /* use same surface type as screen surface */
655 if ((surface_screen->flags & SDL_HWSURFACE))
656 flags |= SDL_HWSURFACE;
658 flags |= SDL_SWSURFACE;
661 /* create surface for temporary copy of screen buffer (source) */
662 if ((surface_source =
663 SDL_CreateRGBSurface(flags,
666 surface_screen->format->BitsPerPixel,
667 surface_screen->format->Rmask,
668 surface_screen->format->Gmask,
669 surface_screen->format->Bmask,
670 surface_screen->format->Amask)) == NULL)
671 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
673 /* create surface for cross-fading screen buffer (target) */
674 if ((surface_target =
675 SDL_CreateRGBSurface(flags,
678 surface_screen->format->BitsPerPixel,
679 surface_screen->format->Rmask,
680 surface_screen->format->Gmask,
681 surface_screen->format->Bmask,
682 surface_screen->format->Amask)) == NULL)
683 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
685 /* create black surface for fading from/to black */
687 SDL_CreateRGBSurface(flags,
690 surface_screen->format->BitsPerPixel,
691 surface_screen->format->Rmask,
692 surface_screen->format->Gmask,
693 surface_screen->format->Bmask,
694 surface_screen->format->Amask)) == NULL)
695 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
697 /* completely fill the surface with black color pixels */
698 SDL_FillRect(surface_black, NULL,
699 SDL_MapRGB(surface_screen->format, 0, 0, 0));
701 initialization_needed = FALSE;
704 /* copy source and target surfaces to temporary surfaces for fading */
705 if (fade_mode & FADE_TYPE_TRANSFORM)
707 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
708 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
710 else if (fade_mode & FADE_TYPE_FADE_IN)
712 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
713 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
715 else /* FADE_TYPE_FADE_OUT */
717 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
718 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
721 time_current = SDL_GetTicks();
723 if (fade_mode == FADE_MODE_MELT)
725 boolean done = FALSE;
727 int melt_columns = width / melt_pixels;
728 int ypos[melt_columns];
729 int max_steps = height / 8 + 32;
734 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
735 #if defined(TARGET_SDL2)
736 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
738 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
741 ypos[0] = -GetSimpleRandom(16);
743 for (i = 1 ; i < melt_columns; i++)
745 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
747 ypos[i] = ypos[i - 1] + r;
760 time_last = time_current;
761 time_current = SDL_GetTicks();
762 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
763 steps_final = MIN(MAX(0, steps), max_steps);
767 done = (steps_done >= steps_final);
769 for (i = 0 ; i < melt_columns; i++)
777 else if (ypos[i] < height)
782 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
784 if (ypos[i] + dy >= height)
785 dy = height - ypos[i];
787 /* copy part of (appearing) target surface to upper area */
788 src_rect.x = src_x + i * melt_pixels;
789 // src_rect.y = src_y + ypos[i];
791 src_rect.w = melt_pixels;
793 src_rect.h = ypos[i] + dy;
795 dst_rect.x = dst_x + i * melt_pixels;
796 // dst_rect.y = dst_y + ypos[i];
799 if (steps_done >= steps_final)
800 SDL_BlitSurface(surface_target, &src_rect,
801 surface_screen, &dst_rect);
805 /* copy part of (disappearing) source surface to lower area */
806 src_rect.x = src_x + i * melt_pixels;
808 src_rect.w = melt_pixels;
809 src_rect.h = height - ypos[i];
811 dst_rect.x = dst_x + i * melt_pixels;
812 dst_rect.y = dst_y + ypos[i];
814 if (steps_done >= steps_final)
815 SDL_BlitSurface(surface_source, &src_rect,
816 surface_screen, &dst_rect);
822 src_rect.x = src_x + i * melt_pixels;
824 src_rect.w = melt_pixels;
827 dst_rect.x = dst_x + i * melt_pixels;
830 if (steps_done >= steps_final)
831 SDL_BlitSurface(surface_target, &src_rect,
832 surface_screen, &dst_rect);
836 if (steps_done >= steps_final)
838 if (draw_border_function != NULL)
839 draw_border_function();
841 #if defined(TARGET_SDL2)
842 // SDL_UpdateWindowSurface(sdl_window);
843 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
844 UpdateScreen(&dst_rect2);
846 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
856 for (alpha = 0.0; alpha < 255.0;)
858 time_last = time_current;
859 time_current = SDL_GetTicks();
860 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
861 alpha_final = MIN(MAX(0, alpha), 255);
863 /* draw existing (source) image to screen buffer */
864 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
866 /* draw new (target) image to screen buffer using alpha blending */
867 #if defined(TARGET_SDL2)
868 SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
869 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
871 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
873 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
875 if (draw_border_function != NULL)
876 draw_border_function();
879 /* only update the region of the screen that is affected from fading */
880 #if defined(TARGET_SDL2)
881 // SDL_UpdateWindowSurface(sdl_window);
882 // SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
883 UpdateScreen(&dst_rect);
885 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
888 SDL_Flip(surface_screen);
896 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
897 int to_x, int to_y, Uint32 color)
899 SDL_Surface *surface = dst_bitmap->surface;
903 swap_numbers(&from_x, &to_x);
906 swap_numbers(&from_y, &to_y);
910 rect.w = (to_x - from_x + 1);
911 rect.h = (to_y - from_y + 1);
913 if (dst_bitmap == backbuffer || dst_bitmap == window)
915 rect.x += video_xoffset;
916 rect.y += video_yoffset;
919 SDL_FillRect(surface, &rect, color);
922 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
923 int to_x, int to_y, Uint32 color)
925 if (dst_bitmap == backbuffer || dst_bitmap == window)
927 from_x += video_xoffset;
928 from_y += video_yoffset;
929 to_x += video_xoffset;
930 to_y += video_yoffset;
933 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
937 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
938 int num_points, Uint32 color)
943 for (i = 0; i < num_points - 1; i++)
945 for (x = 0; x < line_width; x++)
947 for (y = 0; y < line_width; y++)
949 int dx = x - line_width / 2;
950 int dy = y - line_width / 2;
952 if ((x == 0 && y == 0) ||
953 (x == 0 && y == line_width - 1) ||
954 (x == line_width - 1 && y == 0) ||
955 (x == line_width - 1 && y == line_width - 1))
958 sge_Line(surface, points[i].x + dx, points[i].y + dy,
959 points[i+1].x + dx, points[i+1].y + dy, color);
966 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
968 SDL_Surface *surface = src_bitmap->surface;
970 if (src_bitmap == backbuffer || src_bitmap == window)
976 switch (surface->format->BytesPerPixel)
978 case 1: /* assuming 8-bpp */
980 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
984 case 2: /* probably 15-bpp or 16-bpp */
986 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
990 case 3: /* slow 24-bpp mode; usually not used */
992 /* does this work? */
993 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
997 shift = surface->format->Rshift;
998 color |= *(pix + shift / 8) >> shift;
999 shift = surface->format->Gshift;
1000 color |= *(pix + shift / 8) >> shift;
1001 shift = surface->format->Bshift;
1002 color |= *(pix + shift / 8) >> shift;
1008 case 4: /* probably 32-bpp */
1010 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
1019 /* ========================================================================= */
1020 /* The following functions were taken from the SGE library */
1021 /* (SDL Graphics Extension Library) by Anders Lindström */
1022 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
1023 /* ========================================================================= */
1025 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1027 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
1029 switch (surface->format->BytesPerPixel)
1033 /* Assuming 8-bpp */
1034 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1040 /* Probably 15-bpp or 16-bpp */
1041 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1047 /* Slow 24-bpp mode, usually not used */
1051 /* Gack - slow, but endian correct */
1052 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1053 shift = surface->format->Rshift;
1054 *(pix+shift/8) = color>>shift;
1055 shift = surface->format->Gshift;
1056 *(pix+shift/8) = color>>shift;
1057 shift = surface->format->Bshift;
1058 *(pix+shift/8) = color>>shift;
1064 /* Probably 32-bpp */
1065 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1072 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1073 Uint8 R, Uint8 G, Uint8 B)
1075 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
1078 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1080 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1083 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1085 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1088 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1093 /* Gack - slow, but endian correct */
1094 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1095 shift = surface->format->Rshift;
1096 *(pix+shift/8) = color>>shift;
1097 shift = surface->format->Gshift;
1098 *(pix+shift/8) = color>>shift;
1099 shift = surface->format->Bshift;
1100 *(pix+shift/8) = color>>shift;
1103 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1105 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1108 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
1110 switch (dest->format->BytesPerPixel)
1113 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
1117 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
1121 _PutPixel24(dest,x,y,color);
1125 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
1130 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1132 if (SDL_MUSTLOCK(surface))
1134 if (SDL_LockSurface(surface) < 0)
1140 _PutPixel(surface, x, y, color);
1142 if (SDL_MUSTLOCK(surface))
1144 SDL_UnlockSurface(surface);
1148 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1149 Uint8 r, Uint8 g, Uint8 b)
1151 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
1154 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
1156 if (y >= 0 && y <= dest->h - 1)
1158 switch (dest->format->BytesPerPixel)
1161 return y*dest->pitch;
1165 return y*dest->pitch/2;
1169 return y*dest->pitch;
1173 return y*dest->pitch/4;
1181 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
1183 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
1185 switch (surface->format->BytesPerPixel)
1189 /* Assuming 8-bpp */
1190 *((Uint8 *)surface->pixels + ypitch + x) = color;
1196 /* Probably 15-bpp or 16-bpp */
1197 *((Uint16 *)surface->pixels + ypitch + x) = color;
1203 /* Slow 24-bpp mode, usually not used */
1207 /* Gack - slow, but endian correct */
1208 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1209 shift = surface->format->Rshift;
1210 *(pix+shift/8) = color>>shift;
1211 shift = surface->format->Gshift;
1212 *(pix+shift/8) = color>>shift;
1213 shift = surface->format->Bshift;
1214 *(pix+shift/8) = color>>shift;
1220 /* Probably 32-bpp */
1221 *((Uint32 *)surface->pixels + ypitch + x) = color;
1228 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1233 if (SDL_MUSTLOCK(Surface))
1235 if (SDL_LockSurface(Surface) < 0)
1248 /* Do the clipping */
1249 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1253 if (x2 > Surface->w - 1)
1254 x2 = Surface->w - 1;
1261 SDL_FillRect(Surface, &l, Color);
1263 if (SDL_MUSTLOCK(Surface))
1265 SDL_UnlockSurface(Surface);
1269 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1270 Uint8 R, Uint8 G, Uint8 B)
1272 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1275 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1286 /* Do the clipping */
1287 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1291 if (x2 > Surface->w - 1)
1292 x2 = Surface->w - 1;
1299 SDL_FillRect(Surface, &l, Color);
1302 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1307 if (SDL_MUSTLOCK(Surface))
1309 if (SDL_LockSurface(Surface) < 0)
1322 /* Do the clipping */
1323 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1327 if (y2 > Surface->h - 1)
1328 y2 = Surface->h - 1;
1335 SDL_FillRect(Surface, &l, Color);
1337 if (SDL_MUSTLOCK(Surface))
1339 SDL_UnlockSurface(Surface);
1343 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1344 Uint8 R, Uint8 G, Uint8 B)
1346 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1349 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1360 /* Do the clipping */
1361 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1365 if (y2 > Surface->h - 1)
1366 y2 = Surface->h - 1;
1373 SDL_FillRect(Surface, &l, Color);
1376 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1377 Sint16 x2, Sint16 y2, Uint32 Color,
1378 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1381 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1386 sdx = (dx < 0) ? -1 : 1;
1387 sdy = (dy < 0) ? -1 : 1;
1399 for (x = 0; x < dx; x++)
1401 Callback(Surface, px, py, Color);
1415 for (y = 0; y < dy; y++)
1417 Callback(Surface, px, py, Color);
1431 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
1432 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
1433 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1436 sge_DoLine(Surface, X1, Y1, X2, Y2,
1437 SDL_MapRGB(Surface->format, R, G, B), Callback);
1440 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
1443 if (SDL_MUSTLOCK(Surface))
1445 if (SDL_LockSurface(Surface) < 0)
1450 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
1452 /* unlock the display */
1453 if (SDL_MUSTLOCK(Surface))
1455 SDL_UnlockSurface(Surface);
1459 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
1460 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1462 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
1465 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
1467 if (dst_bitmap == backbuffer || dst_bitmap == window)
1473 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
1478 -----------------------------------------------------------------------------
1479 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
1480 -----------------------------------------------------------------------------
1483 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
1484 int width, int height, Uint32 color)
1488 for (y = src_y; y < src_y + height; y++)
1490 for (x = src_x; x < src_x + width; x++)
1492 Uint32 pixel = SDLGetPixel(bitmap, x, y);
1494 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
1499 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1500 int src_x, int src_y, int width, int height,
1501 int dst_x, int dst_y)
1505 for (y = 0; y < height; y++)
1507 for (x = 0; x < width; x++)
1509 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
1511 if (pixel != BLACK_PIXEL)
1512 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
1518 /* ========================================================================= */
1519 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
1520 /* (Rotozoomer) by Andreas Schiffler */
1521 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
1522 /* ========================================================================= */
1525 -----------------------------------------------------------------------------
1528 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
1529 -----------------------------------------------------------------------------
1540 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
1543 tColorRGBA *sp, *csp, *dp;
1550 sp = csp = (tColorRGBA *) src->pixels;
1551 dp = (tColorRGBA *) dst->pixels;
1553 sgap = src->pitch - src->w * 4;
1555 dgap = dst->pitch - dst->w * 4;
1557 for (y = 0; y < dst->h; y++)
1561 for (x = 0; x < dst->w; x++)
1563 tColorRGBA *sp0 = sp;
1564 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1565 tColorRGBA *sp00 = &sp0[0];
1566 tColorRGBA *sp01 = &sp0[1];
1567 tColorRGBA *sp10 = &sp1[0];
1568 tColorRGBA *sp11 = &sp1[1];
1571 /* create new color pixel from all four source color pixels */
1572 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1573 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1574 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1575 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1580 /* advance source pointers */
1583 /* advance destination pointer */
1587 /* advance source pointer */
1588 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1590 /* advance destination pointers */
1591 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1597 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1599 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1600 tColorRGBA *sp, *csp, *dp;
1606 /* use specialized zoom function when scaling down to exactly half size */
1607 if (src->w == 2 * dst->w &&
1608 src->h == 2 * dst->h)
1609 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1611 /* variable setup */
1612 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1613 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1615 /* allocate memory for row increments */
1616 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1617 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1619 /* precalculate row increments */
1622 for (x = 0; x <= dst->w; x++)
1632 for (y = 0; y <= dst->h; y++)
1641 sp = csp = (tColorRGBA *) src->pixels;
1642 dp = (tColorRGBA *) dst->pixels;
1644 sgap = src->pitch - src->w * 4;
1646 dgap = dst->pitch - dst->w * 4;
1649 for (y = 0; y < dst->h; y++)
1654 for (x = 0; x < dst->w; x++)
1659 /* advance source pointers */
1661 sp += (*csax >> 16);
1663 /* advance destination pointer */
1667 /* advance source pointer */
1669 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1671 /* advance destination pointers */
1672 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1682 -----------------------------------------------------------------------------
1685 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1686 -----------------------------------------------------------------------------
1689 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1691 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1692 Uint8 *sp, *dp, *csp;
1695 /* variable setup */
1696 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1697 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1699 /* allocate memory for row increments */
1700 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1701 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1703 /* precalculate row increments */
1706 for (x = 0; x < dst->w; x++)
1709 *csax = (csx >> 16);
1716 for (y = 0; y < dst->h; y++)
1719 *csay = (csy >> 16);
1726 for (x = 0; x < dst->w; x++)
1734 for (y = 0; y < dst->h; y++)
1741 sp = csp = (Uint8 *) src->pixels;
1742 dp = (Uint8 *) dst->pixels;
1743 dgap = dst->pitch - dst->w;
1747 for (y = 0; y < dst->h; y++)
1751 for (x = 0; x < dst->w; x++)
1756 /* advance source pointers */
1760 /* advance destination pointer */
1764 /* advance source pointer (for row) */
1765 csp += ((*csay) * src->pitch);
1768 /* advance destination pointers */
1779 -----------------------------------------------------------------------------
1782 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1783 'zoomx' and 'zoomy' are scaling factors for width and height.
1784 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1785 into a 32bit RGBA format on the fly.
1786 -----------------------------------------------------------------------------
1789 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1791 SDL_Surface *zoom_src = NULL;
1792 SDL_Surface *zoom_dst = NULL;
1793 boolean is_converted = FALSE;
1800 /* determine if source surface is 32 bit or 8 bit */
1801 is_32bit = (src->format->BitsPerPixel == 32);
1803 if (is_32bit || src->format->BitsPerPixel == 8)
1805 /* use source surface 'as is' */
1810 /* new source surface is 32 bit with a defined RGB ordering */
1811 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1812 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1813 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1815 is_converted = TRUE;
1818 /* allocate surface to completely contain the zoomed surface */
1821 /* target surface is 32 bit with source RGBA/ABGR ordering */
1822 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1823 zoom_src->format->Rmask,
1824 zoom_src->format->Gmask,
1825 zoom_src->format->Bmask, 0);
1829 /* target surface is 8 bit */
1830 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1834 /* lock source surface */
1835 SDL_LockSurface(zoom_src);
1837 /* check which kind of surface we have */
1840 /* call the 32 bit transformation routine to do the zooming */
1841 zoomSurfaceRGBA(zoom_src, zoom_dst);
1846 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1847 zoom_dst->format->palette->colors[i] =
1848 zoom_src->format->palette->colors[i];
1849 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1851 /* call the 8 bit transformation routine to do the zooming */
1852 zoomSurfaceY(zoom_src, zoom_dst);
1855 /* unlock source surface */
1856 SDL_UnlockSurface(zoom_src);
1858 /* free temporary surface */
1860 SDL_FreeSurface(zoom_src);
1862 /* return destination surface */
1866 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1868 SDL_Surface *sdl_surface_tmp;
1869 int dst_width = dst_bitmap->width;
1870 int dst_height = dst_bitmap->height;
1872 /* throw away old destination surface */
1873 SDL_FreeSurface(dst_bitmap->surface);
1875 /* create zoomed temporary surface from source surface */
1876 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1878 /* create native format destination surface from zoomed temporary surface */
1879 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1881 /* free temporary surface */
1882 SDL_FreeSurface(sdl_surface_tmp);
1886 /* ========================================================================= */
1887 /* load image to bitmap */
1888 /* ========================================================================= */
1890 Bitmap *SDLLoadImage(char *filename)
1892 Bitmap *new_bitmap = CreateBitmapStruct();
1893 SDL_Surface *sdl_image_tmp;
1895 print_timestamp_init("SDLLoadImage");
1897 print_timestamp_time(getBaseNamePtr(filename));
1899 /* load image to temporary surface */
1900 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1902 SetError("IMG_Load(): %s", SDL_GetError());
1907 print_timestamp_time("IMG_Load");
1909 UPDATE_BUSY_STATE();
1911 /* create native non-transparent surface for current image */
1912 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1914 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1919 print_timestamp_time("SDL_DisplayFormat (opaque)");
1921 UPDATE_BUSY_STATE();
1923 /* create native transparent surface for current image */
1924 SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
1925 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1926 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1928 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1933 print_timestamp_time("SDL_DisplayFormat (masked)");
1935 UPDATE_BUSY_STATE();
1937 /* free temporary surface */
1938 SDL_FreeSurface(sdl_image_tmp);
1940 new_bitmap->width = new_bitmap->surface->w;
1941 new_bitmap->height = new_bitmap->surface->h;
1943 print_timestamp_done("SDLLoadImage");
1949 /* ------------------------------------------------------------------------- */
1950 /* custom cursor fuctions */
1951 /* ------------------------------------------------------------------------- */
1953 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1955 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1956 cursor_info->width, cursor_info->height,
1957 cursor_info->hot_x, cursor_info->hot_y);
1960 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1962 static struct MouseCursorInfo *last_cursor_info = NULL;
1963 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1964 static SDL_Cursor *cursor_default = NULL;
1965 static SDL_Cursor *cursor_current = NULL;
1967 /* if invoked for the first time, store the SDL default cursor */
1968 if (cursor_default == NULL)
1969 cursor_default = SDL_GetCursor();
1971 /* only create new cursor if cursor info (custom only) has changed */
1972 if (cursor_info != NULL && cursor_info != last_cursor_info)
1974 cursor_current = create_cursor(cursor_info);
1975 last_cursor_info = cursor_info;
1978 /* only set new cursor if cursor info (custom or NULL) has changed */
1979 if (cursor_info != last_cursor_info2)
1980 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1982 last_cursor_info2 = cursor_info;
1986 /* ========================================================================= */
1987 /* audio functions */
1988 /* ========================================================================= */
1990 void SDLOpenAudio(void)
1992 #if !defined(TARGET_SDL2)
1993 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1994 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1997 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1999 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
2003 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
2004 AUDIO_NUM_CHANNELS_STEREO,
2005 setup.system.audio_fragment_size) < 0)
2007 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
2011 audio.sound_available = TRUE;
2012 audio.music_available = TRUE;
2013 audio.loops_available = TRUE;
2014 audio.sound_enabled = TRUE;
2016 /* set number of available mixer channels */
2017 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
2018 audio.music_channel = MUSIC_CHANNEL;
2019 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
2021 Mixer_InitChannels();
2024 void SDLCloseAudio(void)
2027 Mix_HaltChannel(-1);
2030 SDL_QuitSubSystem(SDL_INIT_AUDIO);
2034 /* ========================================================================= */
2035 /* event functions */
2036 /* ========================================================================= */
2038 void SDLNextEvent(Event *event)
2040 SDL_WaitEvent(event);
2042 if (event->type == EVENT_BUTTONPRESS ||
2043 event->type == EVENT_BUTTONRELEASE)
2045 if (((ButtonEvent *)event)->x > video_xoffset)
2046 ((ButtonEvent *)event)->x -= video_xoffset;
2048 ((ButtonEvent *)event)->x = 0;
2049 if (((ButtonEvent *)event)->y > video_yoffset)
2050 ((ButtonEvent *)event)->y -= video_yoffset;
2052 ((ButtonEvent *)event)->y = 0;
2054 else if (event->type == EVENT_MOTIONNOTIFY)
2056 if (((MotionEvent *)event)->x > video_xoffset)
2057 ((MotionEvent *)event)->x -= video_xoffset;
2059 ((MotionEvent *)event)->x = 0;
2060 if (((MotionEvent *)event)->y > video_yoffset)
2061 ((MotionEvent *)event)->y -= video_yoffset;
2063 ((MotionEvent *)event)->y = 0;
2067 void SDLHandleWindowManagerEvent(Event *event)
2069 #if defined(PLATFORM_WIN32)
2070 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
2071 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
2073 if (syswmmsg->msg == WM_DROPFILES)
2075 HDROP hdrop = (HDROP)syswmmsg->wParam;
2078 printf("::: SDL_SYSWMEVENT:\n");
2080 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
2082 for (i = 0; i < num_files; i++)
2084 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
2085 char buffer[buffer_len + 1];
2087 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
2089 printf("::: - '%s'\n", buffer);
2092 DragFinish((HDROP)syswmmsg->wParam);
2098 /* ========================================================================= */
2099 /* joystick functions */
2100 /* ========================================================================= */
2102 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
2103 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2104 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2106 static boolean SDLOpenJoystick(int nr)
2108 if (nr < 0 || nr > MAX_PLAYERS)
2111 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
2114 static void SDLCloseJoystick(int nr)
2116 if (nr < 0 || nr > MAX_PLAYERS)
2119 SDL_JoystickClose(sdl_joystick[nr]);
2121 sdl_joystick[nr] = NULL;
2124 static boolean SDLCheckJoystickOpened(int nr)
2126 if (nr < 0 || nr > MAX_PLAYERS)
2129 #if defined(TARGET_SDL2)
2130 return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
2132 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
2136 void HandleJoystickEvent(Event *event)
2140 case SDL_JOYAXISMOTION:
2141 if (event->jaxis.axis < 2)
2142 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
2145 case SDL_JOYBUTTONDOWN:
2146 if (event->jbutton.button < 2)
2147 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
2150 case SDL_JOYBUTTONUP:
2151 if (event->jbutton.button < 2)
2152 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
2160 void SDLInitJoysticks()
2162 static boolean sdl_joystick_subsystem_initialized = FALSE;
2163 boolean print_warning = !sdl_joystick_subsystem_initialized;
2166 if (!sdl_joystick_subsystem_initialized)
2168 sdl_joystick_subsystem_initialized = TRUE;
2170 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2172 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
2177 for (i = 0; i < MAX_PLAYERS; i++)
2179 /* get configured joystick for this player */
2180 char *device_name = setup.input[i].joy.device_name;
2181 int joystick_nr = getJoystickNrFromDeviceName(device_name);
2183 if (joystick_nr >= SDL_NumJoysticks())
2185 if (setup.input[i].use_joystick && print_warning)
2186 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
2191 /* misuse joystick file descriptor variable to store joystick number */
2192 joystick.fd[i] = joystick_nr;
2194 if (joystick_nr == -1)
2197 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
2198 if (SDLCheckJoystickOpened(joystick_nr))
2199 SDLCloseJoystick(joystick_nr);
2201 if (!setup.input[i].use_joystick)
2204 if (!SDLOpenJoystick(joystick_nr))
2207 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
2212 joystick.status = JOYSTICK_ACTIVATED;
2216 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
2218 if (nr < 0 || nr >= MAX_PLAYERS)
2222 *x = sdl_js_axis[nr][0];
2224 *y = sdl_js_axis[nr][1];
2227 *b1 = sdl_js_button[nr][0];
2229 *b2 = sdl_js_button[nr][1];
2234 #endif /* TARGET_SDL */