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 // SDL_Window *sdl_window = NULL;
31 // static SDL_Renderer *sdl_renderer = 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 setFullscreenParameters(char *fullscreen_mode_string)
47 struct ScreenModeInfo *fullscreen_mode;
50 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
52 if (fullscreen_mode == NULL)
55 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
57 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
58 fullscreen_mode->height == video.fullscreen_modes[i].height)
60 fullscreen_width = fullscreen_mode->width;
61 fullscreen_height = fullscreen_mode->height;
63 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
64 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
71 static void SDLSetWindowIcon(char *basename)
73 /* (setting the window icon on Mac OS X would replace the high-quality
74 dock icon with the currently smaller (and uglier) icon from file) */
76 #if !defined(PLATFORM_MACOSX)
77 char *filename = getCustomImageFilename(basename);
82 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
87 if ((surface = IMG_Load(filename)) == NULL)
89 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
94 /* set transparent color */
95 SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
96 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
98 #if defined(TARGET_SDL2)
99 SDL_SetWindowIcon(sdl_window, surface);
101 SDL_WM_SetIcon(surface, NULL);
106 #if defined(TARGET_SDL2)
107 SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface)
109 if (backbuffer == NULL ||
110 backbuffer->surface == NULL)
113 return SDL_ConvertSurface(surface, backbuffer->surface->format, 0);
117 void SDLInitVideoDisplay(void)
119 #if !defined(TARGET_SDL2)
120 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
121 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
123 SDL_putenv("SDL_VIDEO_CENTERED=1");
126 /* initialize SDL video */
127 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
128 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
130 /* set default SDL depth */
131 #if !defined(TARGET_SDL2)
132 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
134 video.default_depth = 32; // (how to determine video depth in SDL2?)
138 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
141 static int screen_xy[][2] =
151 /* default: normal game window size */
152 fullscreen_width = video.width;
153 fullscreen_height = video.height;
154 fullscreen_xoffset = 0;
155 fullscreen_yoffset = 0;
157 for (i = 0; screen_xy[i][0] != -1; i++)
159 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
161 fullscreen_width = screen_xy[i][0];
162 fullscreen_height = screen_xy[i][1];
168 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
169 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
172 checked_free(video.fullscreen_modes);
174 video.fullscreen_modes = NULL;
175 video.fullscreen_mode_current = NULL;
178 #if !defined(TARGET_SDL2)
179 /* get available hardware supported fullscreen modes */
180 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
182 // (for now, no display modes in SDL2 -- change this later)
188 /* no screen modes available => no fullscreen mode support */
189 video.fullscreen_available = FALSE;
191 else if (modes == (SDL_Rect **)-1)
193 /* fullscreen resolution is not restricted -- all resolutions available */
194 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
196 /* use native video buffer size for fullscreen mode */
197 video.fullscreen_modes[0].width = video.width;
198 video.fullscreen_modes[0].height = video.height;
200 video.fullscreen_modes[1].width = -1;
201 video.fullscreen_modes[1].height = -1;
205 /* in this case, a certain number of screen modes is available */
208 for(i = 0; modes[i] != NULL; i++)
210 boolean found_mode = FALSE;
212 /* screen mode is smaller than video buffer size -- skip it */
213 if (modes[i]->w < video.width || modes[i]->h < video.height)
216 if (video.fullscreen_modes != NULL)
217 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
218 if (modes[i]->w == video.fullscreen_modes[j].width &&
219 modes[i]->h == video.fullscreen_modes[j].height)
222 if (found_mode) /* screen mode already stored -- skip it */
225 /* new mode found; add it to list of available fullscreen modes */
229 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
231 sizeof(struct ScreenModeInfo));
233 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
234 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
236 video.fullscreen_modes[num_modes].width = -1;
237 video.fullscreen_modes[num_modes].height = -1;
242 /* no appropriate screen modes available => no fullscreen mode support */
243 video.fullscreen_available = FALSE;
248 /* set window icon */
249 SDLSetWindowIcon(program.sdl_icon_filename);
252 /* open SDL video output device (window or fullscreen mode) */
253 if (!SDLSetVideoMode(backbuffer, fullscreen))
254 Error(ERR_EXIT, "setting video mode failed");
257 /* set window icon */
258 SDLSetWindowIcon(program.sdl_icon_filename);
261 /* set window and icon title */
262 #if defined(TARGET_SDL2)
263 SDL_SetWindowTitle(sdl_window, program.window_title);
265 SDL_WM_SetCaption(program.window_title, program.window_title);
268 /* SDL cannot directly draw to the visible video framebuffer like X11,
269 but always uses a backbuffer, which is then blitted to the visible
270 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
271 visible video framebuffer with 'SDL_Flip', if the hardware supports
272 this). Therefore do not use an additional backbuffer for drawing, but
273 use a symbolic buffer (distinguishable from the SDL backbuffer) called
274 'window', which indicates that the SDL backbuffer should be updated to
275 the visible video framebuffer when attempting to blit to it.
277 For convenience, it seems to be a good idea to create this symbolic
278 buffer 'window' at the same size as the SDL backbuffer. Although it
279 should never be drawn to directly, it would do no harm nevertheless. */
281 /* create additional (symbolic) buffer for double-buffering */
283 ReCreateBitmap(window, video.width, video.height, video.depth);
285 *window = CreateBitmap(video.width, video.height, video.depth);
289 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
291 boolean success = TRUE;
292 #if defined(TARGET_SDL2)
293 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
294 int surface_flags_window = SURFACE_FLAGS;
296 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
297 int surface_flags_window = SURFACE_FLAGS;
299 SDL_Surface *new_surface = NULL;
301 if (*backbuffer == NULL)
302 *backbuffer = CreateBitmapStruct();
304 /* (real bitmap might be larger in fullscreen mode with video offsets) */
305 (*backbuffer)->width = video.width;
306 (*backbuffer)->height = video.height;
308 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
310 setFullscreenParameters(setup.fullscreen_mode);
312 video_xoffset = fullscreen_xoffset;
313 video_yoffset = fullscreen_yoffset;
315 /* switch display to fullscreen mode, if available */
316 #if defined(TARGET_SDL2)
317 sdl_window = SDL_CreateWindow(program.window_title,
318 SDL_WINDOWPOS_CENTERED,
319 SDL_WINDOWPOS_CENTERED,
320 fullscreen_width, fullscreen_height,
321 surface_flags_fullscreen);
322 if (sdl_window != NULL)
324 new_surface = SDL_GetWindowSurface(sdl_window);
326 SDL_UpdateWindowSurface(sdl_window); // immediately map window
329 new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
330 video.depth, surface_flags_fullscreen);
333 if (new_surface == NULL)
335 /* switching display to fullscreen mode failed */
336 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
338 /* do not try it again */
339 video.fullscreen_available = FALSE;
345 (*backbuffer)->surface = new_surface;
347 video.fullscreen_enabled = TRUE;
348 video.fullscreen_mode_current = setup.fullscreen_mode;
354 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
359 /* switch display to window mode */
360 #if defined(TARGET_SDL2)
361 sdl_window = SDL_CreateWindow(program.window_title,
362 SDL_WINDOWPOS_CENTERED,
363 SDL_WINDOWPOS_CENTERED,
364 video.width, video.height,
365 surface_flags_window);
366 if (sdl_window != NULL)
368 new_surface = SDL_GetWindowSurface(sdl_window);
370 SDL_UpdateWindowSurface(sdl_window); // immediately map window
373 new_surface = SDL_SetVideoMode(video.width, video.height,
374 video.depth, surface_flags_window);
377 if (new_surface == NULL)
379 /* switching display to window mode failed -- should not happen */
380 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
386 (*backbuffer)->surface = new_surface;
388 video.fullscreen_enabled = FALSE;
395 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
397 #if defined(PLATFORM_WIN32)
399 SDL_SysWMinfo wminfo;
402 SDL_VERSION(&wminfo.version);
403 SDL_GetWMInfo(&wminfo);
405 hwnd = wminfo.window;
407 DragAcceptFiles(hwnd, TRUE);
416 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
419 SDL_Surface *surface_tmp, *surface_native;
421 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
424 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
426 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
427 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
429 SDL_FreeSurface(surface_tmp);
431 new_bitmap->surface = surface_native;
434 void SDLFreeBitmapPointers(Bitmap *bitmap)
437 SDL_FreeSurface(bitmap->surface);
438 if (bitmap->surface_masked)
439 SDL_FreeSurface(bitmap->surface_masked);
440 bitmap->surface = NULL;
441 bitmap->surface_masked = NULL;
444 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
445 int src_x, int src_y, int width, int height,
446 int dst_x, int dst_y, int mask_mode)
448 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
449 SDL_Rect src_rect, dst_rect;
451 if (src_bitmap == backbuffer)
453 src_x += video_xoffset;
454 src_y += video_yoffset;
462 if (dst_bitmap == backbuffer || dst_bitmap == window)
464 dst_x += video_xoffset;
465 dst_y += video_yoffset;
473 if (src_bitmap != backbuffer || dst_bitmap != window)
474 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
475 src_bitmap->surface_masked : src_bitmap->surface),
476 &src_rect, real_dst_bitmap->surface, &dst_rect);
478 #if defined(TARGET_SDL2)
479 if (dst_bitmap == window)
481 // SDL_UpdateWindowSurface(sdl_window);
482 SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
485 if (dst_bitmap == window)
486 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
490 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
493 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
496 if (dst_bitmap == backbuffer || dst_bitmap == window)
507 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
509 #if defined(TARGET_SDL2)
510 if (dst_bitmap == window)
512 // SDL_UpdateWindowSurface(sdl_window);
513 SDL_UpdateWindowSurfaceRects(sdl_window, &rect, 1);
516 if (dst_bitmap == window)
517 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
521 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
522 int fade_mode, int fade_delay, int post_delay,
523 void (*draw_border_function)(void))
525 static boolean initialization_needed = TRUE;
526 static SDL_Surface *surface_source = NULL;
527 static SDL_Surface *surface_target = NULL;
528 static SDL_Surface *surface_black = NULL;
529 SDL_Surface *surface_screen = backbuffer->surface;
530 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
531 SDL_Rect src_rect, dst_rect;
532 #if defined(TARGET_SDL2)
535 int src_x = x, src_y = y;
536 int dst_x = x, dst_y = y;
537 unsigned int time_last, time_current;
539 /* check if screen size has changed */
540 if (surface_source != NULL && (video.width != surface_source->w ||
541 video.height != surface_source->h))
543 SDL_FreeSurface(surface_source);
544 SDL_FreeSurface(surface_target);
545 SDL_FreeSurface(surface_black);
547 initialization_needed = TRUE;
555 dst_x += video_xoffset;
556 dst_y += video_yoffset;
560 dst_rect.w = width; /* (ignored) */
561 dst_rect.h = height; /* (ignored) */
563 #if defined(TARGET_SDL2)
564 dst_rect2 = dst_rect;
567 if (initialization_needed)
569 #if defined(TARGET_SDL2)
570 unsigned int flags = 0;
572 unsigned int flags = SDL_SRCALPHA;
574 /* use same surface type as screen surface */
575 if ((surface_screen->flags & SDL_HWSURFACE))
576 flags |= SDL_HWSURFACE;
578 flags |= SDL_SWSURFACE;
581 /* create surface for temporary copy of screen buffer (source) */
582 if ((surface_source =
583 SDL_CreateRGBSurface(flags,
586 surface_screen->format->BitsPerPixel,
587 surface_screen->format->Rmask,
588 surface_screen->format->Gmask,
589 surface_screen->format->Bmask,
590 surface_screen->format->Amask)) == NULL)
591 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
593 /* create surface for cross-fading screen buffer (target) */
594 if ((surface_target =
595 SDL_CreateRGBSurface(flags,
598 surface_screen->format->BitsPerPixel,
599 surface_screen->format->Rmask,
600 surface_screen->format->Gmask,
601 surface_screen->format->Bmask,
602 surface_screen->format->Amask)) == NULL)
603 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
605 /* create black surface for fading from/to black */
607 SDL_CreateRGBSurface(flags,
610 surface_screen->format->BitsPerPixel,
611 surface_screen->format->Rmask,
612 surface_screen->format->Gmask,
613 surface_screen->format->Bmask,
614 surface_screen->format->Amask)) == NULL)
615 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
617 /* completely fill the surface with black color pixels */
618 SDL_FillRect(surface_black, NULL,
619 SDL_MapRGB(surface_screen->format, 0, 0, 0));
621 initialization_needed = FALSE;
624 /* copy source and target surfaces to temporary surfaces for fading */
625 if (fade_mode & FADE_TYPE_TRANSFORM)
627 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
628 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
630 else if (fade_mode & FADE_TYPE_FADE_IN)
632 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
633 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
635 else /* FADE_TYPE_FADE_OUT */
637 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
638 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
641 time_current = SDL_GetTicks();
643 if (fade_mode == FADE_MODE_MELT)
645 boolean done = FALSE;
647 int melt_columns = width / melt_pixels;
648 int ypos[melt_columns];
649 int max_steps = height / 8 + 32;
654 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
655 #if defined(TARGET_SDL2)
656 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_NONE);
658 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
661 ypos[0] = -GetSimpleRandom(16);
663 for (i = 1 ; i < melt_columns; i++)
665 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
667 ypos[i] = ypos[i - 1] + r;
680 time_last = time_current;
681 time_current = SDL_GetTicks();
682 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
683 steps_final = MIN(MAX(0, steps), max_steps);
687 done = (steps_done >= steps_final);
689 for (i = 0 ; i < melt_columns; i++)
697 else if (ypos[i] < height)
702 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
704 if (ypos[i] + dy >= height)
705 dy = height - ypos[i];
707 /* copy part of (appearing) target surface to upper area */
708 src_rect.x = src_x + i * melt_pixels;
709 // src_rect.y = src_y + ypos[i];
711 src_rect.w = melt_pixels;
713 src_rect.h = ypos[i] + dy;
715 dst_rect.x = dst_x + i * melt_pixels;
716 // dst_rect.y = dst_y + ypos[i];
719 if (steps_done >= steps_final)
720 SDL_BlitSurface(surface_target, &src_rect,
721 surface_screen, &dst_rect);
725 /* copy part of (disappearing) source surface to lower area */
726 src_rect.x = src_x + i * melt_pixels;
728 src_rect.w = melt_pixels;
729 src_rect.h = height - ypos[i];
731 dst_rect.x = dst_x + i * melt_pixels;
732 dst_rect.y = dst_y + ypos[i];
734 if (steps_done >= steps_final)
735 SDL_BlitSurface(surface_source, &src_rect,
736 surface_screen, &dst_rect);
742 src_rect.x = src_x + i * melt_pixels;
744 src_rect.w = melt_pixels;
747 dst_rect.x = dst_x + i * melt_pixels;
750 if (steps_done >= steps_final)
751 SDL_BlitSurface(surface_target, &src_rect,
752 surface_screen, &dst_rect);
756 if (steps_done >= steps_final)
758 if (draw_border_function != NULL)
759 draw_border_function();
761 #if defined(TARGET_SDL2)
762 // SDL_UpdateWindowSurface(sdl_window);
763 SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect2, 1);
765 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
775 for (alpha = 0.0; alpha < 255.0;)
777 time_last = time_current;
778 time_current = SDL_GetTicks();
779 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
780 alpha_final = MIN(MAX(0, alpha), 255);
782 /* draw existing (source) image to screen buffer */
783 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
785 /* draw new (target) image to screen buffer using alpha blending */
786 #if defined(TARGET_SDL2)
787 SDL_SetSurfaceAlphaMod(surface_target, alpha_final);
788 SDL_SetSurfaceBlendMode(surface_target, SDL_BLENDMODE_BLEND);
790 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
792 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
794 if (draw_border_function != NULL)
795 draw_border_function();
798 /* only update the region of the screen that is affected from fading */
799 #if defined(TARGET_SDL2)
800 // SDL_UpdateWindowSurface(sdl_window);
801 SDL_UpdateWindowSurfaceRects(sdl_window, &dst_rect, 1);
803 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
806 SDL_Flip(surface_screen);
814 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
815 int to_x, int to_y, Uint32 color)
817 SDL_Surface *surface = dst_bitmap->surface;
821 swap_numbers(&from_x, &to_x);
824 swap_numbers(&from_y, &to_y);
828 rect.w = (to_x - from_x + 1);
829 rect.h = (to_y - from_y + 1);
831 if (dst_bitmap == backbuffer || dst_bitmap == window)
833 rect.x += video_xoffset;
834 rect.y += video_yoffset;
837 SDL_FillRect(surface, &rect, color);
840 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
841 int to_x, int to_y, Uint32 color)
843 if (dst_bitmap == backbuffer || dst_bitmap == window)
845 from_x += video_xoffset;
846 from_y += video_yoffset;
847 to_x += video_xoffset;
848 to_y += video_yoffset;
851 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
855 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
856 int num_points, Uint32 color)
861 for (i = 0; i < num_points - 1; i++)
863 for (x = 0; x < line_width; x++)
865 for (y = 0; y < line_width; y++)
867 int dx = x - line_width / 2;
868 int dy = y - line_width / 2;
870 if ((x == 0 && y == 0) ||
871 (x == 0 && y == line_width - 1) ||
872 (x == line_width - 1 && y == 0) ||
873 (x == line_width - 1 && y == line_width - 1))
876 sge_Line(surface, points[i].x + dx, points[i].y + dy,
877 points[i+1].x + dx, points[i+1].y + dy, color);
884 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
886 SDL_Surface *surface = src_bitmap->surface;
888 if (src_bitmap == backbuffer || src_bitmap == window)
894 switch (surface->format->BytesPerPixel)
896 case 1: /* assuming 8-bpp */
898 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
902 case 2: /* probably 15-bpp or 16-bpp */
904 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
908 case 3: /* slow 24-bpp mode; usually not used */
910 /* does this work? */
911 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
915 shift = surface->format->Rshift;
916 color |= *(pix + shift / 8) >> shift;
917 shift = surface->format->Gshift;
918 color |= *(pix + shift / 8) >> shift;
919 shift = surface->format->Bshift;
920 color |= *(pix + shift / 8) >> shift;
926 case 4: /* probably 32-bpp */
928 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
937 /* ========================================================================= */
938 /* The following functions were taken from the SGE library */
939 /* (SDL Graphics Extension Library) by Anders Lindström */
940 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
941 /* ========================================================================= */
943 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
945 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
947 switch (surface->format->BytesPerPixel)
952 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
958 /* Probably 15-bpp or 16-bpp */
959 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
965 /* Slow 24-bpp mode, usually not used */
969 /* Gack - slow, but endian correct */
970 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
971 shift = surface->format->Rshift;
972 *(pix+shift/8) = color>>shift;
973 shift = surface->format->Gshift;
974 *(pix+shift/8) = color>>shift;
975 shift = surface->format->Bshift;
976 *(pix+shift/8) = color>>shift;
982 /* Probably 32-bpp */
983 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
990 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
991 Uint8 R, Uint8 G, Uint8 B)
993 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
996 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
998 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
1001 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1003 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
1006 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1011 /* Gack - slow, but endian correct */
1012 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
1013 shift = surface->format->Rshift;
1014 *(pix+shift/8) = color>>shift;
1015 shift = surface->format->Gshift;
1016 *(pix+shift/8) = color>>shift;
1017 shift = surface->format->Bshift;
1018 *(pix+shift/8) = color>>shift;
1021 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1023 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
1026 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
1028 switch (dest->format->BytesPerPixel)
1031 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
1035 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
1039 _PutPixel24(dest,x,y,color);
1043 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
1048 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
1050 if (SDL_MUSTLOCK(surface))
1052 if (SDL_LockSurface(surface) < 0)
1058 _PutPixel(surface, x, y, color);
1060 if (SDL_MUSTLOCK(surface))
1062 SDL_UnlockSurface(surface);
1066 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
1067 Uint8 r, Uint8 g, Uint8 b)
1069 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
1072 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
1074 if (y >= 0 && y <= dest->h - 1)
1076 switch (dest->format->BytesPerPixel)
1079 return y*dest->pitch;
1083 return y*dest->pitch/2;
1087 return y*dest->pitch;
1091 return y*dest->pitch/4;
1099 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
1101 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
1103 switch (surface->format->BytesPerPixel)
1107 /* Assuming 8-bpp */
1108 *((Uint8 *)surface->pixels + ypitch + x) = color;
1114 /* Probably 15-bpp or 16-bpp */
1115 *((Uint16 *)surface->pixels + ypitch + x) = color;
1121 /* Slow 24-bpp mode, usually not used */
1125 /* Gack - slow, but endian correct */
1126 pix = (Uint8 *)surface->pixels + ypitch + x*3;
1127 shift = surface->format->Rshift;
1128 *(pix+shift/8) = color>>shift;
1129 shift = surface->format->Gshift;
1130 *(pix+shift/8) = color>>shift;
1131 shift = surface->format->Bshift;
1132 *(pix+shift/8) = color>>shift;
1138 /* Probably 32-bpp */
1139 *((Uint32 *)surface->pixels + ypitch + x) = color;
1146 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1151 if (SDL_MUSTLOCK(Surface))
1153 if (SDL_LockSurface(Surface) < 0)
1166 /* Do the clipping */
1167 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1171 if (x2 > Surface->w - 1)
1172 x2 = Surface->w - 1;
1179 SDL_FillRect(Surface, &l, Color);
1181 if (SDL_MUSTLOCK(Surface))
1183 SDL_UnlockSurface(Surface);
1187 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1188 Uint8 R, Uint8 G, Uint8 B)
1190 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1193 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1204 /* Do the clipping */
1205 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1209 if (x2 > Surface->w - 1)
1210 x2 = Surface->w - 1;
1217 SDL_FillRect(Surface, &l, Color);
1220 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1225 if (SDL_MUSTLOCK(Surface))
1227 if (SDL_LockSurface(Surface) < 0)
1240 /* Do the clipping */
1241 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1245 if (y2 > Surface->h - 1)
1246 y2 = Surface->h - 1;
1253 SDL_FillRect(Surface, &l, Color);
1255 if (SDL_MUSTLOCK(Surface))
1257 SDL_UnlockSurface(Surface);
1261 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1262 Uint8 R, Uint8 G, Uint8 B)
1264 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1267 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1278 /* Do the clipping */
1279 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1283 if (y2 > Surface->h - 1)
1284 y2 = Surface->h - 1;
1291 SDL_FillRect(Surface, &l, Color);
1294 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1295 Sint16 x2, Sint16 y2, Uint32 Color,
1296 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1299 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1304 sdx = (dx < 0) ? -1 : 1;
1305 sdy = (dy < 0) ? -1 : 1;
1317 for (x = 0; x < dx; x++)
1319 Callback(Surface, px, py, Color);
1333 for (y = 0; y < dy; y++)
1335 Callback(Surface, px, py, Color);
1349 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
1350 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
1351 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1354 sge_DoLine(Surface, X1, Y1, X2, Y2,
1355 SDL_MapRGB(Surface->format, R, G, B), Callback);
1358 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
1361 if (SDL_MUSTLOCK(Surface))
1363 if (SDL_LockSurface(Surface) < 0)
1368 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
1370 /* unlock the display */
1371 if (SDL_MUSTLOCK(Surface))
1373 SDL_UnlockSurface(Surface);
1377 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
1378 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1380 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
1383 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
1385 if (dst_bitmap == backbuffer || dst_bitmap == window)
1391 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
1396 -----------------------------------------------------------------------------
1397 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
1398 -----------------------------------------------------------------------------
1401 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
1402 int width, int height, Uint32 color)
1406 for (y = src_y; y < src_y + height; y++)
1408 for (x = src_x; x < src_x + width; x++)
1410 Uint32 pixel = SDLGetPixel(bitmap, x, y);
1412 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
1417 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1418 int src_x, int src_y, int width, int height,
1419 int dst_x, int dst_y)
1423 for (y = 0; y < height; y++)
1425 for (x = 0; x < width; x++)
1427 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
1429 if (pixel != BLACK_PIXEL)
1430 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
1436 /* ========================================================================= */
1437 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
1438 /* (Rotozoomer) by Andreas Schiffler */
1439 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
1440 /* ========================================================================= */
1443 -----------------------------------------------------------------------------
1446 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
1447 -----------------------------------------------------------------------------
1458 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
1461 tColorRGBA *sp, *csp, *dp;
1468 sp = csp = (tColorRGBA *) src->pixels;
1469 dp = (tColorRGBA *) dst->pixels;
1471 sgap = src->pitch - src->w * 4;
1473 dgap = dst->pitch - dst->w * 4;
1475 for (y = 0; y < dst->h; y++)
1479 for (x = 0; x < dst->w; x++)
1481 tColorRGBA *sp0 = sp;
1482 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1483 tColorRGBA *sp00 = &sp0[0];
1484 tColorRGBA *sp01 = &sp0[1];
1485 tColorRGBA *sp10 = &sp1[0];
1486 tColorRGBA *sp11 = &sp1[1];
1489 /* create new color pixel from all four source color pixels */
1490 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1491 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1492 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1493 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1498 /* advance source pointers */
1501 /* advance destination pointer */
1505 /* advance source pointer */
1506 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1508 /* advance destination pointers */
1509 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1515 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1517 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1518 tColorRGBA *sp, *csp, *dp;
1524 /* use specialized zoom function when scaling down to exactly half size */
1525 if (src->w == 2 * dst->w &&
1526 src->h == 2 * dst->h)
1527 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1529 /* variable setup */
1530 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1531 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1533 /* allocate memory for row increments */
1534 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1535 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1537 /* precalculate row increments */
1540 for (x = 0; x <= dst->w; x++)
1550 for (y = 0; y <= dst->h; y++)
1559 sp = csp = (tColorRGBA *) src->pixels;
1560 dp = (tColorRGBA *) dst->pixels;
1562 sgap = src->pitch - src->w * 4;
1564 dgap = dst->pitch - dst->w * 4;
1567 for (y = 0; y < dst->h; y++)
1572 for (x = 0; x < dst->w; x++)
1577 /* advance source pointers */
1579 sp += (*csax >> 16);
1581 /* advance destination pointer */
1585 /* advance source pointer */
1587 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1589 /* advance destination pointers */
1590 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1600 -----------------------------------------------------------------------------
1603 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1604 -----------------------------------------------------------------------------
1607 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1609 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1610 Uint8 *sp, *dp, *csp;
1613 /* variable setup */
1614 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1615 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1617 /* allocate memory for row increments */
1618 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1619 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1621 /* precalculate row increments */
1624 for (x = 0; x < dst->w; x++)
1627 *csax = (csx >> 16);
1634 for (y = 0; y < dst->h; y++)
1637 *csay = (csy >> 16);
1644 for (x = 0; x < dst->w; x++)
1652 for (y = 0; y < dst->h; y++)
1659 sp = csp = (Uint8 *) src->pixels;
1660 dp = (Uint8 *) dst->pixels;
1661 dgap = dst->pitch - dst->w;
1665 for (y = 0; y < dst->h; y++)
1669 for (x = 0; x < dst->w; x++)
1674 /* advance source pointers */
1678 /* advance destination pointer */
1682 /* advance source pointer (for row) */
1683 csp += ((*csay) * src->pitch);
1686 /* advance destination pointers */
1697 -----------------------------------------------------------------------------
1700 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1701 'zoomx' and 'zoomy' are scaling factors for width and height.
1702 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1703 into a 32bit RGBA format on the fly.
1704 -----------------------------------------------------------------------------
1707 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1709 SDL_Surface *zoom_src = NULL;
1710 SDL_Surface *zoom_dst = NULL;
1711 boolean is_converted = FALSE;
1718 /* determine if source surface is 32 bit or 8 bit */
1719 is_32bit = (src->format->BitsPerPixel == 32);
1721 if (is_32bit || src->format->BitsPerPixel == 8)
1723 /* use source surface 'as is' */
1728 /* new source surface is 32 bit with a defined RGB ordering */
1729 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1730 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1731 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1733 is_converted = TRUE;
1736 /* allocate surface to completely contain the zoomed surface */
1739 /* target surface is 32 bit with source RGBA/ABGR ordering */
1740 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1741 zoom_src->format->Rmask,
1742 zoom_src->format->Gmask,
1743 zoom_src->format->Bmask, 0);
1747 /* target surface is 8 bit */
1748 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1752 /* lock source surface */
1753 SDL_LockSurface(zoom_src);
1755 /* check which kind of surface we have */
1758 /* call the 32 bit transformation routine to do the zooming */
1759 zoomSurfaceRGBA(zoom_src, zoom_dst);
1764 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1765 zoom_dst->format->palette->colors[i] =
1766 zoom_src->format->palette->colors[i];
1767 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1769 /* call the 8 bit transformation routine to do the zooming */
1770 zoomSurfaceY(zoom_src, zoom_dst);
1773 /* unlock source surface */
1774 SDL_UnlockSurface(zoom_src);
1776 /* free temporary surface */
1778 SDL_FreeSurface(zoom_src);
1780 /* return destination surface */
1784 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1786 SDL_Surface *sdl_surface_tmp;
1787 int dst_width = dst_bitmap->width;
1788 int dst_height = dst_bitmap->height;
1790 /* throw away old destination surface */
1791 SDL_FreeSurface(dst_bitmap->surface);
1793 /* create zoomed temporary surface from source surface */
1794 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1796 /* create native format destination surface from zoomed temporary surface */
1797 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1799 /* free temporary surface */
1800 SDL_FreeSurface(sdl_surface_tmp);
1804 /* ========================================================================= */
1805 /* load image to bitmap */
1806 /* ========================================================================= */
1808 Bitmap *SDLLoadImage(char *filename)
1810 Bitmap *new_bitmap = CreateBitmapStruct();
1811 SDL_Surface *sdl_image_tmp;
1813 print_timestamp_init("SDLLoadImage");
1815 print_timestamp_time(getBaseNamePtr(filename));
1817 /* load image to temporary surface */
1818 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1820 SetError("IMG_Load(): %s", SDL_GetError());
1825 print_timestamp_time("IMG_Load");
1827 UPDATE_BUSY_STATE();
1829 /* create native non-transparent surface for current image */
1830 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1832 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1837 print_timestamp_time("SDL_DisplayFormat (opaque)");
1839 UPDATE_BUSY_STATE();
1841 /* create native transparent surface for current image */
1842 SDL_SetColorKey(sdl_image_tmp, SET_TRANSPARENT_PIXEL,
1843 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1844 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1846 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1851 print_timestamp_time("SDL_DisplayFormat (masked)");
1853 UPDATE_BUSY_STATE();
1855 /* free temporary surface */
1856 SDL_FreeSurface(sdl_image_tmp);
1858 new_bitmap->width = new_bitmap->surface->w;
1859 new_bitmap->height = new_bitmap->surface->h;
1861 print_timestamp_done("SDLLoadImage");
1867 /* ------------------------------------------------------------------------- */
1868 /* custom cursor fuctions */
1869 /* ------------------------------------------------------------------------- */
1871 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1873 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1874 cursor_info->width, cursor_info->height,
1875 cursor_info->hot_x, cursor_info->hot_y);
1878 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1880 static struct MouseCursorInfo *last_cursor_info = NULL;
1881 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1882 static SDL_Cursor *cursor_default = NULL;
1883 static SDL_Cursor *cursor_current = NULL;
1885 /* if invoked for the first time, store the SDL default cursor */
1886 if (cursor_default == NULL)
1887 cursor_default = SDL_GetCursor();
1889 /* only create new cursor if cursor info (custom only) has changed */
1890 if (cursor_info != NULL && cursor_info != last_cursor_info)
1892 cursor_current = create_cursor(cursor_info);
1893 last_cursor_info = cursor_info;
1896 /* only set new cursor if cursor info (custom or NULL) has changed */
1897 if (cursor_info != last_cursor_info2)
1898 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1900 last_cursor_info2 = cursor_info;
1904 /* ========================================================================= */
1905 /* audio functions */
1906 /* ========================================================================= */
1908 void SDLOpenAudio(void)
1910 #if !defined(TARGET_SDL2)
1911 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1912 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1915 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1917 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1921 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1922 AUDIO_NUM_CHANNELS_STEREO,
1923 setup.system.audio_fragment_size) < 0)
1925 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1929 audio.sound_available = TRUE;
1930 audio.music_available = TRUE;
1931 audio.loops_available = TRUE;
1932 audio.sound_enabled = TRUE;
1934 /* set number of available mixer channels */
1935 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1936 audio.music_channel = MUSIC_CHANNEL;
1937 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1939 Mixer_InitChannels();
1942 void SDLCloseAudio(void)
1945 Mix_HaltChannel(-1);
1948 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1952 /* ========================================================================= */
1953 /* event functions */
1954 /* ========================================================================= */
1956 void SDLNextEvent(Event *event)
1958 SDL_WaitEvent(event);
1960 if (event->type == EVENT_BUTTONPRESS ||
1961 event->type == EVENT_BUTTONRELEASE)
1963 if (((ButtonEvent *)event)->x > video_xoffset)
1964 ((ButtonEvent *)event)->x -= video_xoffset;
1966 ((ButtonEvent *)event)->x = 0;
1967 if (((ButtonEvent *)event)->y > video_yoffset)
1968 ((ButtonEvent *)event)->y -= video_yoffset;
1970 ((ButtonEvent *)event)->y = 0;
1972 else if (event->type == EVENT_MOTIONNOTIFY)
1974 if (((MotionEvent *)event)->x > video_xoffset)
1975 ((MotionEvent *)event)->x -= video_xoffset;
1977 ((MotionEvent *)event)->x = 0;
1978 if (((MotionEvent *)event)->y > video_yoffset)
1979 ((MotionEvent *)event)->y -= video_yoffset;
1981 ((MotionEvent *)event)->y = 0;
1985 void SDLHandleWindowManagerEvent(Event *event)
1987 #if defined(PLATFORM_WIN32)
1988 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
1989 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
1991 if (syswmmsg->msg == WM_DROPFILES)
1993 HDROP hdrop = (HDROP)syswmmsg->wParam;
1996 printf("::: SDL_SYSWMEVENT:\n");
1998 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
2000 for (i = 0; i < num_files; i++)
2002 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
2003 char buffer[buffer_len + 1];
2005 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
2007 printf("::: - '%s'\n", buffer);
2010 DragFinish((HDROP)syswmmsg->wParam);
2016 /* ========================================================================= */
2017 /* joystick functions */
2018 /* ========================================================================= */
2020 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
2021 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2022 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
2024 static boolean SDLOpenJoystick(int nr)
2026 if (nr < 0 || nr > MAX_PLAYERS)
2029 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
2032 static void SDLCloseJoystick(int nr)
2034 if (nr < 0 || nr > MAX_PLAYERS)
2037 SDL_JoystickClose(sdl_joystick[nr]);
2039 sdl_joystick[nr] = NULL;
2042 static boolean SDLCheckJoystickOpened(int nr)
2044 if (nr < 0 || nr > MAX_PLAYERS)
2047 #if defined(TARGET_SDL2)
2048 return (sdl_joystick[nr] != NULL ? TRUE : FALSE);
2050 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
2054 void HandleJoystickEvent(Event *event)
2058 case SDL_JOYAXISMOTION:
2059 if (event->jaxis.axis < 2)
2060 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
2063 case SDL_JOYBUTTONDOWN:
2064 if (event->jbutton.button < 2)
2065 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
2068 case SDL_JOYBUTTONUP:
2069 if (event->jbutton.button < 2)
2070 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
2078 void SDLInitJoysticks()
2080 static boolean sdl_joystick_subsystem_initialized = FALSE;
2081 boolean print_warning = !sdl_joystick_subsystem_initialized;
2084 if (!sdl_joystick_subsystem_initialized)
2086 sdl_joystick_subsystem_initialized = TRUE;
2088 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
2090 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
2095 for (i = 0; i < MAX_PLAYERS; i++)
2097 /* get configured joystick for this player */
2098 char *device_name = setup.input[i].joy.device_name;
2099 int joystick_nr = getJoystickNrFromDeviceName(device_name);
2101 if (joystick_nr >= SDL_NumJoysticks())
2103 if (setup.input[i].use_joystick && print_warning)
2104 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
2109 /* misuse joystick file descriptor variable to store joystick number */
2110 joystick.fd[i] = joystick_nr;
2112 if (joystick_nr == -1)
2115 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
2116 if (SDLCheckJoystickOpened(joystick_nr))
2117 SDLCloseJoystick(joystick_nr);
2119 if (!setup.input[i].use_joystick)
2122 if (!SDLOpenJoystick(joystick_nr))
2125 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
2130 joystick.status = JOYSTICK_ACTIVATED;
2134 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
2136 if (nr < 0 || nr >= MAX_PLAYERS)
2140 *x = sdl_js_axis[nr][0];
2142 *y = sdl_js_axis[nr][1];
2145 *b1 = sdl_js_button[nr][0];
2147 *b2 = sdl_js_button[nr][1];
2152 #endif /* TARGET_SDL */