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 /* functions from SGE library */
28 void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
30 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
31 static int fullscreen_width;
32 static int fullscreen_height;
33 static int fullscreen_xoffset;
34 static int fullscreen_yoffset;
35 static int video_xoffset;
36 static int video_yoffset;
38 static void setFullscreenParameters(char *fullscreen_mode_string)
40 struct ScreenModeInfo *fullscreen_mode;
43 fullscreen_mode = get_screen_mode_from_string(fullscreen_mode_string);
45 if (fullscreen_mode == NULL)
48 for (i = 0; video.fullscreen_modes[i].width != -1; i++)
50 if (fullscreen_mode->width == video.fullscreen_modes[i].width &&
51 fullscreen_mode->height == video.fullscreen_modes[i].height)
53 fullscreen_width = fullscreen_mode->width;
54 fullscreen_height = fullscreen_mode->height;
56 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
57 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
64 static void SDLSetWindowIcon(char *basename)
66 /* (setting the window icon on Mac OS X would replace the high-quality
67 dock icon with the currently smaller (and uglier) icon from file) */
69 #if !defined(PLATFORM_MACOSX)
70 char *filename = getCustomImageFilename(basename);
75 Error(ERR_WARN, "SDLSetWindowIcon(): cannot find file '%s'", basename);
80 if ((surface = IMG_Load(filename)) == NULL)
82 Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
87 /* set transparent color */
88 SDL_SetColorKey(surface, SDL_SRCCOLORKEY,
89 SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
91 SDL_WM_SetIcon(surface, NULL);
95 void SDLInitVideoDisplay(void)
97 if (!strEqual(setup.system.sdl_videodriver, ARG_DEFAULT))
98 SDL_putenv(getStringCat2("SDL_VIDEODRIVER=", setup.system.sdl_videodriver));
100 SDL_putenv("SDL_VIDEO_CENTERED=1");
102 /* initialize SDL video */
103 if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
104 Error(ERR_EXIT, "SDL_InitSubSystem() failed: %s", SDL_GetError());
106 /* set default SDL depth */
107 video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
110 void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
113 static int screen_xy[][2] =
123 /* default: normal game window size */
124 fullscreen_width = video.width;
125 fullscreen_height = video.height;
126 fullscreen_xoffset = 0;
127 fullscreen_yoffset = 0;
129 for (i = 0; screen_xy[i][0] != -1; i++)
131 if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
133 fullscreen_width = screen_xy[i][0];
134 fullscreen_height = screen_xy[i][1];
140 fullscreen_xoffset = (fullscreen_width - video.width) / 2;
141 fullscreen_yoffset = (fullscreen_height - video.height) / 2;
143 /* get available hardware supported fullscreen modes */
144 modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
148 /* no screen modes available => no fullscreen mode support */
149 video.fullscreen_available = FALSE;
151 else if (modes == (SDL_Rect **)-1)
153 /* fullscreen resolution is not restricted -- all resolutions available */
154 video.fullscreen_modes = checked_calloc(2 * sizeof(struct ScreenModeInfo));
156 /* use native video buffer size for fullscreen mode */
157 video.fullscreen_modes[0].width = video.width;
158 video.fullscreen_modes[0].height = video.height;
160 video.fullscreen_modes[1].width = -1;
161 video.fullscreen_modes[1].height = -1;
165 /* in this case, a certain number of screen modes is available */
168 for(i = 0; modes[i] != NULL; i++)
170 boolean found_mode = FALSE;
172 /* screen mode is smaller than video buffer size -- skip it */
173 if (modes[i]->w < video.width || modes[i]->h < video.height)
176 if (video.fullscreen_modes != NULL)
177 for (j = 0; video.fullscreen_modes[j].width != -1; j++)
178 if (modes[i]->w == video.fullscreen_modes[j].width &&
179 modes[i]->h == video.fullscreen_modes[j].height)
182 if (found_mode) /* screen mode already stored -- skip it */
185 /* new mode found; add it to list of available fullscreen modes */
189 video.fullscreen_modes = checked_realloc(video.fullscreen_modes,
191 sizeof(struct ScreenModeInfo));
193 video.fullscreen_modes[num_modes - 1].width = modes[i]->w;
194 video.fullscreen_modes[num_modes - 1].height = modes[i]->h;
196 video.fullscreen_modes[num_modes].width = -1;
197 video.fullscreen_modes[num_modes].height = -1;
202 /* no appropriate screen modes available => no fullscreen mode support */
203 video.fullscreen_available = FALSE;
207 /* set window icon */
208 SDLSetWindowIcon(program.sdl_icon_filename);
210 /* open SDL video output device (window or fullscreen mode) */
211 if (!SDLSetVideoMode(backbuffer, fullscreen))
212 Error(ERR_EXIT, "setting video mode failed");
214 /* set window and icon title */
215 SDL_WM_SetCaption(program.window_title, program.window_title);
217 /* SDL cannot directly draw to the visible video framebuffer like X11,
218 but always uses a backbuffer, which is then blitted to the visible
219 video framebuffer with 'SDL_UpdateRect' (or replaced with the current
220 visible video framebuffer with 'SDL_Flip', if the hardware supports
221 this). Therefore do not use an additional backbuffer for drawing, but
222 use a symbolic buffer (distinguishable from the SDL backbuffer) called
223 'window', which indicates that the SDL backbuffer should be updated to
224 the visible video framebuffer when attempting to blit to it.
226 For convenience, it seems to be a good idea to create this symbolic
227 buffer 'window' at the same size as the SDL backbuffer. Although it
228 should never be drawn to directly, it would do no harm nevertheless. */
230 /* create additional (symbolic) buffer for double-buffering */
231 *window = CreateBitmap(video.width, video.height, video.depth);
234 boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
236 boolean success = TRUE;
237 int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
238 int surface_flags_window = SURFACE_FLAGS;
239 SDL_Surface *new_surface = NULL;
241 if (*backbuffer == NULL)
242 *backbuffer = CreateBitmapStruct();
244 if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available)
246 setFullscreenParameters(setup.fullscreen_mode);
248 video_xoffset = fullscreen_xoffset;
249 video_yoffset = fullscreen_yoffset;
251 /* switch display to fullscreen mode, if available */
252 if ((new_surface = SDL_SetVideoMode(fullscreen_width, fullscreen_height,
253 video.depth, surface_flags_fullscreen))
256 /* switching display to fullscreen mode failed */
257 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
259 /* do not try it again */
260 video.fullscreen_available = FALSE;
266 (*backbuffer)->surface = new_surface;
268 video.fullscreen_enabled = TRUE;
269 video.fullscreen_mode_current = setup.fullscreen_mode;
275 if ((!fullscreen && video.fullscreen_enabled) || new_surface == NULL)
280 /* switch display to window mode */
281 if ((new_surface = SDL_SetVideoMode(video.width, video.height,
282 video.depth, surface_flags_window))
285 /* switching display to window mode failed -- should not happen */
286 Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
292 (*backbuffer)->surface = new_surface;
294 video.fullscreen_enabled = FALSE;
301 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
303 #if defined(PLATFORM_WIN32)
305 SDL_SysWMinfo wminfo;
308 SDL_VERSION(&wminfo.version);
309 SDL_GetWMInfo(&wminfo);
311 hwnd = wminfo.window;
313 DragAcceptFiles(hwnd, TRUE);
322 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
325 SDL_Surface *surface_tmp, *surface_native;
327 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height, depth,
330 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
332 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
333 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
335 SDL_FreeSurface(surface_tmp);
337 new_bitmap->surface = surface_native;
340 void SDLFreeBitmapPointers(Bitmap *bitmap)
343 SDL_FreeSurface(bitmap->surface);
344 if (bitmap->surface_masked)
345 SDL_FreeSurface(bitmap->surface_masked);
346 bitmap->surface = NULL;
347 bitmap->surface_masked = NULL;
350 void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
351 int src_x, int src_y, int width, int height,
352 int dst_x, int dst_y, int mask_mode)
354 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
355 SDL_Rect src_rect, dst_rect;
357 if (src_bitmap == backbuffer)
359 src_x += video_xoffset;
360 src_y += video_yoffset;
368 if (dst_bitmap == backbuffer || dst_bitmap == window)
370 dst_x += video_xoffset;
371 dst_y += video_yoffset;
379 if (src_bitmap != backbuffer || dst_bitmap != window)
380 SDL_BlitSurface((mask_mode == BLIT_MASKED ?
381 src_bitmap->surface_masked : src_bitmap->surface),
382 &src_rect, real_dst_bitmap->surface, &dst_rect);
384 if (dst_bitmap == window)
385 SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height);
388 void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
391 Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
394 if (dst_bitmap == backbuffer || dst_bitmap == window)
405 SDL_FillRect(real_dst_bitmap->surface, &rect, color);
407 if (dst_bitmap == window)
408 SDL_UpdateRect(backbuffer->surface, x, y, width, height);
411 void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
412 int fade_mode, int fade_delay, int post_delay,
413 void (*draw_border_function)(void))
415 static boolean initialization_needed = TRUE;
416 static SDL_Surface *surface_source = NULL;
417 static SDL_Surface *surface_target = NULL;
418 static SDL_Surface *surface_black = NULL;
419 SDL_Surface *surface_screen = backbuffer->surface;
420 SDL_Surface *surface_cross = (bitmap_cross ? bitmap_cross->surface : NULL);
421 SDL_Rect src_rect, dst_rect;
422 int src_x = x, src_y = y;
423 int dst_x = x, dst_y = y;
424 unsigned int time_last, time_current;
431 dst_x += video_xoffset;
432 dst_y += video_yoffset;
436 dst_rect.w = width; /* (ignored) */
437 dst_rect.h = height; /* (ignored) */
439 if (initialization_needed)
441 unsigned int flags = SDL_SRCALPHA;
443 /* use same surface type as screen surface */
444 if ((surface_screen->flags & SDL_HWSURFACE))
445 flags |= SDL_HWSURFACE;
447 flags |= SDL_SWSURFACE;
449 /* create surface for temporary copy of screen buffer (source) */
450 if ((surface_source =
451 SDL_CreateRGBSurface(flags,
454 surface_screen->format->BitsPerPixel,
455 surface_screen->format->Rmask,
456 surface_screen->format->Gmask,
457 surface_screen->format->Bmask,
458 surface_screen->format->Amask)) == NULL)
459 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
461 /* create surface for cross-fading screen buffer (target) */
462 if ((surface_target =
463 SDL_CreateRGBSurface(flags,
466 surface_screen->format->BitsPerPixel,
467 surface_screen->format->Rmask,
468 surface_screen->format->Gmask,
469 surface_screen->format->Bmask,
470 surface_screen->format->Amask)) == NULL)
471 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
473 /* create black surface for fading from/to black */
475 SDL_CreateRGBSurface(flags,
478 surface_screen->format->BitsPerPixel,
479 surface_screen->format->Rmask,
480 surface_screen->format->Gmask,
481 surface_screen->format->Bmask,
482 surface_screen->format->Amask)) == NULL)
483 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
485 /* completely fill the surface with black color pixels */
486 SDL_FillRect(surface_black, NULL,
487 SDL_MapRGB(surface_screen->format, 0, 0, 0));
489 initialization_needed = FALSE;
492 /* copy source and target surfaces to temporary surfaces for fading */
493 if (fade_mode & FADE_TYPE_TRANSFORM)
495 SDL_BlitSurface(surface_cross, &src_rect, surface_source, &src_rect);
496 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
498 else if (fade_mode & FADE_TYPE_FADE_IN)
500 SDL_BlitSurface(surface_black, &src_rect, surface_source, &src_rect);
501 SDL_BlitSurface(surface_screen, &dst_rect, surface_target, &src_rect);
503 else /* FADE_TYPE_FADE_OUT */
505 SDL_BlitSurface(surface_screen, &dst_rect, surface_source, &src_rect);
506 SDL_BlitSurface(surface_black, &src_rect, surface_target, &src_rect);
509 time_current = SDL_GetTicks();
511 if (fade_mode == FADE_MODE_MELT)
513 boolean done = FALSE;
515 int melt_columns = width / melt_pixels;
516 int ypos[melt_columns];
517 int max_steps = height / 8 + 32;
522 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
523 SDL_SetAlpha(surface_target, 0, 0); /* disable alpha blending */
525 ypos[0] = -GetSimpleRandom(16);
527 for (i = 1 ; i < melt_columns; i++)
529 int r = GetSimpleRandom(3) - 1; /* randomly choose from { -1, 0, -1 } */
531 ypos[i] = ypos[i - 1] + r;
544 time_last = time_current;
545 time_current = SDL_GetTicks();
546 steps += max_steps * ((float)(time_current - time_last) / fade_delay);
547 steps_final = MIN(MAX(0, steps), max_steps);
551 done = (steps_done >= steps_final);
553 for (i = 0 ; i < melt_columns; i++)
561 else if (ypos[i] < height)
566 int dy = (ypos[i] < y1) ? ypos[i] + 1 : y2 + GetSimpleRandom(y3);
568 if (ypos[i] + dy >= height)
569 dy = height - ypos[i];
571 /* copy part of (appearing) target surface to upper area */
572 src_rect.x = src_x + i * melt_pixels;
573 // src_rect.y = src_y + ypos[i];
575 src_rect.w = melt_pixels;
577 src_rect.h = ypos[i] + dy;
579 dst_rect.x = dst_x + i * melt_pixels;
580 // dst_rect.y = dst_y + ypos[i];
583 if (steps_done >= steps_final)
584 SDL_BlitSurface(surface_target, &src_rect,
585 surface_screen, &dst_rect);
589 /* copy part of (disappearing) source surface to lower area */
590 src_rect.x = src_x + i * melt_pixels;
592 src_rect.w = melt_pixels;
593 src_rect.h = height - ypos[i];
595 dst_rect.x = dst_x + i * melt_pixels;
596 dst_rect.y = dst_y + ypos[i];
598 if (steps_done >= steps_final)
599 SDL_BlitSurface(surface_source, &src_rect,
600 surface_screen, &dst_rect);
606 src_rect.x = src_x + i * melt_pixels;
608 src_rect.w = melt_pixels;
611 dst_rect.x = dst_x + i * melt_pixels;
614 if (steps_done >= steps_final)
615 SDL_BlitSurface(surface_target, &src_rect,
616 surface_screen, &dst_rect);
620 if (steps_done >= steps_final)
622 if (draw_border_function != NULL)
623 draw_border_function();
625 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
634 for (alpha = 0.0; alpha < 255.0;)
636 time_last = time_current;
637 time_current = SDL_GetTicks();
638 alpha += 255 * ((float)(time_current - time_last) / fade_delay);
639 alpha_final = MIN(MAX(0, alpha), 255);
641 /* draw existing (source) image to screen buffer */
642 SDL_BlitSurface(surface_source, &src_rect, surface_screen, &dst_rect);
644 /* draw new (target) image to screen buffer using alpha blending */
645 SDL_SetAlpha(surface_target, SDL_SRCALPHA, alpha_final);
646 SDL_BlitSurface(surface_target, &src_rect, surface_screen, &dst_rect);
648 if (draw_border_function != NULL)
649 draw_border_function();
652 /* only update the region of the screen that is affected from fading */
653 SDL_UpdateRect(surface_screen, dst_x, dst_y, width, height);
655 SDL_Flip(surface_screen);
663 void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
664 int to_x, int to_y, Uint32 color)
666 SDL_Surface *surface = dst_bitmap->surface;
670 swap_numbers(&from_x, &to_x);
673 swap_numbers(&from_y, &to_y);
677 rect.w = (to_x - from_x + 1);
678 rect.h = (to_y - from_y + 1);
680 if (dst_bitmap == backbuffer || dst_bitmap == window)
682 rect.x += video_xoffset;
683 rect.y += video_yoffset;
686 SDL_FillRect(surface, &rect, color);
689 void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
690 int to_x, int to_y, Uint32 color)
692 if (dst_bitmap == backbuffer || dst_bitmap == window)
694 from_x += video_xoffset;
695 from_y += video_yoffset;
696 to_x += video_xoffset;
697 to_y += video_yoffset;
700 sge_Line(dst_bitmap->surface, from_x, from_y, to_x, to_y, color);
704 void SDLDrawLines(SDL_Surface *surface, struct XY *points,
705 int num_points, Uint32 color)
710 for (i = 0; i < num_points - 1; i++)
712 for (x = 0; x < line_width; x++)
714 for (y = 0; y < line_width; y++)
716 int dx = x - line_width / 2;
717 int dy = y - line_width / 2;
719 if ((x == 0 && y == 0) ||
720 (x == 0 && y == line_width - 1) ||
721 (x == line_width - 1 && y == 0) ||
722 (x == line_width - 1 && y == line_width - 1))
725 sge_Line(surface, points[i].x + dx, points[i].y + dy,
726 points[i+1].x + dx, points[i+1].y + dy, color);
733 Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
735 SDL_Surface *surface = src_bitmap->surface;
737 if (src_bitmap == backbuffer || src_bitmap == window)
743 switch (surface->format->BytesPerPixel)
745 case 1: /* assuming 8-bpp */
747 return *((Uint8 *)surface->pixels + y * surface->pitch + x);
751 case 2: /* probably 15-bpp or 16-bpp */
753 return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
757 case 3: /* slow 24-bpp mode; usually not used */
759 /* does this work? */
760 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
764 shift = surface->format->Rshift;
765 color |= *(pix + shift / 8) >> shift;
766 shift = surface->format->Gshift;
767 color |= *(pix + shift / 8) >> shift;
768 shift = surface->format->Bshift;
769 color |= *(pix + shift / 8) >> shift;
775 case 4: /* probably 32-bpp */
777 return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
786 /* ========================================================================= */
787 /* The following functions were taken from the SGE library */
788 /* (SDL Graphics Extension Library) by Anders Lindström */
789 /* http://www.etek.chalmers.se/~e8cal1/sge/index.html */
790 /* ========================================================================= */
792 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
794 if (x >= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1)
796 switch (surface->format->BytesPerPixel)
801 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
807 /* Probably 15-bpp or 16-bpp */
808 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
814 /* Slow 24-bpp mode, usually not used */
818 /* Gack - slow, but endian correct */
819 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
820 shift = surface->format->Rshift;
821 *(pix+shift/8) = color>>shift;
822 shift = surface->format->Gshift;
823 *(pix+shift/8) = color>>shift;
824 shift = surface->format->Bshift;
825 *(pix+shift/8) = color>>shift;
831 /* Probably 32-bpp */
832 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
839 void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
840 Uint8 R, Uint8 G, Uint8 B)
842 _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B));
845 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
847 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
850 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
852 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
855 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
860 /* Gack - slow, but endian correct */
861 pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
862 shift = surface->format->Rshift;
863 *(pix+shift/8) = color>>shift;
864 shift = surface->format->Gshift;
865 *(pix+shift/8) = color>>shift;
866 shift = surface->format->Bshift;
867 *(pix+shift/8) = color>>shift;
870 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
872 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
875 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
877 switch (dest->format->BytesPerPixel)
880 *((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
884 *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
888 _PutPixel24(dest,x,y,color);
892 *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
897 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
899 if (SDL_MUSTLOCK(surface))
901 if (SDL_LockSurface(surface) < 0)
907 _PutPixel(surface, x, y, color);
909 if (SDL_MUSTLOCK(surface))
911 SDL_UnlockSurface(surface);
915 void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y,
916 Uint8 r, Uint8 g, Uint8 b)
918 sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, r, g, b));
921 Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y)
923 if (y >= 0 && y <= dest->h - 1)
925 switch (dest->format->BytesPerPixel)
928 return y*dest->pitch;
932 return y*dest->pitch/2;
936 return y*dest->pitch;
940 return y*dest->pitch/4;
948 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
950 if (x >= 0 && x <= surface->w - 1 && ypitch >= 0)
952 switch (surface->format->BytesPerPixel)
957 *((Uint8 *)surface->pixels + ypitch + x) = color;
963 /* Probably 15-bpp or 16-bpp */
964 *((Uint16 *)surface->pixels + ypitch + x) = color;
970 /* Slow 24-bpp mode, usually not used */
974 /* Gack - slow, but endian correct */
975 pix = (Uint8 *)surface->pixels + ypitch + x*3;
976 shift = surface->format->Rshift;
977 *(pix+shift/8) = color>>shift;
978 shift = surface->format->Gshift;
979 *(pix+shift/8) = color>>shift;
980 shift = surface->format->Bshift;
981 *(pix+shift/8) = color>>shift;
987 /* Probably 32-bpp */
988 *((Uint32 *)surface->pixels + ypitch + x) = color;
995 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1000 if (SDL_MUSTLOCK(Surface))
1002 if (SDL_LockSurface(Surface) < 0)
1015 /* Do the clipping */
1016 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1020 if (x2 > Surface->w - 1)
1021 x2 = Surface->w - 1;
1028 SDL_FillRect(Surface, &l, Color);
1030 if (SDL_MUSTLOCK(Surface))
1032 SDL_UnlockSurface(Surface);
1036 void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y,
1037 Uint8 R, Uint8 G, Uint8 B)
1039 sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B));
1042 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
1053 /* Do the clipping */
1054 if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0)
1058 if (x2 > Surface->w - 1)
1059 x2 = Surface->w - 1;
1066 SDL_FillRect(Surface, &l, Color);
1069 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1074 if (SDL_MUSTLOCK(Surface))
1076 if (SDL_LockSurface(Surface) < 0)
1089 /* Do the clipping */
1090 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1094 if (y2 > Surface->h - 1)
1095 y2 = Surface->h - 1;
1102 SDL_FillRect(Surface, &l, Color);
1104 if (SDL_MUSTLOCK(Surface))
1106 SDL_UnlockSurface(Surface);
1110 void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2,
1111 Uint8 R, Uint8 G, Uint8 B)
1113 sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B));
1116 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
1127 /* Do the clipping */
1128 if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0)
1132 if (y2 > Surface->h - 1)
1133 y2 = Surface->h - 1;
1140 SDL_FillRect(Surface, &l, Color);
1143 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1,
1144 Sint16 x2, Sint16 y2, Uint32 Color,
1145 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1148 Sint16 dx, dy, sdx, sdy, x, y, px, py;
1153 sdx = (dx < 0) ? -1 : 1;
1154 sdy = (dy < 0) ? -1 : 1;
1166 for (x = 0; x < dx; x++)
1168 Callback(Surface, px, py, Color);
1182 for (y = 0; y < dy; y++)
1184 Callback(Surface, px, py, Color);
1198 void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1,
1199 Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B,
1200 void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y,
1203 sge_DoLine(Surface, X1, Y1, X2, Y2,
1204 SDL_MapRGB(Surface->format, R, G, B), Callback);
1207 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
1210 if (SDL_MUSTLOCK(Surface))
1212 if (SDL_LockSurface(Surface) < 0)
1217 sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel);
1219 /* unlock the display */
1220 if (SDL_MUSTLOCK(Surface))
1222 SDL_UnlockSurface(Surface);
1226 void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2,
1227 Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1229 sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B));
1232 void SDLPutPixel(Bitmap *dst_bitmap, int x, int y, Pixel pixel)
1234 if (dst_bitmap == backbuffer || dst_bitmap == window)
1240 sge_PutPixel(dst_bitmap->surface, x, y, pixel);
1245 -----------------------------------------------------------------------------
1246 quick (no, it's slow) and dirty hack to "invert" rectangle inside SDL surface
1247 -----------------------------------------------------------------------------
1250 void SDLInvertArea(Bitmap *bitmap, int src_x, int src_y,
1251 int width, int height, Uint32 color)
1255 for (y = src_y; y < src_y + height; y++)
1257 for (x = src_x; x < src_x + width; x++)
1259 Uint32 pixel = SDLGetPixel(bitmap, x, y);
1261 SDLPutPixel(bitmap, x, y, pixel == BLACK_PIXEL ? color : BLACK_PIXEL);
1266 void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
1267 int src_x, int src_y, int width, int height,
1268 int dst_x, int dst_y)
1272 for (y = 0; y < height; y++)
1274 for (x = 0; x < width; x++)
1276 Uint32 pixel = SDLGetPixel(src_bitmap, src_x + x, src_y + y);
1278 if (pixel != BLACK_PIXEL)
1279 SDLPutPixel(dst_bitmap, dst_x + x, dst_y + y, BLACK_PIXEL);
1285 /* ========================================================================= */
1286 /* The following functions were taken from the SDL_gfx library version 2.0.3 */
1287 /* (Rotozoomer) by Andreas Schiffler */
1288 /* http://www.ferzkopp.net/Software/SDL_gfx-2.0/index.html */
1289 /* ========================================================================= */
1292 -----------------------------------------------------------------------------
1295 zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
1296 -----------------------------------------------------------------------------
1307 int zoomSurfaceRGBA_scaleDownBy2(SDL_Surface *src, SDL_Surface *dst)
1310 tColorRGBA *sp, *csp, *dp;
1314 sp = csp = (tColorRGBA *) src->pixels;
1315 dp = (tColorRGBA *) dst->pixels;
1316 sgap = src->pitch - src->w * 4;
1317 dgap = dst->pitch - dst->w * 4;
1319 for (y = 0; y < dst->h; y++)
1323 for (x = 0; x < dst->w; x++)
1325 tColorRGBA *sp0 = sp;
1326 tColorRGBA *sp1 = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
1327 tColorRGBA *sp00 = &sp0[0];
1328 tColorRGBA *sp01 = &sp0[1];
1329 tColorRGBA *sp10 = &sp1[0];
1330 tColorRGBA *sp11 = &sp1[1];
1333 /* create new color pixel from all four source color pixels */
1334 new.r = (sp00->r + sp01->r + sp10->r + sp11->r) / 4;
1335 new.g = (sp00->g + sp01->g + sp10->g + sp11->g) / 4;
1336 new.b = (sp00->b + sp01->b + sp10->b + sp11->b) / 4;
1337 new.a = (sp00->a + sp01->a + sp10->a + sp11->a) / 4;
1342 /* advance source pointers */
1345 /* advance destination pointer */
1349 /* advance source pointer */
1350 csp = (tColorRGBA *) ((Uint8 *) csp + 2 * src->pitch);
1352 /* advance destination pointers */
1353 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1359 int zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst)
1361 int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1362 tColorRGBA *sp, *csp, *dp;
1365 /* use specialized zoom function when scaling down to exactly half size */
1366 if (src->w == 2 * dst->w &&
1367 src->h == 2 * dst->h)
1368 return zoomSurfaceRGBA_scaleDownBy2(src, dst);
1370 /* variable setup */
1371 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
1372 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
1374 /* allocate memory for row increments */
1375 sax = (int *)checked_malloc((dst->w + 1) * sizeof(Uint32));
1376 say = (int *)checked_malloc((dst->h + 1) * sizeof(Uint32));
1378 /* precalculate row increments */
1381 for (x = 0; x <= dst->w; x++)
1391 for (y = 0; y <= dst->h; y++)
1400 sp = csp = (tColorRGBA *) src->pixels;
1401 dp = (tColorRGBA *) dst->pixels;
1402 sgap = src->pitch - src->w * 4;
1403 dgap = dst->pitch - dst->w * 4;
1406 for (y = 0; y < dst->h; y++)
1411 for (x = 0; x < dst->w; x++)
1416 /* advance source pointers */
1418 sp += (*csax >> 16);
1420 /* advance destination pointer */
1424 /* advance source pointer */
1426 csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
1428 /* advance destination pointers */
1429 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
1439 -----------------------------------------------------------------------------
1442 zoomes 8 bit palette/Y 'src' surface to 'dst' surface
1443 -----------------------------------------------------------------------------
1446 int zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst)
1448 Uint32 x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy;
1449 Uint8 *sp, *dp, *csp;
1452 /* variable setup */
1453 sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
1454 sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
1456 /* allocate memory for row increments */
1457 sax = (Uint32 *)checked_malloc(dst->w * sizeof(Uint32));
1458 say = (Uint32 *)checked_malloc(dst->h * sizeof(Uint32));
1460 /* precalculate row increments */
1463 for (x = 0; x < dst->w; x++)
1466 *csax = (csx >> 16);
1473 for (y = 0; y < dst->h; y++)
1476 *csay = (csy >> 16);
1483 for (x = 0; x < dst->w; x++)
1491 for (y = 0; y < dst->h; y++)
1498 sp = csp = (Uint8 *) src->pixels;
1499 dp = (Uint8 *) dst->pixels;
1500 dgap = dst->pitch - dst->w;
1504 for (y = 0; y < dst->h; y++)
1508 for (x = 0; x < dst->w; x++)
1513 /* advance source pointers */
1517 /* advance destination pointer */
1521 /* advance source pointer (for row) */
1522 csp += ((*csay) * src->pitch);
1525 /* advance destination pointers */
1536 -----------------------------------------------------------------------------
1539 Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface.
1540 'zoomx' and 'zoomy' are scaling factors for width and height.
1541 If the surface is not 8bit or 32bit RGBA/ABGR it will be converted
1542 into a 32bit RGBA format on the fly.
1543 -----------------------------------------------------------------------------
1546 SDL_Surface *zoomSurface(SDL_Surface *src, int dst_width, int dst_height)
1548 SDL_Surface *zoom_src = NULL;
1549 SDL_Surface *zoom_dst = NULL;
1550 boolean is_converted = FALSE;
1557 /* determine if source surface is 32 bit or 8 bit */
1558 is_32bit = (src->format->BitsPerPixel == 32);
1560 if (is_32bit || src->format->BitsPerPixel == 8)
1562 /* use source surface 'as is' */
1567 /* new source surface is 32 bit with a defined RGB ordering */
1568 zoom_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1569 0x000000ff, 0x0000ff00, 0x00ff0000, 0);
1570 SDL_BlitSurface(src, NULL, zoom_src, NULL);
1572 is_converted = TRUE;
1575 /* allocate surface to completely contain the zoomed surface */
1578 /* target surface is 32 bit with source RGBA/ABGR ordering */
1579 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 32,
1580 zoom_src->format->Rmask,
1581 zoom_src->format->Gmask,
1582 zoom_src->format->Bmask, 0);
1586 /* target surface is 8 bit */
1587 zoom_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dst_width, dst_height, 8,
1591 /* lock source surface */
1592 SDL_LockSurface(zoom_src);
1594 /* check which kind of surface we have */
1597 /* call the 32 bit transformation routine to do the zooming */
1598 zoomSurfaceRGBA(zoom_src, zoom_dst);
1603 for (i = 0; i < zoom_src->format->palette->ncolors; i++)
1604 zoom_dst->format->palette->colors[i] =
1605 zoom_src->format->palette->colors[i];
1606 zoom_dst->format->palette->ncolors = zoom_src->format->palette->ncolors;
1608 /* call the 8 bit transformation routine to do the zooming */
1609 zoomSurfaceY(zoom_src, zoom_dst);
1612 /* unlock source surface */
1613 SDL_UnlockSurface(zoom_src);
1615 /* free temporary surface */
1617 SDL_FreeSurface(zoom_src);
1619 /* return destination surface */
1623 void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
1625 SDL_Surface *sdl_surface_tmp;
1626 int dst_width = dst_bitmap->width;
1627 int dst_height = dst_bitmap->height;
1629 /* throw away old destination surface */
1630 SDL_FreeSurface(dst_bitmap->surface);
1632 /* create zoomed temporary surface from source surface */
1633 sdl_surface_tmp = zoomSurface(src_bitmap->surface, dst_width, dst_height);
1635 /* create native format destination surface from zoomed temporary surface */
1636 dst_bitmap->surface = SDL_DisplayFormat(sdl_surface_tmp);
1638 /* free temporary surface */
1639 SDL_FreeSurface(sdl_surface_tmp);
1643 /* ========================================================================= */
1644 /* load image to bitmap */
1645 /* ========================================================================= */
1647 Bitmap *SDLLoadImage(char *filename)
1649 Bitmap *new_bitmap = CreateBitmapStruct();
1650 SDL_Surface *sdl_image_tmp;
1652 /* load image to temporary surface */
1653 if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
1655 SetError("IMG_Load(): %s", SDL_GetError());
1660 UPDATE_BUSY_STATE();
1662 /* create native non-transparent surface for current image */
1663 if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1665 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1670 UPDATE_BUSY_STATE();
1672 /* create native transparent surface for current image */
1673 SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
1674 SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
1675 if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
1677 SetError("SDL_DisplayFormat(): %s", SDL_GetError());
1682 UPDATE_BUSY_STATE();
1684 /* free temporary surface */
1685 SDL_FreeSurface(sdl_image_tmp);
1687 new_bitmap->width = new_bitmap->surface->w;
1688 new_bitmap->height = new_bitmap->surface->h;
1694 /* ------------------------------------------------------------------------- */
1695 /* custom cursor fuctions */
1696 /* ------------------------------------------------------------------------- */
1698 static SDL_Cursor *create_cursor(struct MouseCursorInfo *cursor_info)
1700 return SDL_CreateCursor(cursor_info->data, cursor_info->mask,
1701 cursor_info->width, cursor_info->height,
1702 cursor_info->hot_x, cursor_info->hot_y);
1705 void SDLSetMouseCursor(struct MouseCursorInfo *cursor_info)
1707 static struct MouseCursorInfo *last_cursor_info = NULL;
1708 static struct MouseCursorInfo *last_cursor_info2 = NULL;
1709 static SDL_Cursor *cursor_default = NULL;
1710 static SDL_Cursor *cursor_current = NULL;
1712 /* if invoked for the first time, store the SDL default cursor */
1713 if (cursor_default == NULL)
1714 cursor_default = SDL_GetCursor();
1716 /* only create new cursor if cursor info (custom only) has changed */
1717 if (cursor_info != NULL && cursor_info != last_cursor_info)
1719 cursor_current = create_cursor(cursor_info);
1720 last_cursor_info = cursor_info;
1723 /* only set new cursor if cursor info (custom or NULL) has changed */
1724 if (cursor_info != last_cursor_info2)
1725 SDL_SetCursor(cursor_info ? cursor_current : cursor_default);
1727 last_cursor_info2 = cursor_info;
1731 /* ========================================================================= */
1732 /* audio functions */
1733 /* ========================================================================= */
1735 void SDLOpenAudio(void)
1737 if (!strEqual(setup.system.sdl_audiodriver, ARG_DEFAULT))
1738 SDL_putenv(getStringCat2("SDL_AUDIODRIVER=", setup.system.sdl_audiodriver));
1740 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1742 Error(ERR_WARN, "SDL_InitSubSystem() failed: %s", SDL_GetError());
1746 if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, MIX_DEFAULT_FORMAT,
1747 AUDIO_NUM_CHANNELS_STEREO,
1748 setup.system.audio_fragment_size) < 0)
1750 Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
1754 audio.sound_available = TRUE;
1755 audio.music_available = TRUE;
1756 audio.loops_available = TRUE;
1757 audio.sound_enabled = TRUE;
1759 /* set number of available mixer channels */
1760 audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
1761 audio.music_channel = MUSIC_CHANNEL;
1762 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
1764 Mixer_InitChannels();
1767 void SDLCloseAudio(void)
1770 Mix_HaltChannel(-1);
1773 SDL_QuitSubSystem(SDL_INIT_AUDIO);
1777 /* ========================================================================= */
1778 /* event functions */
1779 /* ========================================================================= */
1781 void SDLNextEvent(Event *event)
1783 SDL_WaitEvent(event);
1785 if (event->type == EVENT_BUTTONPRESS ||
1786 event->type == EVENT_BUTTONRELEASE)
1788 if (((ButtonEvent *)event)->x > video_xoffset)
1789 ((ButtonEvent *)event)->x -= video_xoffset;
1791 ((ButtonEvent *)event)->x = 0;
1792 if (((ButtonEvent *)event)->y > video_yoffset)
1793 ((ButtonEvent *)event)->y -= video_yoffset;
1795 ((ButtonEvent *)event)->y = 0;
1797 else if (event->type == EVENT_MOTIONNOTIFY)
1799 if (((MotionEvent *)event)->x > video_xoffset)
1800 ((MotionEvent *)event)->x -= video_xoffset;
1802 ((MotionEvent *)event)->x = 0;
1803 if (((MotionEvent *)event)->y > video_yoffset)
1804 ((MotionEvent *)event)->y -= video_yoffset;
1806 ((MotionEvent *)event)->y = 0;
1810 void SDLHandleWindowManagerEvent(Event *event)
1812 #if defined(PLATFORM_WIN32)
1813 SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
1814 SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
1816 if (syswmmsg->msg == WM_DROPFILES)
1818 HDROP hdrop = (HDROP)syswmmsg->wParam;
1821 printf("::: SDL_SYSWMEVENT:\n");
1823 num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
1825 for (i = 0; i < num_files; i++)
1827 int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
1828 char buffer[buffer_len + 1];
1830 DragQueryFile(hdrop, i, buffer, buffer_len + 1);
1832 printf("::: - '%s'\n", buffer);
1835 DragFinish((HDROP)syswmmsg->wParam);
1841 /* ========================================================================= */
1842 /* joystick functions */
1843 /* ========================================================================= */
1845 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
1846 static int sdl_js_axis[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1847 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1849 static boolean SDLOpenJoystick(int nr)
1851 if (nr < 0 || nr > MAX_PLAYERS)
1854 return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
1857 static void SDLCloseJoystick(int nr)
1859 if (nr < 0 || nr > MAX_PLAYERS)
1862 SDL_JoystickClose(sdl_joystick[nr]);
1865 static boolean SDLCheckJoystickOpened(int nr)
1867 if (nr < 0 || nr > MAX_PLAYERS)
1870 return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
1873 void HandleJoystickEvent(Event *event)
1877 case SDL_JOYAXISMOTION:
1878 if (event->jaxis.axis < 2)
1879 sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
1882 case SDL_JOYBUTTONDOWN:
1883 if (event->jbutton.button < 2)
1884 sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
1887 case SDL_JOYBUTTONUP:
1888 if (event->jbutton.button < 2)
1889 sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
1897 void SDLInitJoysticks()
1899 static boolean sdl_joystick_subsystem_initialized = FALSE;
1900 boolean print_warning = !sdl_joystick_subsystem_initialized;
1903 if (!sdl_joystick_subsystem_initialized)
1905 sdl_joystick_subsystem_initialized = TRUE;
1907 if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
1909 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
1914 for (i = 0; i < MAX_PLAYERS; i++)
1916 /* get configured joystick for this player */
1917 char *device_name = setup.input[i].joy.device_name;
1918 int joystick_nr = getJoystickNrFromDeviceName(device_name);
1920 if (joystick_nr >= SDL_NumJoysticks())
1922 if (setup.input[i].use_joystick && print_warning)
1923 Error(ERR_WARN, "cannot find joystick %d", joystick_nr);
1928 /* misuse joystick file descriptor variable to store joystick number */
1929 joystick.fd[i] = joystick_nr;
1931 if (joystick_nr == -1)
1934 /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
1935 if (SDLCheckJoystickOpened(joystick_nr))
1936 SDLCloseJoystick(joystick_nr);
1938 if (!setup.input[i].use_joystick)
1941 if (!SDLOpenJoystick(joystick_nr))
1944 Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
1949 joystick.status = JOYSTICK_ACTIVATED;
1953 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1955 if (nr < 0 || nr >= MAX_PLAYERS)
1959 *x = sdl_js_axis[nr][0];
1961 *y = sdl_js_axis[nr][1];
1964 *b1 = sdl_js_button[nr][0];
1966 *b2 = sdl_js_button[nr][1];
1971 #endif /* TARGET_SDL */